EMAN2
emdata_sparx.cpp
Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Pawel A.Penczek, 09/09/2006 (Pawel.A.Penczek@uth.tmc.edu)
00007  * Copyright (c) 2000-2006 The University of Texas - Houston Medical School
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 <stack>
00037 #include "ctf.h"
00038 #include "emdata.h"
00039 #include <iostream>
00040 #include <cmath>
00041 #include <cstring>
00042 
00043 #include <gsl/gsl_sf_bessel.h>
00044 #include <gsl/gsl_errno.h>
00045 #include <vector>
00046 #include <boost/shared_ptr.hpp>
00047 
00048 using boost::shared_ptr;
00049 using std::vector;
00050 using std::cout;
00051 using namespace EMAN;
00052 using namespace std;
00053 
00054 EMData *EMData::real2FH(float OverSamplekB) // PRB
00055 {
00056         int nx        = get_xsize();
00057         int ny        = get_ysize();
00058         int nz        = get_zsize();
00059         int Center  = (int) floor( (nx+1.0)/2.0 +.01);
00060 #ifdef DEBUG
00061         printf("nx=%d, ny=%d, nz=%d Center=%d\n", nx,ny,nz, Center);
00062 #endif  //DEBUG
00063         float ScalFactor=4.1f;
00064         gsl_set_error_handler_off();
00065 
00066         if ( (nz==1) && (nx==ny) && (!is_complex())  && (Center*2)==(nx+1)){
00067 #ifdef DEBUG
00068                 printf("entered if \n");fflush(stdout);
00069 #endif  //DEBUG
00070 //              MArray2D ImBW = this ->get_2dview();
00071                 EMData*  ImBW = this ;
00072                 int Size=nx;
00073                 int iMax = (int) floor( (Size-1.0)/2 +.01);
00074                 int CountMax = (iMax+2)*(iMax+1)/2;
00075                 int *PermMatTr  = new int[CountMax];
00076                 float *RValsSorted  = new float[CountMax];
00077                 float *weightofkValsSorted = new float[CountMax];
00078                 int *SizeReturned = new int[1];
00079                 Util::Radialize(PermMatTr, RValsSorted,weightofkValsSorted,Size, SizeReturned);
00080                 int RIntMax= SizeReturned[0];
00081 
00082                 int mMax = (int) floor( ScalFactor*RValsSorted[RIntMax-1]+10.0);
00083 
00084                 int kIntMax=2+ (int) floor( RValsSorted[RIntMax-1]*OverSamplekB);
00085                 float *kVec2Use= new float[kIntMax];
00086                 for (int kk=0; kk<kIntMax; kk++){
00087                         kVec2Use[kk]= ((float) kk)/OverSamplekB;}
00088 
00089                 float *krVec= new float[kIntMax*RIntMax];
00090                 int Count=0;
00091                 for (int jk=0; jk<kIntMax; jk++ ){
00092                         for (int jR=0; jR<RIntMax; jR++ ){
00093                                 krVec[Count]=2.0f*M_PI*RValsSorted[jR]
00094                                         *kVec2Use[jk]/( (float) Size);
00095                                 Count++;
00096 //                              printf("krVec[%d]=%f \n",Count,krVec[Count-1]);fflush(stdout);
00097                 }} // end building up krVec
00098                 float krVecMin= kVec2Use[1]*RValsSorted[1];
00099                 float krVecMax = krVec[kIntMax*RIntMax-1]+krVecMin;
00100                 int Number2Use = (int) floor(OverSamplekB*krVecMax+1.0);
00101                 float *krVec2Use      = new float[Number2Use+1];
00102                 float *sampledBesselJ = new float[Number2Use+1];
00103 #ifdef DEBUG
00104                 printf("Size=%d, iMax=%d, SizeReturned=%d, RIntMax=%d, \n"
00105                       "mMax=%d, kIntMax=%d, krVecMin=%f, krVecMax=%f,  Number2Use=%d  \n\n",
00106                         Size, iMax, SizeReturned[0], RIntMax, mMax, kIntMax,
00107                                krVecMin,krVecMax,Number2Use);fflush(stdout);
00108 #endif  //DEBUG
00109                 for (int jkr=0; jkr<= Number2Use; jkr++) {
00110                         krVec2Use[jkr] =((float)jkr)*krVecMax/
00111                                     ((float)Number2Use);
00112 //                      printf("krVec2Use[%d]=%f \n",jkr+1,krVec2Use[jkr]);fflush(stdout);
00113                 }
00114 
00115 
00116                 EMData* rhoOfkmB = copy(); // glibc detected ** malloc(); memory corruption
00117 //              printf("finished O \n");fflush(stdout);
00118                 rhoOfkmB->set_size(2*(mMax+1),kIntMax);
00119                 rhoOfkmB->to_zero();
00120 //              MArray2D rhoOfkmB = FH->get_2dview();
00121 
00122                 int CenterM= Center-1; // to convert from Matlab to C++
00123                 std::complex <float> *rhoOfRandmTemp = new std::complex <float>[RIntMax];
00124                 std::complex <float> rhoTemp;
00125 
00126                 int PCount=0;
00127 
00128                 for (int m=0; m <=mMax; m++){
00129                 //    if m==mMax, tic, end
00130                         std::complex <float> tempF(0.0f,-1.0f);
00131                         std::complex <float> overallFactor = (std::complex <float>) pow(tempF,m);  //(-i)^m ;  % I dropped off the 2 pi
00132                         std::complex <float> mI(0.0f,static_cast<float>(m));
00133                         for (int ii=0; ii< RIntMax; ii++){ rhoOfRandmTemp[ii]=0;}
00134                         for (int jx=0; jx <Center ; jx++) {
00135                                 for (int jy=0; jy <=jx; jy++){
00136                                         float fjx=float(jx);
00137                                         float fjy= float(jy);
00138                                         Count = (jx*jx+jx)/2 +1 +jy;
00139                                         PCount = PermMatTr[Count-1];
00140 //                                      printf("PCount=%d, Count=%d \n", PCount, Count);
00141                                         rhoTemp =  std::complex <float> ((*ImBW)(CenterM+jx,CenterM+jy)) *exp(mI* std::complex <float> (atan2(+fjy,+fjx)))
00142                                          +   std::complex <float> ((*ImBW)(CenterM+jx,CenterM-jy)) * exp(mI*std::complex <float>(atan2(-fjy,+fjx)))
00143                                          +   std::complex <float> ((*ImBW)(CenterM-jx,CenterM+jy)) * exp(mI*std::complex <float>(atan2(+fjy,-fjx)))
00144                                          +   std::complex <float> ((*ImBW)(CenterM-jx,CenterM-jy)) * exp(mI*std::complex <float>(atan2(-fjy,-fjx)))
00145                                          +   std::complex <float> ((*ImBW)(CenterM+jy,CenterM+jx)) * exp(mI*std::complex <float>(atan2(+fjx,+fjy)))
00146                                          +   std::complex <float> ((*ImBW)(CenterM+jy,CenterM-jx)) * exp(mI*std::complex <float>(atan2(-fjx,+fjy)))
00147                                          +   std::complex <float> ((*ImBW)(CenterM-jy,CenterM+jx)) * exp(mI*std::complex <float>(atan2(+fjx,-fjy)))
00148                                          +   std::complex <float> ((*ImBW)(CenterM-jy,CenterM-jx)) * exp(mI*std::complex <float>(atan2(-fjx,-fjy)));
00149                                         if (((jx+jy)==0)&&(m>0) ){
00150                                                 rhoTemp=0;}
00151 //                      printf("m=%d, jx=%d, jy=%d, rhoTemp= %f+ %f i\n", m,jx,jy,(rhoTemp.real()), (rhoTemp.imag()) );fflush(stdout);
00152 //                      {" %f,%f %f,%f %f,%f %f,%f \n",
00153 //                             ImBW[CenterM+jx][CenterM+jy] ,ImBW[CenterM+jx][CenterM-jy]  , ImBW[CenterM-jx][CenterM+jy] ,ImBW[CenterM-jx][CenterM-jy],
00154 //                             ImBW[CenterM+jy][CenterM+jx] ,ImBW[CenterM+jy][CenterM-jx]  , ImBW[CenterM-jy][CenterM+jx] ,ImBW[CenterM-jy][CenterM-jx]);
00155                                         rhoOfRandmTemp[PCount-1] +=
00156                                             rhoTemp/((float)pow(2.,(int)( (jx==0)  +(jy==0)+ (jy==jx))));
00157 
00158                         }} // end walk through lattice
00159 //                      printf("\n m=%d rhoOfRandmTemp" ,m  );fflush(stdout);
00160 //                      for (int ss=0; ss< RIntMax; ss++){
00161 //                              printf(" %3.1f+ %3.1fi \t",(rhoOfRandmTemp[ss].real()), (rhoOfRandmTemp[ss].imag())   );fflush(stdout);}
00162 
00163 // calculate product
00164 
00165                         float tempp;
00166 //                      printf("\n m=%d sampledBesselJ" ,m  );fflush(stdout);
00167                         for (int st=0; st<= Number2Use; st++){
00168                                 tempp=krVec2Use[st];
00169                                 sampledBesselJ[st] = static_cast<float>(gsl_sf_bessel_Jn(m,tempp));
00170 //                              printf(" %3.2f  \t",sampledBesselJ[st]   );fflush(stdout);
00171                         } // good so far
00172 
00173 //                      sampledBesselJ  = BesselJ(m,krVec2Use);
00174                         float *tempMB = new float [kIntMax*RIntMax];
00175                         Util::spline_mat(krVec2Use, sampledBesselJ, Number2Use+1,krVec,tempMB,kIntMax*RIntMax );
00176 //                      printf("\n tempMB m=%d y2" ,m  );fflush(stdout);
00177                         std::complex <float> *rowV = new std::complex <float> [kIntMax];
00178 
00179 //                      for (int st=0; st< kIntMax*RIntMax; st++){printf(" %3.2f  \t",tempMB[st]   );fflush(stdout);} // good so far
00180 
00181 //   tempMB,krVec is in blocks of RIntMax
00182 //                      printf("\n rowV m=%d \t" ,m  );fflush(stdout);
00183                         for (int st=0; st < kIntMax; st++) {
00184                                         rowV[st]=0;
00185                                         for (int sv=0; sv < RIntMax; sv++) {
00186                                                 rowV[st]+=  rhoOfRandmTemp[sv] *tempMB[sv+st*RIntMax];
00187                                         }
00188                                          rowV[st] *= overallFactor;
00189 //                                      printf(" %1.3f +%1.3fi \t" , rowV[st].real(), rowV[st].imag() );fflush(stdout);
00190                         }
00191                         for (int st=0; st < kIntMax; st++) {
00192                                 (*rhoOfkmB)(2*m  ,st) = rowV[st].real();
00193                                 (*rhoOfkmB)(2*m+1,st) = rowV[st].imag();
00194                         }
00195 //                      rowV = overallFactor*rhoOfRandmTemp*tempMBB;
00196 //                      rhoOfkmB(m+1,1:kIntMax) = rowV ;
00197 
00198 //                      if m==mMax, toc, end
00199 
00200 // %'final interpolation'
00201 // %     rhoOfkm(m+1,:) = spline(kVec2Use,rowV,RValsSorted); ;
00202 
00203 
00204                 } // ends m loop
00205 
00206                 update();
00207                 rhoOfkmB-> update();
00208                 rhoOfkmB->set_complex(true);
00209                 if(rhoOfkmB->get_ysize()==1 && rhoOfkmB->get_zsize()==1) {
00210                         rhoOfkmB->set_complex_x(true);
00211                 }
00212         rhoOfkmB->set_ri(true);
00213         rhoOfkmB->set_FH(true);
00214         rhoOfkmB->set_fftodd(true);
00215                 return rhoOfkmB;
00216         } else {
00217                 LOGERR("2D real square odd image expected.");
00218                 throw ImageFormatException("2D real square odd image expected.");
00219         }
00220 }
00221 
00222 EMData *EMData::copy_empty_head() const
00223 {
00224         ENTERFUNC;
00225         EMData *ret = new EMData();
00226         ret->attr_dict = attr_dict;
00227         ret->flags = flags;
00228         ret->all_translation = all_translation;
00229         ret->path = path;
00230         ret->pathnum = pathnum;
00231 
00232 // should these be here? d.woolford I did not comment them out, merely place them here (commented out) to draw attention
00233 //      ret->xoff = xoff;
00234 //      ret->yoff = yoff;
00235 //      ret->zoff = zoff;
00236 //      ret->changecount = changecount;
00237 
00238         ret->update();
00239 
00240         EXITFUNC;
00241         return ret;
00242 }
00243 
00244 
00245 EMData *EMData::FH2F(int Size, float OverSamplekB, int IntensityFlag)  // PRB
00246 {
00247         int nx=get_xsize();
00248         int ny=get_ysize();
00249         int nz=get_zsize();
00250         float ScalFactor=4.1f;
00251         int Center = (int) floor((Size+1.0)/2.0 +.1);
00252         int CenterM= Center-1;
00253         int CountMax = (Center+1)*Center/2;
00254 
00255         int     *PermMatTr           = new int[CountMax];
00256         float  *RValsSorted         = new float[CountMax];
00257         float  *weightofkValsSorted = new float[CountMax];
00258         int      *SizeReturned        = new int[1];
00259         Util::Radialize(PermMatTr, RValsSorted,weightofkValsSorted,Size, SizeReturned);
00260         int RIntMax= SizeReturned[0];  // replaces CountMax; the latter should now never be used.
00261 //      kVec2Use = (0:1/OverSamplek:RValsSorted(RIntMax)+1/OverSamplek); %   in pixels  (otherwise need *2*pi/Size)
00262 
00263         int   mMax = (int) floor( ScalFactor*RValsSorted[RIntMax-1]+10.0);
00264 
00265         int    kIntMax  = 2+ (int) floor( RValsSorted[RIntMax-1]*OverSamplekB);
00266         float *kVec2Use = new float[kIntMax];
00267         for (int kk=0; kk<kIntMax; kk++){
00268                 kVec2Use[kk]= ((float) kk)/OverSamplekB;}
00269 
00270 
00271 
00272 #ifdef DEBUG
00273         printf("nx=%d, ny=%d, nz=%d Center=%d mMax=%d CountMax=%d kIntMax=%d Centerm1=%d  Size=%d\n\n",
00274             nx,ny,nz, Center, mMax, CountMax, kIntMax,  CenterM, Size);
00275 #endif
00276 
00277         EMData * rhoOfkmB = this;
00278 
00279 //     check mMax's are equal
00280 //     check kIntMax's are equal
00281 
00282         if ( (nx==2*(mMax+1)) && (ny==kIntMax) &&(nz==1) ) {
00283 
00284         EMData *rhoOfkandm = copy();
00285         rhoOfkandm ->set_size(2*(mMax+1),RIntMax);
00286         rhoOfkandm ->to_zero();
00287 //      MArray2D rhoOfkandm = tempCopy->get_2dview();  % Just changed Nov 20 2005
00288 //      printf("rhoOfkandm \n");
00289         for (int mr=0; mr <2*(mMax+1); mr++){
00290                 float *Row= new float[kIntMax];
00291                 float *RowOut= new float[RIntMax];
00292                 for (int ii=0; ii<kIntMax; ii++){ Row[ii]=(*rhoOfkmB)(mr,ii);}
00293                 Util::spline_mat(kVec2Use, Row, kIntMax,  RValsSorted, RowOut, RIntMax );
00294                 for (int ii=0; ii<RIntMax; ii++){
00295                         (*rhoOfkandm)(mr,ii) = RowOut[ii];
00296 //                      printf("%3.3f  ",RowOut[ii]);
00297                 }
00298 //              printf(" \n");
00299 //              rhoOfkandm(m+1,:) = spline(kVec2Use,rhoOfkmBReIm(m+1,1:kIntMax),kIntMax,RValsSorted);
00300         }
00301         rhoOfkandm ->update();
00302 
00303 //          So far so good PRB ....
00304 
00305         EMData* outCopy = rhoOfkandm ->copy();
00306         outCopy->set_size(2*Size,Size,1);
00307         outCopy->to_zero();
00308 //      MArray2D ImBWfftRm = outCopy->get_2dview();
00309 
00310         int Count =0, kInt, kIntm1;
00311         std::complex <float> ImfTemp;
00312         float kValue, thetak;
00313 
00314         for (int jkx=0; jkx <Center; jkx++) { // These index the outputted picture
00315                 for (int jky=0; jky<=jkx; jky++){
00316                         kInt = PermMatTr[Count];
00317                         kIntm1= kInt-1;
00318                         Count++;
00319                         float fjkx = float(jkx);
00320                         float fjky = float(jky);
00321 
00322                         kValue = std::sqrt(fjkx*fjkx +  fjky*fjky )  ;
00323 //                      mMaxR= floor(ScalFactor*kValue +10);
00324 
00325  //                   How many copies
00326 
00327                         thetak = atan2(fjky,fjkx);
00328                         ImfTemp = (*rhoOfkandm)(0, kIntm1) ;
00329                         for (int mm= 1; mm <mMax;mm++) {  // The index for m
00330                                 std::complex <float> fact(0,-mm*thetak);
00331                                 std::complex <float> expfact= exp(fact);
00332                                 std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1),(*rhoOfkandm)(2*mm+1,kIntm1));
00333                                 float mmFac = float(1-2*(mm%2));
00334                                 if (IntensityFlag==1){ mmFac=1;}
00335                                 ImfTemp +=   expfact * tempRho + mmFac  *conj(expfact*tempRho);//pow(float(-1),mm)
00336                         }
00337                         (*outCopy)(2*(CenterM+jkx),CenterM+jky)   = ImfTemp.real();
00338                         (*outCopy)(2*(CenterM+jkx)+1,CenterM+jky) = ImfTemp.imag();
00339 //                      printf("jkx=%d, jky=%d; %f + %f i \n",jkx,jky,ImfTemp.real(), ImfTemp.imag());
00340 
00341                         if (jky>0) {
00342                                 thetak = atan2(-fjky,fjkx);
00343                                 ImfTemp = (*rhoOfkandm)(0,kIntm1);
00344                                 for (int mm= 1; mm<mMax; mm++) { // The index for m
00345                                         std::complex <float> fact(0,-mm*thetak);
00346                                         std::complex <float> expfact= exp(fact);
00347                                         std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1), (*rhoOfkandm)(2*mm+1,kIntm1));
00348                                         float mmFac = float(1-2*(mm%2));
00349                                         if (IntensityFlag==1){ mmFac=1;}
00350                                         ImfTemp +=   expfact * tempRho +  mmFac  *conj(expfact*tempRho);
00351                                 }
00352                                 (*outCopy)(2*(CenterM+jkx),CenterM-jky)  = ImfTemp.real();
00353 
00354                                 (*outCopy)(2*(CenterM+jkx)+1,CenterM-jky) = ImfTemp.imag();
00355                         }
00356 
00357                         if (jkx>0) {
00358                                 thetak = atan2(fjky,-fjkx);
00359                                 ImfTemp = (*rhoOfkandm)(0,kIntm1);
00360                                 for (int mm= 1; mm<mMax; mm++) { // The index for m
00361                                         std::complex <float> fact(0,-mm*thetak);
00362                                         std::complex <float> expfact= exp(fact);
00363                                         std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1), (*rhoOfkandm)(2*mm+1,kIntm1));
00364                                         float mmFac = float(1-2*(mm%2));
00365                                         if (IntensityFlag==1){ mmFac=1;}
00366                                         ImfTemp +=   expfact * tempRho +  mmFac *conj(expfact*tempRho);
00367                                 }
00368                                 (*outCopy)(2*(CenterM-jkx)  ,CenterM+jky) = ImfTemp.real();
00369                                 (*outCopy)(2*(CenterM-jkx)+1,CenterM+jky) = ImfTemp.imag();
00370                         }
00371 
00372                         if (jkx>0 && jky>0) {
00373                                 thetak = atan2(-fjky,-fjkx);
00374                                 ImfTemp = (*rhoOfkandm)(0 , kIntm1);
00375                                 for (int mm= 1; mm<mMax; mm++) {  // The index for m
00376                                         std::complex <float> fact(0,-mm*thetak);
00377                                         std::complex <float> expfact= exp(fact);
00378                                         std::complex <float> tempRho( (*rhoOfkandm)(2*mm,kIntm1),(*rhoOfkandm)(2*mm+1,kIntm1) );
00379                                         float mmFac = float(1-2*(mm%2));
00380                                         if (IntensityFlag==1){ mmFac=1;}
00381                                         ImfTemp +=   expfact * tempRho +  mmFac *conj(expfact*tempRho);
00382                                 }
00383                                 (*outCopy)(2*(CenterM-jkx)  ,CenterM-jky) = ImfTemp.real();
00384                                 (*outCopy)(2*(CenterM-jkx)+1,CenterM-jky) = ImfTemp.imag();
00385                         }
00386 
00387                         if (jky< jkx) {
00388                                 thetak = atan2(fjkx,fjky);
00389                                 ImfTemp = (*rhoOfkandm)(0,kIntm1);
00390                                 for (int mm= 1; mm<mMax; mm++){ // The index for m
00391                                         std::complex <float> fact(0,-mm*thetak);
00392                                         std::complex <float> expfact= exp(fact);
00393                                         std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1),(*rhoOfkandm)(2*mm+1,kIntm1));
00394                                         float mmFac = float(1-2*(mm%2));
00395                                         if (IntensityFlag==1){ mmFac=1;}
00396                                         ImfTemp +=   expfact * tempRho +  mmFac *conj(expfact*tempRho);
00397                                 }
00398                                 (*outCopy)(2*(CenterM+jky)  ,CenterM+jkx) = ImfTemp.real();
00399                                 (*outCopy)(2*(CenterM+jky)+1,CenterM+jkx) = ImfTemp.imag();
00400 
00401                                 if (jky>0){
00402                                         thetak = atan2(fjkx,-fjky);
00403                                         ImfTemp = (*rhoOfkandm)(0, kIntm1);
00404                                         for (int mm= 1; mm <mMax; mm++) { // The index for m
00405                                                 std::complex <float> fact(0,-mm*thetak);
00406                                                 std::complex <float> expfact= exp(fact);
00407                                                 std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1),(*rhoOfkandm)(2*mm+1,kIntm1));
00408                                         float mmFac = float(1-2*(mm%2));
00409                                         if (IntensityFlag==1){ mmFac=1;}
00410                                                 ImfTemp +=  expfact * tempRho +  mmFac *conj(expfact*tempRho);
00411                                         }
00412                                         (*outCopy)(2*(CenterM-jky)  ,CenterM+jkx) = ImfTemp.real();
00413                                         (*outCopy)(2*(CenterM-jky)+1,CenterM+jkx) = ImfTemp.imag();
00414                                 }
00415 
00416                                  if (jkx>0) {
00417                                          thetak = atan2(-fjkx,fjky);
00418                                          ImfTemp = (*rhoOfkandm)(0,kIntm1);
00419                                         for (int mm= 1; mm <mMax; mm++) { // The index for m
00420                                                 std::complex <float> fact(0,-mm*thetak);
00421                                                 std::complex <float> expfact= exp(fact);
00422                                                 std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1),(*rhoOfkandm)(2*mm+1,kIntm1));
00423                                                 float mmFac = float(1-2*(mm%2));
00424                                                 if (IntensityFlag==1){ mmFac=1;}
00425                                                 ImfTemp +=  expfact * tempRho +  mmFac *conj(expfact*tempRho);
00426                                         }
00427                                         (*outCopy)(2*(CenterM+jky)  ,CenterM-jkx) = ImfTemp.real();
00428                                         (*outCopy)(2*(CenterM+jky)+1,CenterM-jkx) = ImfTemp.imag();
00429                                 }
00430 
00431                                 if (jkx>0 && jky>0) {
00432                                         thetak = atan2(-fjkx,-fjky);
00433                                         ImfTemp = (*rhoOfkandm)(0,kIntm1) ;
00434                                         for (int mm= 1; mm <mMax; mm++) { // The index for m
00435                                                 std::complex <float> fact(0,-mm*thetak);
00436                                                 std::complex <float> expfact= exp(fact);
00437                                                 std::complex <float> tempRho((*rhoOfkandm)(2*mm,kIntm1) ,(*rhoOfkandm)(2*mm+1,kIntm1) );
00438                                                 float mmFac = float(1-2*(mm%2));
00439                                                 if (IntensityFlag==1){ mmFac=1;}
00440                                                 ImfTemp +=  expfact * tempRho +  mmFac *conj(expfact*tempRho);
00441                                         }
00442                                         (*outCopy)(2*(CenterM-jky)  ,CenterM-jkx) = ImfTemp.real();
00443                                         (*outCopy)(2*(CenterM-jky)+1,CenterM-jkx) = ImfTemp.imag();
00444                                 }
00445                         } // ends jky <jkx
00446 
00447 
00448                 } // ends jky
00449         } // ends jkx
00450         outCopy->update();
00451         outCopy->set_complex(true);
00452         if(outCopy->get_ysize()==1 && outCopy->get_zsize()==1) outCopy->set_complex_x(true);
00453         outCopy->set_ri(true);
00454         outCopy->set_FH(false);
00455         outCopy->set_fftodd(true);
00456         outCopy->set_shuffled(true);
00457         return outCopy;
00458         } else {
00459                 LOGERR("can't be an FH image not this size");
00460                 throw ImageFormatException("something strange about this image: not a FH");
00461 
00462         }
00463 }  // ends FH2F
00464 
00465 
00466 EMData *EMData::FH2Real(int Size, float OverSamplekB, int)  // PRB
00467 {
00468         EMData* FFT= FH2F(Size,OverSamplekB,0);
00469         FFT->process_inplace("xform.fourierorigin.tocorner");
00470         EMData* eguess= FFT ->do_ift();
00471         return eguess;
00472 }  // ends FH2F
00473 
00474 float dist(int lnlen, const float* line_1, const float* line_2)
00475 {
00476         float dis2=0.0;
00477         for( int i=0; i < lnlen; ++i) {
00478                 float tmp = line_1[i] - line_2[i];
00479                 dis2 += tmp*tmp;
00480         }
00481         //return static_cast<float>(std::sqrt(dis2));
00482         return dis2;
00483 }
00484 
00485 float dist_r(int lnlen, const float* line_1, const float* line_2)
00486 {
00487         double dis2 = 0.0;
00488         for( int i=0; i < lnlen; ++i ) {
00489                 float tmp = line_1[lnlen-1-i] - line_2[i];
00490                 dis2 += tmp*tmp;
00491         }
00492         return static_cast<float>(std::sqrt(dis2));
00493 }
00494 
00495 /*
00496 float EMData::cm_euc(EMData* sinoj, int n1, int n2, float alpha1, float alpha2)
00497 {
00498     int lnlen = get_xsize();
00499 
00500         Assert( n1 >=0 && n1 < get_ysize() );
00501         Assert( n2 >=0 && n2 < get_ysize() );
00502         Assert( alpha1>=0.0 && alpha1 < 360.0 );
00503         Assert( alpha2>=0.0 && alpha2 < 360.0 );
00504 
00505         float* line_1 = get_data() + n1*lnlen;
00506         float* line_2 = sinoj->get_data() + n2*lnlen;
00507         float just = (alpha1-180.0f)*(alpha2-180.0f);
00508         if( just > 0.0 ) return dist(lnlen, line_1, line_2);
00509 
00510         if( just == 0.0 ) {
00511                 float dist_1 = dist(lnlen, line_1, line_2);
00512                 float dist_2 = dist_r(lnlen, line_1, line_2);
00513 #ifdef  _WIN32
00514                 return _cpp_min(dist_1, dist_2);
00515 #else
00516                 return std::min(dist_1, dist_2);
00517 #endif  //_WIN32
00518         }
00519 
00520         Assert( (alpha1-180.0)*(alpha2-180.0) < 0.0 );
00521         return dist_r(lnlen, line_1, line_2);
00522 }
00523 */
00524 
00525 float EMData::cm_euc(EMData* sinoj, int n1, int n2)
00526 {
00527     int lnlen = get_xsize();
00528     float* line_1 = get_data() + n1 * lnlen;
00529     float* line_2 = sinoj->get_data() + n2 * lnlen;
00530     return dist(lnlen, line_1, line_2);
00531 }
00532 
00533 EMData* EMData::rotavg() {
00534 
00535         ENTERFUNC;
00536 
00537         int rmax;
00538     EMData* ret = new EMData();
00539     vector<int> saved_offsets = get_array_offsets();
00540     vector<float> count;
00541 
00542         if (ny<2 && nz <2) {
00543                 LOGERR("No 1D images.");
00544                 throw ImageDimensionException("No 1D images!");
00545         }
00546 
00547     if( this->is_complex() )  {
00548         //  We will assume square image for the time being
00549         rmax = ny/2;
00550         ret->set_size(rmax+1, 1, 1);
00551         ret->to_zero();
00552         count.resize(rmax+1);
00553         set_array_offsets(1,1,1);
00554         int nz2 = nz/2;
00555         int ny2 = ny/2;
00556         int nx2 = nx/2;
00557         int jx, jy, jz;
00558         float argy, argz;
00559                         for ( int iz = 1; iz <= nz; iz++) {
00560                                 jz=iz-1; if (jz>nz2) jz=jz-nz; argz = float(jz*jz);
00561                                 for ( int iy = 1; iy <= ny; iy++) {
00562                                         jy=iy-1; if (jy>ny2) jy=jy-ny; argy = argz + float(jy*jy);
00563                                         for ( int ix = 1; ix <= nx2; ix++) {
00564                                         jx=ix-1;
00565                     float r = std::sqrt(argy + float(jx*jx));
00566                     int  ir = int(r);
00567                     if (ir >= rmax) continue;
00568                     float frac = r - float(ir);
00569                     float qres = 1.0f - frac;
00570                     float temp = std::real(cmplx(ix,iy,iz));
00571                     // cout<<"  "<<jx<<"  "<<jy<<"  "<<ir<<"  "<<temp<<"  "<<frac<<endl;
00572                     (*ret)(ir)   += temp*qres;
00573                     (*ret)(ir+1) += temp*frac;
00574                     count[ir]    += qres;
00575                     count[ir+1]  += frac;
00576                                         }
00577                                 }
00578                         }
00579 
00580     } else {
00581 
00582             float apix[3];
00583         apix[0] = get_attr_default("apix_x",1.0);
00584             apix[1] = get_attr_default("apix_y",1.0);
00585         apix[2] = get_attr_default("apix_z",1.0);
00586         float min_apix = *std::min_element(&apix[0],&apix[3]);
00587 
00588         //here,only the relative value of apix_x, apix_y, apix_z are considered
00589         float apix_x = apix[0]/min_apix;
00590         float apix_y = apix[1]/min_apix;
00591         float apix_z = 1.0;
00592 
00593             if( nz > 1)   apix_z=apix[2]/min_apix;
00594 
00595             float apix_x2 = apix_x*apix_x;
00596             float apix_y2 = apix_y*apix_y;
00597             float apix_z2 = apix_z*apix_z;
00598 
00599         set_array_offsets(-nx/2,-ny/2,-nz/2);
00600 
00601 #ifdef _WIN32
00602         //int rmax = _cpp_min(nx/2 + nx%2, ny/2 + ny%2);
00603             if ( nz == 1 )  rmax = _cpp_min( nx/2 + nx%2, ny/2 + ny%2);
00604         else            rmax = _cpp_min(nx/2 + nx%2, _cpp_min(ny/2 + ny%2, nz/2 + nz%2));
00605 #else
00606             //int rmax = std::min(nx/2 + nx%2, ny/2 + ny%2);
00607             if ( nz == 1 )  rmax = std::min(nx/2 + nx%2, ny/2 + ny%2);
00608             else            rmax = std::min(nx/2 + nx%2, std::min(ny/2 + ny%2, nz/2 + nz%2));
00609 #endif  //_WIN32
00610 
00611         float rmax_ratio = 0.0f;
00612         if      (rmax == nx/2 + nx%2 ) rmax_ratio = apix_x;
00613         else if (rmax == ny/2 + ny%2)  rmax_ratio = apix_y;
00614         else                           rmax_ratio = apix_z;
00615 
00616         ret->set_size(rmax+1, 1, 1);
00617         ret->to_zero();
00618         count.resize(rmax+1);
00619         for (int k = -nz/2; k < nz/2 + nz%2; k++) {
00620             if (abs( k*apix_z) > rmax*rmax_ratio ) continue;
00621             for (int j = -ny/2; j < ny/2 + ny%2; j++) {
00622                 if (abs( j*apix_y ) > rmax*rmax_ratio) continue;
00623                 for (int i = -nx/2; i < nx/2 + nx%2; i++) {
00624                     float r = std::sqrt(float(k*k*apix_z2) + float(j*j*apix_y2) + float(i*i*apix_x2))/rmax_ratio;
00625                     int ir = int(r);
00626                     if (ir >= rmax) continue;
00627                     float frac = r - float(ir);
00628                     (*ret)(ir) += (*this)(i,j,k)*(1.0f - frac);
00629                     (*ret)(ir+1) += (*this)(i,j,k)*frac;
00630                     count[ir] += 1.0f - frac;
00631                     count[ir+1] += frac;
00632                 }
00633             }
00634         }
00635         }
00636         for (int ir = 0; ir <= rmax; ir++) {
00637 #ifdef _WIN32
00638         (*ret)(ir) /= _cpp_max(count[ir],1.0f);
00639 #else
00640         (*ret)(ir) /= std::max(count[ir],1.0f);
00641 #endif  //_WIN32
00642     }
00643         set_array_offsets(saved_offsets);
00644         ret->update();
00645         EXITFUNC;
00646         return ret;
00647 }
00648 
00649 EMData* EMData::rotavg_i() {
00650 
00651         int rmax;
00652         ENTERFUNC;
00653         if ( ny == 1 && nz == 1 ) {
00654                 LOGERR("Input image must be 2-D or 3-D!");
00655                 throw ImageDimensionException("Input image must be 2-D or 3-D!");
00656         }
00657 
00658         EMData* avg1D  = new EMData();
00659         EMData* result = new EMData();
00660 
00661         result->set_size(nx,ny,nz);
00662         result->to_zero();
00663         result->set_array_offsets(-nx/2, -ny/2, -nz/2);
00664 
00665         if ( nz == 1 ) {
00666 #ifdef  _WIN32
00667                 rmax = _cpp_min(nx/2 + nx%2, ny/2 + ny%2);
00668         } else {
00669                 rmax = _cpp_min(nx/2 + nx%2, _cpp_min(ny/2 + ny%2, nz/2 + nz%2));
00670 #else
00671                 rmax = std::min(nx/2 + nx%2, ny/2 + ny%2);
00672         } else {
00673                 rmax = std::min(nx/2 + nx%2, std::min(ny/2 + ny%2, nz/2 + nz%2));
00674 #endif  //_WIN32
00675         }
00676 
00677         avg1D = rotavg();
00678         float padded_value = 0.0, r;
00679         int i, j, k, ir;
00680         size_t number_of_pixels = 0;
00681         for ( k = -nz/2; k < nz/2 + nz%2; k++) {
00682                 if (abs(k) > rmax) continue;
00683                 for ( j = -ny/2; j < ny/2 + ny%2; j++) {
00684                         if (abs(j) > rmax) continue;
00685                         for (i = -nx/2; i < nx/2 + nx%2; i++) {
00686                                 r = std::sqrt(float(k*k) + float(j*j) + float(i*i));
00687                                 ir = int(r);
00688                                 if (ir > rmax || ir < rmax-2 ) continue ;
00689                                 else {
00690                                         padded_value += (*avg1D)(ir) ;
00691                                         number_of_pixels++ ;
00692                                 }
00693                         }
00694                 }
00695         }
00696         padded_value /= number_of_pixels;
00697         for ( k = -nz/2; k < nz/2 + nz%2; k++) {
00698                 for ( j = -ny/2; j < ny/2 + ny%2; j++) {
00699                         for ( i = -nx/2; i < nx/2 + nx%2; i++)  {
00700                                 r = std::sqrt(float(k*k) + float(j*j) + float(i*i));
00701                                 ir = int(r);
00702                                 if (ir >= rmax) (*result)(i,j,k) = padded_value ;
00703                                 else            (*result)(i,j,k) = (*avg1D)(ir)+((*avg1D)(ir+1)-(*avg1D)(ir))*(r - float(ir));
00704 
00705                         }
00706                 }
00707         }
00708         result->update();
00709         result->set_array_offsets(0,0,0);
00710         EXITFUNC;
00711         return result;
00712 }
00713 
00714 
00715 EMData* EMData::mult_radial(EMData* radial) {
00716 
00717         ENTERFUNC;
00718         if ( ny == 1 && nz == 1 ) {
00719                 LOGERR("Input image must be 2-D or 3-D!");
00720                 throw ImageDimensionException("Input image must be 2-D or 3-D!");
00721         }
00722 
00723         EMData* result = this->copy_head();
00724 
00725         result->to_zero();
00726         result->set_array_offsets(-nx/2, -ny/2, -nz/2);
00727         this->set_array_offsets(-nx/2, -ny/2, -nz/2);
00728         int rmax = radial->get_xsize();
00729         int i, j, k, ir;
00730         float r;
00731         for ( k = -nz/2; k < nz/2+nz%2; k++) {
00732                 for ( j = -ny/2; j < ny/2+ny%2; j++) {
00733                         for ( i = -nx/2; i < nx/2+nx%2; i++)  {
00734                                 r = std::sqrt(float(k*k) + float(j*j) + float(i*i));
00735                                 ir = int(r);
00736                                 if(ir < rmax-1)  (*result)(i,j,k) = (*this)(i,j,k) * ((*radial)(ir)+((*radial)(ir+1)-(*radial)(ir))*(r - float(ir)));
00737                         }
00738                 }
00739         }
00740         result->update();
00741         result->set_array_offsets(0,0,0);
00742         this->set_array_offsets(0,0,0);
00743         EXITFUNC;
00744         return result;
00745 }
00746 
00747 #define rdata(i,j,k) rdata[(i-1)+((j-1)+(k-1)*ny)*(size_t)nx]
00748 #define square(x) ((x)*(x))
00749 vector<float> EMData::cog() {
00750 
00751         vector<float> cntog;
00752         int ndim = get_ndim();
00753         int i=1,j=1,k=1;
00754         float val,sum1=0.f,MX=0.f,RG=0.f,MY=0.f,MZ=0.f,r=0.f;
00755 
00756         if (ndim == 1) {
00757                 for ( i = 1;i <= nx; i++) {
00758                         val   = rdata(i,j,k);
00759                         sum1 += val;
00760                         MX   += ((i-1)*val);
00761                 }
00762                 MX=(MX/sum1);
00763                 for ( i = 1;i <= nx; i++) {
00764                         val   = rdata(i,j,k);
00765                         sum1 += val;
00766                         RG   += val*(square(MX - (i-1)));
00767                 }
00768                 RG=std::sqrt(RG/sum1);
00769                 MX=MX-(nx/2);
00770                 cntog.push_back(MX);
00771                 cntog.push_back(RG);
00772 #ifdef _WIN32
00773                 cntog.push_back((float)Util::round(MX));
00774 #else
00775                 cntog.push_back(round(MX));
00776 #endif  //_WIN32
00777         } else if (ndim == 2) {
00778                 for (j=1;j<=ny;j++) {
00779                         for (i=1;i<=nx;i++) {
00780                                 val = rdata(i,j,k);
00781                                 sum1 += val;
00782                                 MX   += ((i-1)*val);
00783                                 MY   += ((j-1)*val);
00784                         }
00785                 }
00786                 MX=(MX/sum1);
00787                 MY=(MY/sum1);
00788                 sum1=0.f;
00789                 RG=0.f;
00790                 for (j=1;j<=ny;j++) {
00791                         r = (square(MY-(j-1)));
00792                         for (i=1;i<=nx;i++) {
00793                                 val = rdata(i,j,k);
00794                                 sum1 += val;
00795                                 RG   += val*(square(MX - (i-1)) + r);
00796                         }
00797                 }
00798                 RG = std::sqrt(RG/sum1);
00799                 MX = MX - nx/2;
00800                 MY = MY - ny/2;
00801                 cntog.push_back(MX);
00802                 cntog.push_back(MY);
00803                 cntog.push_back(RG);
00804 #ifdef _WIN32
00805                 cntog.push_back((float)Util::round(MX));cntog.push_back((float)Util::round(MY));
00806 #else
00807                 cntog.push_back(round(MX));cntog.push_back(round(MY));
00808 #endif  //_WIN32
00809         } else {
00810                 for (k = 1;k <= nz;k++) {
00811                         for (j=1;j<=ny;j++) {
00812                                 for (i=1;i<=nx;i++) {
00813                                         val = rdata(i,j,k);
00814                                         sum1 += val;
00815                                         MX += ((i-1)*val);
00816                                         MY += ((j-1)*val);
00817                                         MZ += ((k-1)*val);
00818                                 }
00819                         }
00820                 }
00821                 MX = MX/sum1;
00822                 MY = MY/sum1;
00823                 MZ = MZ/sum1;
00824                 sum1=0.f;
00825                 RG=0.f;
00826                 for (k = 1;k <= nz;k++) {
00827                         for (j=1;j<=ny;j++) {
00828                                 float r = (square(MY-(j-1)) + square(MZ - (k-1)));
00829                                 for (i=1;i<=nx;i++) {
00830                                         val = rdata(i,j,k);
00831                                         sum1 += val;
00832                                         RG   += val*(square(MX - (i-1)) + r);
00833                                 }
00834                         }
00835                 }
00836                 RG = std::sqrt(RG/sum1);
00837                 MX = MX - nx/2;
00838                 MY = MY - ny/2;
00839                 MZ = MZ - nz/2;
00840                 cntog.push_back(MX);
00841                 cntog.push_back(MY);
00842                 cntog.push_back(MZ);
00843                 cntog.push_back(RG);
00844 #ifdef _WIN32
00845                 cntog.push_back((float)Util::round(MX));cntog.push_back((float)Util::round(MY));cntog.push_back((float)Util::round(MZ));
00846 #else
00847                 cntog.push_back(round(MX));cntog.push_back(round(MY));cntog.push_back(round(MZ));
00848 #endif  //_WIN32
00849         }
00850         return cntog;
00851 }
00852 #undef square
00853 #undef rdata
00854 
00855 
00856 
00857 
00858 
00859 vector < float >EMData::calc_fourier_shell_correlation(EMData * with, float w)
00860 {
00861         ENTERFUNC;
00862 
00863 /*
00864  ******************************************************
00865  *DISCLAIMER
00866  * 08/16/05 P.A.Penczek
00867  * The University of Texas
00868  * Pawel.A.Penczek@uth.tmc.edu
00869  * Please do not modify the content of calc_fourier_shell_correlation
00870  ******************************************************/
00871 /*
00872 Fourier Ring/Shell Correlation
00873 Purpose: Calculate CCF in Fourier space as a function of spatial frequency
00874          between a pair of 2-3D images.
00875 Method: Calculate FFT (if needed), calculate FSC.
00876 Input:  f - real or complex 2-3D image
00877         g - real or complex 2-3D image
00878         w - float ring width
00879 Output: 2D 3xk real image.
00880         k - length of FSC curve, depends on dimensions of the image and ring width
00881         1 column - FSC,
00882         2 column - normalized frequency [0,0.5]
00883         3 column - currently n /error of the FSC = 1/sqrt(n),
00884                      where n is the number of Fourier coefficients within given shell
00885 */
00886         int needfree=0, kz, ky, ii;
00887         float  argx, argy, argz;
00888 
00889         if (!with) {
00890                 throw NullPointerException("NULL input image");
00891         }
00892 
00893 
00894         EMData *f = this;
00895         EMData *g = with;
00896 
00897         int nx  = f->get_xsize();
00898         int ny  = f->get_ysize();
00899         int nz  = f->get_zsize();
00900 
00901         if (ny==0 && nz==0) {
00902                 throw ImageFormatException( "Cannot calculate FSC for 1D images");
00903         }
00904 
00905         if (f->is_complex()) nx = (nx - 2 + f->is_fftodd()); // nx is the real-space size of the input image
00906         int lsd2 = (nx + 2 - nx%2) ; // Extended x-dimension of the complex image
00907 
00908 //  Process f if real
00909         EMData* fpimage = NULL;
00910         if (f->is_complex()) fpimage = f;
00911         else {
00912                 fpimage= f->norm_pad(false, 1); 
00913                 fpimage->do_fft_inplace();
00914                 needfree|=1; // Extend and do the FFT if f is real
00915         } 
00916 
00917 //  Process g if real
00918         EMData* gpimage = NULL;
00919         if (g->is_complex()) gpimage = g;
00920         else {
00921                 gpimage= g->norm_pad(false, 1);
00922                 gpimage->do_fft_inplace();
00923                 needfree|=2;  // Extend and do the FFT if g is real
00924         }
00925 
00926         float *d1 = fpimage->get_data();
00927         float *d2 = gpimage->get_data();
00928 
00929         int nx2 = nx/2;
00930         int ny2 = ny/2;
00931         int nz2 = nz/2;
00932 
00933         float dx2 = 1.0f/float(nx2)/float(nx2);
00934         float dy2 = 1.0f/float(ny2)/float(ny2);
00935 
00936 #ifdef _WIN32
00937         float dz2 = 1.0f / _cpp_max(float(nz2),1.0f)/_cpp_max(float(nz2),1.0f);
00938         int inc = Util::round(float( _cpp_max( _cpp_max(nx2,ny2),nz2) )/w );
00939 #else
00940         float dz2 = 1.0f/std::max(float(nz2),1.0f)/std::max(float(nz2),1.0f);
00941         int inc = Util::round(float(std::max(std::max(nx2,ny2),nz2))/w);
00942 #endif  //_WIN32
00943 
00944         double* ret = new double[inc+1];
00945         double* n1 = new double[inc+1];
00946         double* n2 = new double[inc+1];
00947         float*  lr = new float[inc+1];
00948         for (int i = 0; i <= inc; i++) {
00949                 ret[i] = 0.0f; n1[i] = 0.0f; n2[i] = 0.0f; lr[i]=0.0f;
00950         }
00951 
00952         for (int iz = 0; iz <= nz-1; iz++) {
00953                 if(iz>nz2) kz=iz-nz; else kz=iz; argz = float(kz*kz)*dz2;
00954                 for (int iy = 0; iy <= ny-1; iy++) {
00955                         if(iy>ny2) ky=iy-ny; else ky=iy; argy = argz + float(ky*ky)*dy2;
00956                         for (int ix = 0; ix <= lsd2-1; ix+=2) {
00957                         // Skip Friedel related values
00958                                 if (ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
00959                                         argx = 0.5f*std::sqrt(argy + float(ix*ix)*0.25f*dx2);
00960                                         int r = Util::round(inc*2*argx);
00961                                         if(r <= inc) {
00962                                                 ii = ix + (iy  + iz * ny)* lsd2;
00963                                                 ret[r] += d1[ii] * double(d2[ii]) + d1[ii + 1] * double(d2[ii + 1]);
00964                                                 n1[r]  += d1[ii] * double(d1[ii]) + d1[ii + 1] * double(d1[ii + 1]);
00965                                                 n2[r]  += d2[ii] * double(d2[ii]) + d2[ii + 1] * double(d2[ii + 1]);
00966                                                 lr[r]  += 2.0f;
00967                                         }
00968                                 }
00969                         }
00970                 }
00971         }
00972 
00973         int  linc = 0;
00974         for (int i = 0; i <= inc; i++) if(lr[i]>0) linc++;
00975 
00976         vector<float> result(linc*3);
00977 
00978         ii = -1;
00979         for (int i = 0; i <= inc; i++) {
00980                 if(lr[i]>0) {
00981                         ii++;
00982                         result[ii]        = float(i)/float(2*inc);
00983                         result[ii+linc]   = float(ret[i] / (std::sqrt(n1[i] * n2[i])));
00984                         result[ii+2*linc] = lr[i]  /*1.0f/sqrt(float(lr[i]))*/;
00985                 }
00986                 /*else {
00987                         result[i]           = 0.0f;
00988                         result[i+inc+1]     = 0.0f;
00989                         result[i+2*(inc+1)] = 0.0f;}*/
00990         }
00991 
00992         if (needfree&1) {
00993                 if (fpimage) {
00994                         delete fpimage;
00995                         fpimage = 0;
00996                 }
00997         }
00998         if (needfree&2) {
00999                 if (gpimage) {
01000                         delete gpimage;
01001                         gpimage = 0;
01002                 }
01003         }
01004         delete[] ret; delete[]  n1; delete[]  n2; delete[]  lr;
01005 
01006         EXITFUNC;
01007         return result;
01008 }
01009 
01010 
01011 vector < float >EMData::scale_factors(EMData * with, int beg, int end)
01012 {
01013         ENTERFUNC;
01014 
01015 /*
01016  ******************************************************
01017  *DISCLAIMER
01018  * 04/20/14 P.A.Penczek
01019  * The University of Texas
01020  * Pawel.A.Penczek@uth.tmc.edu
01021  * Please do not modify
01022  ******************************************************/
01023 /*
01024 */
01025         int needfree=0, kz, ky, ii;
01026         float  argx, argy, argz;
01027 
01028         if (!with) {
01029                 throw NullPointerException("NULL input image");
01030         }
01031 
01032 
01033         EMData *f = this;
01034         EMData *g = with;
01035 
01036         int nx  = f->get_xsize();
01037         int ny  = f->get_ysize();
01038         int nz  = f->get_zsize();
01039 
01040         if (ny==0 && nz==0) {
01041                 throw ImageFormatException( "Cannot calculate for 1D images");
01042         }
01043 
01044         if (f->is_complex()) nx = (nx - 2 + f->is_fftodd()); // nx is the real-space size of the input image
01045         int lsd2 = (nx + 2 - nx%2) ; // Extended x-dimension of the complex image
01046 
01047 //  Process f if real
01048         EMData* fpimage = NULL;
01049         if (f->is_complex()) fpimage = f;
01050         else {
01051                 fpimage= f->norm_pad(false, 1); 
01052                 fpimage->do_fft_inplace();
01053                 needfree|=1; // Extend and do the FFT if f is real
01054         } 
01055 
01056 //  Process g if real
01057         EMData* gpimage = NULL;
01058         if (g->is_complex()) gpimage = g;
01059         else {
01060                 gpimage= g->norm_pad(false, 1);
01061                 gpimage->do_fft_inplace();
01062                 needfree|=2;  // Extend and do the FFT if g is real
01063         }
01064 
01065         float *d1 = fpimage->get_data();
01066         float *d2 = gpimage->get_data();
01067 
01068         int nx2 = nx/2;
01069         int ny2 = ny/2;
01070         int nz2 = nz/2;
01071 
01072         float dx2 = 1.0f/float(nx2)/float(nx2);
01073         float dy2 = 1.0f/float(ny2)/float(ny2);
01074 
01075 
01076 #ifdef _WIN32
01077         float dz2 = 1.0f / _cpp_max(float(nz2),1.0f)/_cpp_max(float(nz2),1.0f);
01078         int inc = Util::round(float( _cpp_max( _cpp_max(nx2,ny2),nz2) ));
01079 #else
01080         float dz2 = 1.0f/std::max(float(nz2),1.0f)/std::max(float(nz2),1.0f);
01081         int inc = Util::round(float(std::max(std::max(nx2,ny2),nz2) ));
01082 #endif  //_WIN32
01083         int len = end - beg + 1;
01084 
01085         double* ret1 = new double[len];
01086         double* ret2 = new double[len];
01087         float*  lr   = new float[len];
01088         for (int i = 0; i < len; i++) {
01089                 ret1[i] = 0.0f; ret2[i] = 0.0f; lr[i]=0;
01090         }
01091 
01092         for (int iz = 0; iz <= nz-1; iz++) {
01093                 if(iz>nz2) kz=iz-nz; else kz=iz; argz = float(kz*kz)*dz2;
01094                 for (int iy = 0; iy <= ny-1; iy++) {
01095                         if(iy>ny2) ky=iy-ny; else ky=iy; argy = argz + float(ky*ky)*dy2;
01096                         for (int ix = 0; ix <= lsd2-1; ix+=2) {
01097                         // Skip Friedel related values
01098                                 if (ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
01099                                         argx = 0.5f*std::sqrt(argy + float(ix*ix)*0.25f*dx2);
01100                                         int r = Util::round(inc*2*argx);
01101                                         if((r >= beg) && (r <= end)) {
01102                                                 ii = ix + (iy  + iz * ny)* lsd2;
01103                                                 ret1[r-beg] += d1[ii] * double(d2[ii]) + d1[ii + 1] * double(d2[ii + 1]);
01104                                                 ret2[r-beg] += d2[ii] * double(d2[ii]) + d2[ii + 1] * double(d2[ii + 1]);
01105                                                 lr[r-beg]   += 2.0f;
01106                                         }
01107                                 }
01108                         }
01109                 }
01110         }
01111 
01112         vector<float> result(len*2);
01113 
01114         for (int i = 0; i < len; i++) {
01115                         result[i]       = ret1[i]/lr[i];
01116                         result[i+len]   = ret2[i]/lr[i];
01117         }
01118 
01119         delete[] ret1; delete[] ret2; delete[]  lr;
01120 
01121         if (needfree&1) {
01122                 if (fpimage) {
01123                         delete fpimage;
01124                         fpimage = 0;
01125                 }
01126         }
01127         if (needfree&2) {
01128                 if (gpimage) {
01129                         delete gpimage;
01130                         gpimage = 0;
01131                 }
01132         }
01133 
01134         EXITFUNC;
01135         return result;
01136 }
01137 
01138 EMData* EMData::symvol(string symString) {
01139         ENTERFUNC;
01140         int nsym = Transform::get_nsym(symString); // number of symmetries
01141         Transform sym;
01142         // set up output volume
01143         EMData *svol = new EMData;
01144         svol->set_size(nx, ny, nz);
01145         svol->to_zero();
01146         // actual work -- loop over symmetries and symmetrize
01147         for (int isym = 0; isym < nsym; isym++) {
01148                 Transform rm = sym.get_sym(symString, isym);
01149                 EMData* symcopy = this -> rot_scale_trans(rm);
01150                 *svol += (*symcopy);
01151                 delete symcopy;
01152         }
01153         *svol /=  ((float) nsym);
01154         svol->update();
01155         EXITFUNC;
01156         return svol;
01157 }
01158 
01159 #define proj(ix,iy,iz)  proj[ix-1+(iy-1+(iz-1)*ny)*(size_t)nx]
01160 #define pnewimg(ix,iy,iz)  pnewimg[ix-1+(iy-1+(iz-1)*ny)*(size_t)nx]
01161 EMData* EMData::average_circ_sub() const
01162 {
01163 //  this is written as though dimensions could be different, but in fact they should be all equal nx=ny=nz,
01164 //                                                           no check of this
01165         ENTERFUNC;
01166         const EMData* const image = this;
01167         EMData* newimg = copy_head();
01168         float *proj = image->get_data();
01169         float *pnewimg = newimg->get_data();
01170         //  Calculate average outside of a circle
01171         float r2 = static_cast<float>( (nx/2)*(nx/2) );
01172         float qs=0.0f;
01173         int m=0;
01174         int ncz = nz/2 + 1;
01175         int ncy = ny/2 + 1;
01176         int ncx = nx/2 + 1;
01177         for (int iz = 1; iz <= nz; iz++) {
01178                 float yy = static_cast<float>( (iz-ncz)*(iz-ncz) );
01179                 for (int iy = 1; iy <=ny; iy++) { float xx = yy + (iy-ncy)*(iy-ncy);
01180                         for (int ix = 1; ix <= nx; ix++) {
01181                                 if ( xx+float((ix-ncx)*(ix-ncx)) > r2 ) {
01182                                         qs += proj(ix,iy,iz);
01183                                         m++;
01184                                 }
01185                         }
01186                 }
01187         }
01188 
01189 
01190         if( m > 0 ) qs /= m;
01191 
01192         for (int iz = 1; iz <= nz; iz++)
01193                 for (int iy = 1; iy <= ny; iy++)
01194                         for (int ix = 1; ix <= nx; ix++)
01195                                         pnewimg(ix,iy,iz) = proj(ix,iy,iz) - qs;
01196         newimg->update();
01197         return newimg;
01198         EXITFUNC;
01199 }
01200 
01201 
01202 //  Helper functions for method nn
01203 
01204 
01205 void EMData::onelinenn(int j, int n, int n2, EMData* wptr, EMData* bi, const Transform& tf)
01206 {
01207         //std::cout<<"   onelinenn  "<<j<<"  "<<n<<"  "<<n2<<"  "<<std::endl;
01208         int jp = (j >= 0) ? j+1 : n+j+1;
01209         //for(int i = 0; i <= 2; i++){{for(int l = 0; l <= 2; l++) std::cout<<"  "<<tf[l][i];}std::cout<<std::endl;};std::cout<<std::endl;
01210         // loop over x
01211         for (int i = 0; i <= n2; i++) {
01212                 if (((i*i+j*j) < n*n/4) && !((0 == i) && (j < 0))) {
01213 //        if ( !((0 == i) && (j < 0))) {
01214                         float xnew = i*tf[0][0] + j*tf[1][0];
01215                         float ynew = i*tf[0][1] + j*tf[1][1];
01216                         float znew = i*tf[0][2] + j*tf[1][2];
01217                         std::complex<float> btq;
01218                         if (xnew < 0.) {
01219                                 xnew = -xnew;
01220                                 ynew = -ynew;
01221                                 znew = -znew;
01222                                 btq = conj(bi->cmplx(i,jp));
01223                         } else {
01224                                 btq = bi->cmplx(i,jp);
01225                         }
01226                         int ixn = int(xnew + 0.5 + n) - n;
01227                         int iyn = int(ynew + 0.5 + n) - n;
01228                         int izn = int(znew + 0.5 + n) - n;
01229                         
01230                         int iza, iya;
01231                         if (izn >= 0)  iza = izn + 1;
01232                         else           iza = n + izn + 1;
01233 
01234                         if (iyn >= 0) iya = iyn + 1;
01235                         else          iya = n + iyn + 1;
01236 
01237                         cmplx(ixn,iya,iza) += btq;
01238                         //std::cout<<"    "<<j<<"  "<<ixn<<"  "<<iya<<"  "<<iza<<"  "<<btq<<std::endl;
01239                         (*wptr)(ixn,iya,iza)++;
01240                         
01241                         /*if ((ixn <= n2) && (iyn >= -n2) && (iyn <= n2)  && (izn >= -n2) && (izn <= n2)) {
01242                                 if (ixn >= 0) {
01243                                         int iza, iya;
01244                                         if (izn >= 0)  iza = izn + 1;
01245                                         else           iza = n + izn + 1;
01246 
01247                                         if (iyn >= 0) iya = iyn + 1;
01248                                         else          iya = n + iyn + 1;
01249 
01250                                         cmplx(ixn,iya,iza) += btq;
01251                                         //std::cout<<"    "<<j<<"  "<<ixn<<"  "<<iya<<"  "<<iza<<"  "<<btq<<std::endl;
01252                                         (*wptr)(ixn,iya,iza)++;
01253                                 } else {
01254                                         int izt, iyt;
01255                                         if (izn > 0) izt = n - izn + 1;
01256                                         else         izt = -izn + 1;
01257 
01258                                         if (iyn > 0) iyt = n - iyn + 1;
01259                                         else         iyt = -iyn + 1;
01260 
01261                                         cmplx(-ixn,iyt,izt) += conj(btq);
01262                                         //std::cout<<" *  "<<j<<"  "<<ixn<<"  "<<iyt<<"  "<<izt<<"  "<<btq<<std::endl;
01263                                         (*wptr)(-ixn,iyt,izt)++;
01264                                 }
01265                         }*/
01266                 }
01267         }
01268 }
01269 
01270 
01271 void EMData::onelinenn_mult(int j, int n, int n2, EMData* wptr, EMData* bi, const Transform& tf, float mult)
01272 {
01273         //std::cout<<"   onelinenn  "<<j<<"  "<<n<<"  "<<n2<<"  "<<std::endl;
01274         int jp = (j >= 0) ? j+1 : n+j+1;
01275         //for(int i = 0; i <= 1; i++){for(int l = 0; l <= 2; l++){std::cout<<"  "<<tf[i][l]<<"  "<<std::endl;}}
01276         // loop over x
01277         for (int i = 0; i <= n2; i++) {
01278         if (((i*i+j*j) < n*n/4) && !((0 == i) && (j < 0))) {
01279 //        if ( !((0 == i) && (j < 0))) {
01280                         float xnew = i*tf[0][0] + j*tf[1][0];
01281                         float ynew = i*tf[0][1] + j*tf[1][1];
01282                         float znew = i*tf[0][2] + j*tf[1][2];
01283                         std::complex<float> btq;
01284                         if (xnew < 0.) {
01285                                 xnew = -xnew;
01286                                 ynew = -ynew;
01287                                 znew = -znew;
01288                                 btq = conj(bi->cmplx(i,jp));
01289                         } else {
01290                                 btq = bi->cmplx(i,jp);
01291                         }
01292                         int ixn = int(xnew + 0.5 + n) - n;
01293                         int iyn = int(ynew + 0.5 + n) - n;
01294                         int izn = int(znew + 0.5 + n) - n;
01295                         
01296                         
01297                         int iza, iya;
01298                         if (izn >= 0)  iza = izn + 1;
01299                         else           iza = n + izn + 1;
01300 
01301                         if (iyn >= 0) iya = iyn + 1;
01302                         else          iya = n + iyn + 1;
01303 
01304                         cmplx(ixn,iya,iza) += btq * mult;
01305                         (*wptr)(ixn,iya,iza)+= mult;
01306                         
01307                         /*if ((ixn <= n2) && (iyn >= -n2) && (iyn <= n2)  && (izn >= -n2) && (izn <= n2)) {
01308                                 if (ixn >= 0) {
01309                                         int iza, iya;
01310                                         if (izn >= 0)  iza = izn + 1;
01311                                         else           iza = n + izn + 1;
01312 
01313                                         if (iyn >= 0) iya = iyn + 1;
01314                                         else          iya = n + iyn + 1;
01315 
01316                                         cmplx(ixn,iya,iza) += btq*float(mult);
01317                                         (*wptr)(ixn,iya,iza)+=float(mult);
01318                                 } else {
01319                                         int izt, iyt;
01320                                         if (izn > 0) izt = n - izn + 1;
01321                                         else         izt = -izn + 1;
01322 
01323                                         if (iyn > 0) iyt = n - iyn + 1;
01324                                         else         iyt = -iyn + 1;
01325 
01326                                         cmplx(-ixn,iyt,izt) += conj(btq)*float(mult);
01327                                         (*wptr)(-ixn,iyt,izt)+=float(mult);
01328                                 }
01329                         }*/
01330                 }
01331         }
01332 }
01333 
01334 void EMData::nn(EMData* wptr, EMData* myfft, const Transform& tf, float mult)
01335 {
01336         ENTERFUNC;
01337         int nxc = attr_dict["nxc"]; // # of complex elements along x
01338         // let's treat nr, bi, and local data as matrices
01339         vector<int> saved_offsets = get_array_offsets();
01340         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01341         set_array_offsets(0,1,1);
01342         myfft->set_array_offsets(0,1);
01343         // loop over frequencies in y
01344         //for(int i = 0; i <= 2; i++){{for(int l = 0; l <= 2; l++) std::cout<<"  "<<tf[l][i];}std::cout<<std::endl;};std::cout<<std::endl;
01345         //Dict tt = tf.get_rotation("spider");
01346         //std::cout << static_cast<float>(tt["phi"]) << " " << static_cast<float>(tt["theta"]) << " " << static_cast<float>(tt["psi"]) << std::endl;
01347         if( mult == 1 ) {
01348                 for (int iy = -ny/2 + 1; iy <= ny/2; iy++) onelinenn(iy, ny, nxc, wptr, myfft, tf);
01349         } else {
01350                 for (int iy = -ny/2 + 1; iy <= ny/2; iy++) onelinenn_mult(iy, ny, nxc, wptr, myfft, tf, mult);
01351         }
01352 
01353         set_array_offsets(saved_offsets);
01354         myfft->set_array_offsets(myfft_saved_offsets);
01355         EXITFUNC;
01356 }
01357 
01358 
01359 void EMData::insert_rect_slice(EMData* w, EMData* myfft, const Transform& trans, int sizeofprojection, float xratio, float yratio, float zratio, int npad, float mult)
01360 {
01361         ENTERFUNC;
01362         vector<int> saved_offsets = get_array_offsets();
01363         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01364         set_array_offsets(0,1,1);
01365         myfft->set_array_offsets(0,1);
01366         
01367         // insert rectangular fft from my nn4_rect code
01368 
01369         Vec2f coordinate_2d_square;
01370         Vec3f coordinate_3dnew;
01371         Vec3f axis_newx;
01372         Vec3f axis_newy;
01373         Vec3f tempv;
01374         
01375         //begin of scaling factor calculation
01376         //unit vector x,y of 2D fft transformed to new positon after rotation and scaling
01377         axis_newx[0] = xratio*0.5f*(sizeofprojection*npad)*trans[0][0];
01378         axis_newx[1] = yratio*0.5f*(sizeofprojection*npad)*trans[0][1];
01379         axis_newx[2] = zratio*0.5f*(sizeofprojection*npad)*trans[0][2];
01380 
01381         float ellipse_length_x = std::sqrt(axis_newx[0]*axis_newx[0]+axis_newx[1]*axis_newx[1]+axis_newx[2]*axis_newx[2]);
01382         
01383         int ellipse_length_x_int = int(ellipse_length_x);
01384         float ellipse_step_x = 0.5f*(sizeofprojection*npad)/float(ellipse_length_x_int);
01385         float xscale = ellipse_step_x;//scal increased
01386 
01387         axis_newy[0] = xratio*0.5f*(sizeofprojection*npad)*trans[1][0];
01388         axis_newy[1] = yratio*0.5f*(sizeofprojection*npad)*trans[1][1];
01389         axis_newy[2] = zratio*0.5f*(sizeofprojection*npad)*trans[1][2];
01390 
01391 
01392 
01393         float ellipse_length_y = std::sqrt(axis_newy[0]*axis_newy[0]+axis_newy[1]*axis_newy[1]+axis_newy[2]*axis_newy[2]);
01394         int ellipse_length_y_int = int(ellipse_length_y);
01395         float ellipse_step_y = 0.5f*(sizeofprojection*npad)/float(ellipse_length_y_int);
01396         float yscale = ellipse_step_y;
01397         //end of scaling factor calculation
01398         std::complex<float> c1;
01399         int nxyz = sizeofprojection*npad;
01400 
01401         float r2=0.25f*sizeofprojection*npad*sizeofprojection*npad;
01402         float r2_at_point;
01403         
01404         for(int i=0;i<ellipse_length_x_int;i++) {
01405                 for(int j=-1*ellipse_length_y_int+1; j<=ellipse_length_y_int; j++) {
01406                     
01407                         r2_at_point=i*xscale*i*xscale+j*yscale*j*yscale;
01408                         if(r2_at_point<=r2 ) {
01409                                 
01410                                 
01411                                 coordinate_2d_square[0] = xscale*float(i);
01412                                 coordinate_2d_square[1] = yscale*float(j);
01413                                 float xnew = coordinate_2d_square[0]*trans[0][0] + coordinate_2d_square[1]*trans[1][0];
01414                                 float ynew = coordinate_2d_square[0]*trans[0][1] + coordinate_2d_square[1]*trans[1][1];
01415                                 float znew = coordinate_2d_square[0]*trans[0][2] + coordinate_2d_square[1]*trans[1][2];
01416                                 coordinate_3dnew[0] = xnew*xratio;
01417                                 coordinate_3dnew[1] = ynew*yratio;
01418                                 coordinate_3dnew[2] = znew*zratio;
01419                                 
01420                                 //bilinear interpolation
01421                                 float xp = coordinate_2d_square[0];
01422                                 float yp = ( coordinate_2d_square[1] >= 0) ? coordinate_2d_square[1]+1 : nxyz+coordinate_2d_square[1]+1;
01423                                 std::complex<float> lin_interpolated(0,0);
01424                                 int xlow=int(xp),xhigh=int(xp)+1;
01425                                 int ylow=int(yp),yhigh=int(yp)+1;
01426                                 float tx=xp-xlow,ty=yp-ylow;
01427 
01428                                 
01429                                 if(j == -1) {
01430                                         
01431                                         if(ylow<yp)
01432                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)*(1-ty) + myfft->cmplx(xlow,yhigh)*(1-tx)*ty
01433                                                 + myfft->cmplx(xhigh,ylow)*tx*(1-ty) + myfft->cmplx(xhigh,yhigh)*tx*ty;
01434                                         else 
01435                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)
01436                                                 + myfft->cmplx(xhigh,ylow)*tx;
01437                                                                         
01438                                 } else {
01439                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)*(1-ty) + myfft->cmplx(xlow,yhigh)*(1-tx)*ty
01440                                                 + myfft->cmplx(xhigh,ylow)*tx*(1-ty)+ myfft->cmplx(xhigh,yhigh)*tx*ty;
01441                                         
01442                                 }
01443                                         
01444                                 c1 = lin_interpolated;
01445                                 
01446                                 //now nearest neighborhood interpolation
01447                                 
01448                                 std::complex<float> btq;
01449                                 if ( coordinate_3dnew[0] < 0.) {
01450                                         coordinate_3dnew[0] = -coordinate_3dnew[0];
01451                                         coordinate_3dnew[1] = -coordinate_3dnew[1];
01452                                         coordinate_3dnew[2] = -coordinate_3dnew[2];
01453                                         btq = conj(c1);
01454                                         } else {
01455                                         btq = c1;
01456                                         }
01457                                 int ixn = int(coordinate_3dnew[0] + 0.5 + nx) - nx;
01458                                 int iyn = int(coordinate_3dnew[1] + 0.5 + ny) - ny;
01459                                 int izn = int(coordinate_3dnew[2] + 0.5 + nz) - nz;
01460 
01461                                 int iza, iya;
01462                                 if (izn >= 0)  iza = izn + 1;
01463                                 else           iza = nz + izn + 1;
01464 
01465                                 if (iyn >= 0) iya = iyn + 1;
01466                                 else          iya = ny + iyn + 1;
01467 
01468                                 cmplx(ixn,iya,iza) += btq * mult;
01469                                 (*w)(ixn,iya,iza) += mult;
01470                                         
01471                                 }
01472                         }
01473                             
01474                 }
01475 
01476 
01477         //end insert rectanular fft
01478                 
01479         set_array_offsets(saved_offsets);
01480         myfft->set_array_offsets(myfft_saved_offsets);
01481         EXITFUNC;
01482 
01483 }
01484 
01485 
01486 
01487 void EMData::nn_SSNR(EMData* wptr, EMData* wptr2, EMData* myfft, const Transform& tf, float)
01488 {
01489         ENTERFUNC;
01490         int nxc = attr_dict["nxc"];
01491 
01492         vector<int> saved_offsets = get_array_offsets();
01493         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01494 
01495         set_array_offsets(0,1,1);
01496         myfft->set_array_offsets(0,1);
01497 
01498         int iymin = is_fftodd() ? -ny/2 : -ny/2 + 1 ;
01499         int iymax = ny/2;
01500         int izmin = is_fftodd() ? -nz/2 : -nz/2 + 1 ;
01501         int izmax = nz/2;
01502 
01503         for (int iy = iymin; iy <= iymax; iy++) {
01504                 int jp = iy >= 0 ? iy+1 : ny+iy+1; //checked, works for both odd and even
01505                 for (int ix = 0; ix <= nxc; ix++) {
01506                         if (( 4*(ix*ix+iy*iy) < ny*ny ) && !( ix == 0 && iy < 0 ) ) {
01507                                 float xnew = ix*tf[0][0] + iy*tf[1][0];
01508                                 float ynew = ix*tf[0][1] + iy*tf[1][1];
01509                                 float znew = ix*tf[0][2] + iy*tf[1][2];
01510                                 std::complex<float> btq;
01511                                 if (xnew < 0.0) {
01512                                         xnew = -xnew; // ensures xnew>=0.0
01513                                         ynew = -ynew;
01514                                         znew = -znew;
01515                                         btq = conj(myfft->cmplx(ix,jp));
01516                                 } else {
01517                                         btq = myfft->cmplx(ix,jp);
01518                                 }
01519                                 int ixn = int(xnew + 0.5 + nx) - nx; // ensures ixn >= 0
01520                                 int iyn = int(ynew + 0.5 + ny) - ny;
01521                                 int izn = int(znew + 0.5 + nz) - nz;
01522                                 if ((ixn <= nxc) && (iyn >= iymin) && (iyn <= iymax) && (izn >= izmin) && (izn <= izmax)) {
01523                                         if (ixn >= 0) {
01524                                                 int iza, iya;
01525                                                 if (izn >= 0)  iza = izn + 1;
01526                                                 else           iza = nz + izn + 1;
01527 
01528                                                 if (iyn >= 0) iya = iyn + 1;
01529                                                 else          iya = ny + iyn + 1;
01530 
01531                                                 cmplx(ixn,iya,iza) += btq;
01532                                                 (*wptr)(ixn,iya,iza)++;
01533                                                 (*wptr2)(ixn,iya,iza) += norm(btq);
01534                                         } else {
01535                                                 int izt, iyt;
01536                                                 if (izn > 0) izt = nz - izn + 1;
01537                                                 else         izt = -izn + 1;
01538 
01539                                                 if (iyn > 0) iyt = ny - iyn + 1;
01540                                                 else         iyt = -iyn + 1;
01541 
01542                                                 cmplx(-ixn,iyt,izt) += std::conj(btq);
01543                                                 (*wptr)(-ixn,iyt,izt)++;
01544                                                 (*wptr2)(-ixn,iyt,izt) += std::norm(btq);
01545                                         }
01546                                 }
01547                         }
01548                 }
01549         }
01550         set_array_offsets(saved_offsets);
01551         myfft->set_array_offsets(myfft_saved_offsets);
01552         EXITFUNC;
01553 }
01554 
01555 
01556 
01557 void EMData::symplane0(EMData* wptr) {
01558         ENTERFUNC;
01559         int nxc = attr_dict["nxc"];
01560         int n = nxc*2;
01561         // let's treat the local data as a matrix
01562         vector<int> saved_offsets = get_array_offsets();
01563         set_array_offsets(0,1,1);
01564         for (int iza = 2; iza <= nxc; iza++) {
01565                 for (int iya = 2; iya <= nxc; iya++) {
01566                         cmplx(0,iya,iza) += conj(cmplx(0,n-iya+2,n-iza+2));
01567                         (*wptr)(0,iya,iza) += (*wptr)(0,n-iya+2,n-iza+2);
01568                         cmplx(0,n-iya+2,n-iza+2) = conj(cmplx(0,iya,iza));
01569                         (*wptr)(0,n-iya+2,n-iza+2) = (*wptr)(0,iya,iza);
01570                         cmplx(0,n-iya+2,iza) += conj(cmplx(0,iya,n-iza+2));
01571                         (*wptr)(0,n-iya+2,iza) += (*wptr)(0,iya,n-iza+2);
01572                         cmplx(0,iya,n-iza+2) = conj(cmplx(0,n-iya+2,iza));
01573                         (*wptr)(0,iya,n-iza+2) = (*wptr)(0,n-iya+2,iza);
01574                 }
01575         }
01576         for (int iya = 2; iya <= nxc; iya++) {
01577                 cmplx(0,iya,1) += conj(cmplx(0,n-iya+2,1));
01578                 (*wptr)(0,iya,1) += (*wptr)(0,n-iya+2,1);
01579                 cmplx(0,n-iya+2,1) = conj(cmplx(0,iya,1));
01580                 (*wptr)(0,n-iya+2,1) = (*wptr)(0,iya,1);
01581         }
01582         for (int iza = 2; iza <= nxc; iza++) {
01583                 cmplx(0,1,iza) += conj(cmplx(0,1,n-iza+2));
01584                 (*wptr)(0,1,iza) += (*wptr)(0,1,n-iza+2);
01585                 cmplx(0,1,n-iza+2) = conj(cmplx(0,1,iza));
01586                 (*wptr)(0,1,n-iza+2) = (*wptr)(0,1,iza);
01587         }
01588         EXITFUNC;
01589 }
01590 
01591 void EMData::symplane1(EMData* wptr, EMData* wptr2) {
01592         ENTERFUNC;
01593         int nxc = attr_dict["nxc"];
01594         int n = nxc*2;
01595         vector<int> saved_offsets = get_array_offsets();
01596         set_array_offsets(0,1,1);
01597         for (int iza = 2; iza <= nxc; iza++) {
01598                 for (int iya = 2; iya <= nxc; iya++) {
01599                         cmplx(0,iya,iza) += conj(cmplx(0,n-iya+2,n-iza+2));
01600                         (*wptr)(0,iya,iza) += (*wptr)(0,n-iya+2,n-iza+2);
01601                         (*wptr2)(0,iya,iza) += (*wptr2)(0,n-iya+2,n-iza+2);
01602                         cmplx(0,n-iya+2,n-iza+2) = conj(cmplx(0,iya,iza));
01603                         (*wptr)(0,n-iya+2,n-iza+2) = (*wptr)(0,iya,iza);
01604                         (*wptr2)(0,n-iya+2,n-iza+2) = (*wptr2)(0,iya,iza);
01605                         cmplx(0,n-iya+2,iza) += conj(cmplx(0,iya,n-iza+2));
01606                         (*wptr)(0,n-iya+2,iza) += (*wptr)(0,iya,n-iza+2);
01607                         (*wptr2)(0,n-iya+2,iza) += (*wptr2)(0,iya,n-iza+2);
01608                         cmplx(0,iya,n-iza+2) = conj(cmplx(0,n-iya+2,iza));
01609                         (*wptr)(0,iya,n-iza+2) = (*wptr)(0,n-iya+2,iza);
01610                         (*wptr2)(0,iya,n-iza+2) = (*wptr2)(0,n-iya+2,iza);
01611                 }
01612         }
01613         for (int iya = 2; iya <= nxc; iya++) {
01614                 cmplx(0,iya,1) += conj(cmplx(0,n-iya+2,1));
01615                 (*wptr)(0,iya,1) += (*wptr)(0,n-iya+2,1);
01616                 (*wptr2)(0,iya,1) += (*wptr2)(0,n-iya+2,1);
01617                 cmplx(0,n-iya+2,1) = conj(cmplx(0,iya,1));
01618                 (*wptr)(0,n-iya+2,1) = (*wptr)(0,iya,1);
01619                 (*wptr2)(0,n-iya+2,1) = (*wptr2)(0,iya,1);
01620         }
01621         for (int iza = 2; iza <= nxc; iza++) {
01622                 cmplx(0,1,iza) += conj(cmplx(0,1,n-iza+2));
01623                 (*wptr)(0,1,iza) += (*wptr)(0,1,n-iza+2);
01624                 (*wptr2)(0,1,iza) += (*wptr2)(0,1,n-iza+2);
01625                 cmplx(0,1,n-iza+2) = conj(cmplx(0,1,iza));
01626                 (*wptr)(0,1,n-iza+2) = (*wptr)(0,1,iza);
01627                 (*wptr2)(0,1,n-iza+2) = (*wptr2)(0,1,iza);
01628         }
01629         EXITFUNC;
01630 }
01631 
01632 void EMData::symplane2(EMData* wptr, EMData* wptr2, EMData* wptr3) {
01633         ENTERFUNC;
01634         int nxc = attr_dict["nxc"];
01635         int n = nxc*2;
01636         vector<int> saved_offsets = get_array_offsets();
01637         set_array_offsets(0,1,1);
01638         for (int iza = 2; iza <= nxc; iza++) {
01639                 for (int iya = 2; iya <= nxc; iya++) {
01640                         cmplx(0,iya,iza) += conj(cmplx(0,n-iya+2,n-iza+2));
01641                         (*wptr)(0,iya,iza) += (*wptr)(0,n-iya+2,n-iza+2);
01642                         (*wptr2)(0,iya,iza) += (*wptr2)(0,n-iya+2,n-iza+2);
01643                         (*wptr3)(0,iya,iza) += (*wptr3)(0,n-iya+2,n-iza+2);
01644 
01645                         cmplx(0,n-iya+2,n-iza+2) = conj(cmplx(0,iya,iza));
01646                         (*wptr)(0,n-iya+2,n-iza+2) = (*wptr)(0,iya,iza);
01647                         (*wptr2)(0,n-iya+2,n-iza+2) = (*wptr2)(0,iya,iza);
01648                         (*wptr3)(0,n-iya+2,n-iza+2) = (*wptr3)(0,iya,iza);
01649 
01650                         cmplx(0,n-iya+2,iza) += conj(cmplx(0,iya,n-iza+2));
01651                         (*wptr)(0,n-iya+2,iza) += (*wptr)(0,iya,n-iza+2);
01652                         (*wptr2)(0,n-iya+2,iza) += (*wptr2)(0,iya,n-iza+2);
01653                         (*wptr3)(0,n-iya+2,iza) += (*wptr3)(0,iya,n-iza+2);
01654 
01655                         cmplx(0,iya,n-iza+2) = conj(cmplx(0,n-iya+2,iza));
01656                         (*wptr)(0,iya,n-iza+2) = (*wptr)(0,n-iya+2,iza);
01657                         (*wptr2)(0,iya,n-iza+2) = (*wptr2)(0,n-iya+2,iza);
01658                         (*wptr3)(0,iya,n-iza+2) = (*wptr3)(0,n-iya+2,iza);
01659                 }
01660         }
01661         for (int iya = 2; iya <= nxc; iya++) {
01662                 cmplx(0,iya,1) += conj(cmplx(0,n-iya+2,1));
01663                 (*wptr)(0,iya,1) += (*wptr)(0,n-iya+2,1);
01664                 (*wptr2)(0,iya,1) += (*wptr2)(0,n-iya+2,1);
01665                 (*wptr3)(0,iya,1) += (*wptr3)(0,n-iya+2,1);
01666 
01667                 cmplx(0,n-iya+2,1) = conj(cmplx(0,iya,1));
01668                 (*wptr)(0,n-iya+2,1) = (*wptr)(0,iya,1);
01669                 (*wptr2)(0,n-iya+2,1) = (*wptr2)(0,iya,1);
01670                 (*wptr3)(0,n-iya+2,1) = (*wptr3)(0,iya,1);
01671         }
01672         for (int iza = 2; iza <= nxc; iza++) {
01673                 cmplx(0,1,iza) += conj(cmplx(0,1,n-iza+2));
01674                 (*wptr)(0,1,iza) += (*wptr)(0,1,n-iza+2);
01675                 (*wptr2)(0,1,iza) += (*wptr2)(0,1,n-iza+2);
01676                 (*wptr3)(0,1,iza) += (*wptr3)(0,1,n-iza+2);
01677 
01678                 cmplx(0,1,n-iza+2) = conj(cmplx(0,1,iza));
01679                 (*wptr)(0,1,n-iza+2) = (*wptr)(0,1,iza);
01680                 (*wptr2)(0,1,n-iza+2) = (*wptr2)(0,1,iza);
01681                 (*wptr3)(0,1,n-iza+2) = (*wptr3)(0,1,iza);
01682         }
01683         EXITFUNC;
01684 }
01685 
01686 
01687 class ctf_store
01688 {
01689 public:
01690 
01691     static void init( int winsize, const Ctf* ctf ) {
01692                 Dict params = ctf->to_dict();
01693 
01694                 m_winsize = winsize;
01695 
01696                 m_voltage = params["voltage"];
01697                 m_pixel   = params["apix"];
01698                 m_cs      = params["cs"];
01699                 m_ampcont = params["ampcont"];
01700                 m_bfactor = params["bfactor"];
01701                 m_defocus = params["defocus"];
01702                 m_dza     = params["dfdiff"];
01703                 m_azz     = params["dfang"];
01704                 m_winsize2= m_winsize*m_winsize;
01705                 m_vecsize = m_winsize2/4;
01706     }
01707 
01708     static float get_ctf( int r2 ,int i, int j) {
01709                 float  ak = std::sqrt( r2/float(m_winsize2) )/m_pixel;
01710                 if(m_dza == 0.0f)  return Util::tf( m_defocus, ak, m_voltage, m_cs, m_ampcont, m_bfactor, 1);
01711                 else {
01712                         float az = atan2(float(j), float(i));
01713                         float dzz = m_defocus - m_dza/2.0f*sin(2*(az+m_azz*M_PI/180.0f));
01714                         return Util::tf( dzz, ak, m_voltage, m_cs, m_ampcont, m_bfactor, 1);
01715                 }
01716         }
01717 
01718 private:
01719 
01720         static int m_winsize, m_winsize2, m_vecsize;
01721         static float m_cs;
01722         static float m_voltage;
01723         static float m_pixel;
01724         static float m_ampcont;
01725         static float m_bfactor;
01726         static float m_defocus;
01727         static float m_dza;
01728         static float m_azz;
01729 };
01730 
01731 
01732 int ctf_store::m_winsize, ctf_store::m_winsize2, ctf_store::m_vecsize;
01733 
01734 float ctf_store::m_cs, ctf_store::m_voltage, ctf_store::m_pixel;
01735 float ctf_store::m_ampcont, ctf_store::m_bfactor;
01736 float ctf_store::m_defocus, ctf_store::m_dza, ctf_store::m_azz;
01737 
01738 
01739 class ctf_store_new
01740 {
01741 public:
01742 
01743         static void init( int winsize, const Ctf* ctf ) {
01744                 Dict params = ctf->to_dict();
01745 
01746                 m_winsize = winsize;
01747 
01748                 m_voltage = params["voltage"];
01749                 m_pixel   = params["apix"];
01750                 m_cs      = params["cs"];
01751                 m_ampcont = params["ampcont"];
01752                 m_bfactor = params["bfactor"];
01753                 m_defocus = params["defocus"];
01754                 m_dza     = params["dfdiff"];
01755                 m_azz     = params["dfang"];
01756                 m_winsize2= m_winsize*m_winsize;
01757                 m_vecsize = m_winsize2/4;
01758     }
01759 
01760     static float get_ctf( float r2 ) {  //  HAS TO BE CORRECTED AS astigmatism m_dza and m_azz is not used!!  PAP 04/27/2013
01761                 float ak = std::sqrt( r2/float(m_winsize2) )/m_pixel;
01762                 return Util::tf( m_defocus, ak, m_voltage, m_cs, m_ampcont, m_bfactor, 1);
01763     }
01764 
01765 private:
01766 
01767         static int m_winsize, m_winsize2, m_vecsize;
01768         static float m_cs;
01769         static float m_voltage;
01770         static float m_pixel;
01771         static float m_ampcont;
01772         static float m_bfactor;
01773         static float m_defocus;
01774         static float m_dza;
01775         static float m_azz;
01776 };
01777 
01778 
01779 int ctf_store_new::m_winsize, ctf_store_new::m_winsize2, ctf_store_new::m_vecsize;
01780 
01781 float ctf_store_new::m_cs, ctf_store_new::m_voltage, ctf_store_new::m_pixel;
01782 float ctf_store_new::m_ampcont, ctf_store_new::m_bfactor;
01783 float ctf_store_new::m_defocus, ctf_store_new::m_dza, ctf_store_new::m_azz;
01784 
01785 
01786 
01787 //  Helper functions for method nn4_ctf
01788 void EMData::onelinenn_ctf(int j, int n, int n2, EMData* w, EMData* bi, const Transform& tf, float mult) {
01789 //std::cout<<"   onelinenn_ctf  "<<j<<"  "<<n<<"  "<<n2<<"  "<<std::endl;
01790 
01791         //int remove = bi->get_attr_default( "remove", 0 );
01792 
01793         int jp = (j >= 0) ? j+1 : n+j+1;
01794         // loop over x
01795         for (int i = 0; i <= n2; i++) {
01796                 int r2 = i*i+j*j;
01797                 if ( (r2<n*n/4) && !((0==i) && (j<0)) ) {
01798                         float ctf = ctf_store::get_ctf( r2, i, j ); //This is in 2D projection plane
01799                         float xnew = i*tf[0][0] + j*tf[1][0];
01800                         float ynew = i*tf[0][1] + j*tf[1][1];
01801                         float znew = i*tf[0][2] + j*tf[1][2];
01802                         std::complex<float> btq;
01803                         if (xnew < 0.) {
01804                                 xnew = -xnew;
01805                                 ynew = -ynew;
01806                                 znew = -znew;
01807                                 btq = conj(bi->cmplx(i,jp));
01808                         } else  btq = bi->cmplx(i,jp);
01809                         int ixn = int(xnew + 0.5 + n) - n;
01810                         int iyn = int(ynew + 0.5 + n) - n;
01811                         int izn = int(znew + 0.5 + n) - n;
01812 
01813                         int iza, iya;
01814                         if (izn >= 0)  iza = izn + 1;
01815                         else           iza = n + izn + 1;
01816 
01817                         if (iyn >= 0)  iya = iyn + 1;
01818                         else           iya = n + iyn + 1;
01819 
01820                         //if(remove > 0 ) {
01821                         //      cmplx(ixn,iya,iza) -= btq*ctf*mult;
01822                         //      (*w)(ixn,iya,iza)  -= ctf*ctf*mult;
01823                         //} else {
01824                                 cmplx(ixn,iya,iza) += btq*ctf*mult;
01825                                 (*w)(ixn,iya,iza)  += ctf*ctf*mult;
01826                         //}
01827 
01828                 }
01829         }
01830 }
01831 
01832 //  Helper functions for method nn4_ctfw
01833 void EMData::onelinenn_ctfw(int j, int n, int n2, EMData* w, EMData* bi, EMData* sigmasq2, const Transform& tf, float weight) {
01834 //std::cout<<"   onelinenn_ctf  "<<j<<"  "<<n<<"  "<<n2<<"  "<<std::endl;
01835 //for (int i = 0; i <= 127; i++)  cout <<"  "<<i<<"  "<<(*sigmasq2)(i)<<endl;
01836     int nnd4 = n*n/4;
01837         int jp = (j >= 0) ? j+1 : n+j+1;
01838         //for (int i = 0; i<190; i++) cout <<"  "<<i<<"  "<< (*sigmasq2)(i)<<endl;
01839         // loop over x
01840         for (int i = 0; i <= n2; i++) {
01841                 int r2 = i*i+j*j;
01842                 if ( (r2<nnd4) && !((0==i) && (j<0)) ) {
01843                         float ctf = ctf_store::get_ctf( r2, i, j ); //This is in 2D projection plane
01844                         float xnew = i*tf[0][0] + j*tf[1][0];
01845                         float ynew = i*tf[0][1] + j*tf[1][1];
01846                         float znew = i*tf[0][2] + j*tf[1][2];
01847                         std::complex<float> btq;
01848                         if (xnew < 0.) {
01849                                 xnew = -xnew;
01850                                 ynew = -ynew;
01851                                 znew = -znew;
01852                                 btq = conj(bi->cmplx(i,jp));
01853                         } else  btq = bi->cmplx(i,jp);
01854                         int ixn = int(xnew + 0.5 + n) - n;
01855                         int iyn = int(ynew + 0.5 + n) - n;
01856                         int izn = int(znew + 0.5 + n) - n;
01857 
01858                         int iza, iya;
01859                         if (izn >= 0)  iza = izn + 1;
01860                         else           iza = n + izn + 1;
01861 
01862                         if (iyn >= 0) iya = iyn + 1;
01863                         else          iya = n + iyn + 1;
01864 
01865             // linear interpolation of 1D sigmasq2
01866             float rr = std::sqrt(float(r2));
01867             int   ir = int(rr);
01868             float df = rr - float(ir);
01869             float mult = (1.0f - df)*(*sigmasq2)(ir) + df*(*sigmasq2)(ir+1);
01870             //cout <<"  "<<jp<<"  "<<i<<"  "<<j<<"  "<<rr<<"  "<<ir<<"  "<<mult<<"  "<<1.0f/mult<<"  "<<btq<<"  "<<weight<<endl;
01871                         cmplx(ixn, iya, iza) += btq*ctf*mult*weight;
01872                         (*w)(ixn, iya, iza)  += ctf*ctf*mult*weight;
01873 
01874                 }
01875         }
01876 }
01877 
01878 void EMData::onelinenn_ctf_applied(int j, int n, int n2,
01879                           EMData* w, EMData* bi, const Transform& tf, float mult) {//std::cout<<"   onelinenn_ctf  "<<j<<"  "<<n<<"  "<<n2<<"  "<<std::endl;
01880 
01881         int remove = bi->get_attr_default( "remove", 0 );
01882 
01883         int jp = (j >= 0) ? j+1 : n+j+1;
01884         // loop over x
01885         for (int i = 0; i <= n2; i++) {
01886                 int r2 = i*i + j*j;
01887                 if ( (r2< n*n/4) && !((0==i) && (j< 0)) ) {
01888                         float  ctf = ctf_store::get_ctf(r2, i, j);
01889 
01890                          //        if ( !((0 == i) && (j < 0))) {
01891                         float xnew = i*tf[0][0] + j*tf[1][0];
01892                         float ynew = i*tf[0][1] + j*tf[1][1];
01893                         float znew = i*tf[0][2] + j*tf[1][2];
01894                         std::complex<float> btq;
01895                         if (xnew < 0.) {
01896                                 xnew = -xnew;
01897                                 ynew = -ynew;
01898                                 znew = -znew;
01899                                 btq = conj(bi->cmplx(i,jp));
01900                         } else  btq = bi->cmplx(i,jp);
01901                         int ixn = int(xnew + 0.5 + n) - n;
01902                         int iyn = int(ynew + 0.5 + n) - n;
01903                         int izn = int(znew + 0.5 + n) - n;
01904                         
01905                         int iza, iya;
01906                         if (izn >= 0)  iza = izn + 1;
01907                         else           iza = n + izn + 1;
01908 
01909                         if (iyn >= 0) iya = iyn + 1;
01910                         else          iya = n + iyn + 1;
01911 
01912                         if( remove > 0 ) {
01913                                 cmplx(ixn,iya,iza) -= btq*mult;
01914                                 (*w)(ixn,iya,iza) -= mult*ctf*ctf;
01915                         } else {
01916                                 cmplx(ixn,iya,iza) += btq*mult;
01917                                 (*w)(ixn,iya,iza) += mult*ctf*ctf;
01918                         }
01919 
01920                 }
01921         }
01922 }
01923 
01924 void EMData::nn_ctf(EMData* w, EMData* myfft, const Transform& tf, float mult) {
01925         ENTERFUNC;
01926         int nxc = attr_dict["nxc"]; // # of complex elements along x
01927         // let's treat nr, bi, and local data as matrices
01928         vector<int> saved_offsets = get_array_offsets();
01929         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01930         set_array_offsets(0,1,1);
01931         myfft->set_array_offsets(0,1);
01932 
01933     Ctf* ctf = myfft->get_attr("ctf");
01934     ctf_store::init( ny, ctf );
01935     if(ctf) {delete ctf; ctf=0;}
01936 
01937         // loop over frequencies in y
01938         for (int iy = -ny/2 + 1; iy <= ny/2; iy++) onelinenn_ctf(iy, ny, nxc, w, myfft, tf, mult);
01939         set_array_offsets(saved_offsets);
01940         myfft->set_array_offsets(myfft_saved_offsets);
01941         EXITFUNC;
01942 }
01943 
01944 void EMData::nn_ctfw(EMData* w, EMData* myfft, EMData* sigmasq2, const Transform& tf, float weight ) {
01945         ENTERFUNC;
01946         int nxc = attr_dict["nxc"]; // # of complex elements along x
01947         // let's treat nr, bi, and local data as matrices
01948         vector<int> saved_offsets = get_array_offsets();
01949         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01950         set_array_offsets(0,1,1);
01951         myfft->set_array_offsets(0,1);
01952         //sigmasq2->set_array_offsets(0,1);
01953 
01954     Ctf* ctf = myfft->get_attr("ctf");
01955     ctf_store::init( ny, ctf );
01956     if(ctf) {delete ctf; ctf=0;}
01957 
01958         // loop over frequencies in y
01959         for (int iy = -ny/2 + 1; iy <= ny/2; iy++) onelinenn_ctfw(iy, ny, nxc, w, myfft, sigmasq2, tf, weight);
01960         set_array_offsets(saved_offsets);
01961         myfft->set_array_offsets(myfft_saved_offsets);
01962         EXITFUNC;
01963 }
01964 
01965 void EMData::nn_ctf_applied(EMData* w, EMData* myfft, const Transform& tf, float mult) {
01966         ENTERFUNC;
01967         int nxc = attr_dict["nxc"]; // # of complex elements along x
01968         // let's treat nr, bi, and local data as matrices
01969         vector<int> saved_offsets = get_array_offsets();
01970         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01971         set_array_offsets(0,1,1);
01972         myfft->set_array_offsets(0,1);
01973 
01974         Ctf* ctf = myfft->get_attr( "ctf" );
01975         ctf_store::init( ny, ctf );
01976         if(ctf) {delete ctf; ctf=0;}
01977         //}
01978 
01979         // loop over frequencies in y
01980         for (int iy = -ny/2 + 1; iy <= ny/2; iy++) onelinenn_ctf_applied(iy, ny, nxc, w, myfft, tf, mult);
01981         set_array_offsets(saved_offsets);
01982         myfft->set_array_offsets(myfft_saved_offsets);
01983         EXITFUNC;
01984 }
01985 
01986 
01987 void EMData::insert_rect_slice_ctf(EMData* w, EMData* myfft, const Transform& trans, int sizeofprojection, float xratio, float yratio, float zratio, int npad, float mult)
01988 {
01989         ENTERFUNC;
01990         vector<int> saved_offsets = get_array_offsets();
01991         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
01992         set_array_offsets(0,1,1);
01993         myfft->set_array_offsets(0,1);
01994         
01995         // insert rectangular fft from my nn4_rect code
01996 
01997         Vec2f coordinate_2d_square;
01998         Vec3f coordinate_3dnew;
01999         Vec3f axis_newx;
02000         Vec3f axis_newy;
02001         Vec3f tempv;
02002         
02003         //begin of scaling factor calculation
02004         //unit vector x,y of 2D fft transformed to new positon after rotation and scaling
02005         axis_newx[0] = xratio*0.5f*(sizeofprojection*npad)*trans[0][0];
02006         axis_newx[1] = yratio*0.5f*(sizeofprojection*npad)*trans[0][1];
02007         axis_newx[2] = zratio*0.5f*(sizeofprojection*npad)*trans[0][2];
02008 
02009         float ellipse_length_x = std::sqrt(axis_newx[0]*axis_newx[0]+axis_newx[1]*axis_newx[1]+axis_newx[2]*axis_newx[2]);
02010         
02011         int ellipse_length_x_int = int(ellipse_length_x);
02012         float ellipse_step_x = 0.5f*(sizeofprojection*npad)/float(ellipse_length_x_int);
02013         float xscale = ellipse_step_x;//scal increased
02014 
02015         axis_newy[0] = xratio*0.5f*(sizeofprojection*npad)*trans[1][0];
02016         axis_newy[1] = yratio*0.5f*(sizeofprojection*npad)*trans[1][1];
02017         axis_newy[2] = zratio*0.5f*(sizeofprojection*npad)*trans[1][2];
02018 
02019 
02020 
02021         float ellipse_length_y = std::sqrt(axis_newy[0]*axis_newy[0]+axis_newy[1]*axis_newy[1]+axis_newy[2]*axis_newy[2]);
02022         int ellipse_length_y_int = int(ellipse_length_y);
02023         float ellipse_step_y = 0.5f*(sizeofprojection*npad)/float(ellipse_length_y_int);
02024         float yscale = ellipse_step_y;
02025         //end of scaling factor calculation
02026         std::complex<float> c1;
02027         int nxyz = sizeofprojection*npad;
02028         Ctf* ctf = myfft->get_attr( "ctf" );
02029         ctf_store_new::init( nxyz, ctf );
02030         if(ctf) {delete ctf; ctf=0;}
02031         int remove = myfft->get_attr_default( "remove", 0 );
02032 
02033         float r2=0.25f*sizeofprojection*npad*sizeofprojection*npad;
02034         float r2_at_point;
02035         
02036         for(int i=0;i<ellipse_length_x_int;i++) {
02037                 for(int j=-1*ellipse_length_y_int+1; j<=ellipse_length_y_int; j++) {
02038                     
02039                         r2_at_point=i*xscale*i*xscale+j*yscale*j*yscale;
02040                         if(r2_at_point<=r2 && ! ((0==i) && (j<0))) {
02041                                 
02042                                 float ctf_value = ctf_store_new::get_ctf( r2_at_point );
02043                                 coordinate_2d_square[0] = xscale*float(i);
02044                                 coordinate_2d_square[1] = yscale*float(j);
02045                                 float xnew = coordinate_2d_square[0]*trans[0][0] + coordinate_2d_square[1]*trans[1][0];
02046                                 float ynew = coordinate_2d_square[0]*trans[0][1] + coordinate_2d_square[1]*trans[1][1];
02047                                 float znew = coordinate_2d_square[0]*trans[0][2] + coordinate_2d_square[1]*trans[1][2];
02048                                 coordinate_3dnew[0] = xnew*xratio;
02049                                 coordinate_3dnew[1] = ynew*yratio;
02050                                 coordinate_3dnew[2] = znew*zratio;
02051                                 
02052                                 //bilinear interpolation
02053                                 float xp = coordinate_2d_square[0];
02054                                 float yp = ( coordinate_2d_square[1] >= 0) ? coordinate_2d_square[1]+1 : nxyz+coordinate_2d_square[1]+1;
02055                                 std::complex<float> lin_interpolated(0,0);
02056                                 int xlow=int(xp),xhigh=int(xp)+1;
02057                                 int ylow=int(yp),yhigh=int(yp)+1;
02058                                 float tx=xp-xlow,ty=yp-ylow;
02059 
02060                                 
02061                                 if(j == -1) {
02062                                         
02063                                         if(ylow<yp)
02064                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)*(1-ty) + myfft->cmplx(xlow,yhigh)*(1-tx)*ty
02065                                                 + myfft->cmplx(xhigh,ylow)*tx*(1-ty) + myfft->cmplx(xhigh,yhigh)*tx*ty;
02066                                         else 
02067                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)
02068                                                 + myfft->cmplx(xhigh,ylow)*tx;
02069                                                                         
02070                                 } else {
02071                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)*(1-ty) + myfft->cmplx(xlow,yhigh)*(1-tx)*ty
02072                                                 + myfft->cmplx(xhigh,ylow)*tx*(1-ty)+ myfft->cmplx(xhigh,yhigh)*tx*ty;
02073                                         
02074                                 }
02075                                         
02076                                 c1 = lin_interpolated;
02077                                 
02078                                 //now nearest neighborhood interpolation
02079                                 
02080                                 std::complex<float> btq;
02081                                 if ( coordinate_3dnew[0] < 0.) {
02082                                         coordinate_3dnew[0] = -coordinate_3dnew[0];
02083                                         coordinate_3dnew[1] = -coordinate_3dnew[1];
02084                                         coordinate_3dnew[2] = -coordinate_3dnew[2];
02085                                         btq = conj(c1);
02086                                         } else {
02087                                         btq = c1;
02088                                         }
02089                                 int ixn = int(coordinate_3dnew[0] + 0.5 + nx) - nx;
02090                                 int iyn = int(coordinate_3dnew[1] + 0.5 + ny) - ny;
02091                                 int izn = int(coordinate_3dnew[2] + 0.5 + nz) - nz;
02092 
02093                                 int iza, iya;
02094                                 if (izn >= 0)  iza = izn + 1;
02095                                 else           iza = nz + izn + 1;
02096 
02097                                 if (iyn >= 0) iya = iyn + 1;
02098                                 else          iya = ny + iyn + 1;
02099 
02100                                 if(remove > 0 ) {
02101                                         cmplx(ixn,iya,iza) -= btq*ctf_value * mult;
02102                                         (*w)(ixn,iya,iza) -= ctf_value*ctf_value*mult;
02103                                         } else {
02104                                         cmplx(ixn,iya,iza) += btq*ctf_value * mult;
02105                                         (*w)(ixn,iya,iza) += ctf_value*ctf_value*mult;
02106                                         }
02107                                         
02108                                 }
02109                         }
02110                             
02111                 }
02112 
02113 
02114         //end insert rectanular fft
02115                 
02116         set_array_offsets(saved_offsets);
02117         myfft->set_array_offsets(myfft_saved_offsets);
02118         EXITFUNC;
02119 
02120 }
02121 
02122 
02123 void EMData::insert_rect_slice_ctf_applied(EMData* w, EMData* myfft,const Transform& trans,int sizeofprojection,float xratio,float yratio, float zratio, int npad,float mult)
02124 {
02125         ENTERFUNC;
02126         vector<int> saved_offsets = get_array_offsets();
02127         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
02128         set_array_offsets(0,1,1);
02129         myfft->set_array_offsets(0,1);
02130         
02131         // insert rectangular fft from my nn4_rect code
02132 
02133         Vec2f coordinate_2d_square;
02134         Vec3f coordinate_3dnew;
02135         Vec3f axis_newx;
02136         Vec3f axis_newy;
02137         Vec3f tempv;
02138         
02139         //begin of scaling factor calculation
02140         //unit vector x,y of 2D fft transformed to new positon after rotation and scaling
02141         axis_newx[0] = xratio*0.5f*(sizeofprojection*npad)*trans[0][0];
02142         axis_newx[1] = yratio*0.5f*(sizeofprojection*npad)*trans[0][1];
02143         axis_newx[2] = zratio*0.5f*(sizeofprojection*npad)*trans[0][2];
02144 
02145         float ellipse_length_x = std::sqrt(axis_newx[0]*axis_newx[0]+axis_newx[1]*axis_newx[1]+axis_newx[2]*axis_newx[2]);
02146         
02147         int ellipse_length_x_int = int(ellipse_length_x);
02148         float ellipse_step_x = 0.5f*(sizeofprojection*npad)/float(ellipse_length_x_int);
02149         float xscale = ellipse_step_x;//scal increased
02150 
02151         axis_newy[0] = xratio*0.5f*(sizeofprojection*npad)*trans[1][0];
02152         axis_newy[1] = yratio*0.5f*(sizeofprojection*npad)*trans[1][1];
02153         axis_newy[2] = zratio*0.5f*(sizeofprojection*npad)*trans[1][2];
02154 
02155 
02156 
02157         float ellipse_length_y = std::sqrt(axis_newy[0]*axis_newy[0]+axis_newy[1]*axis_newy[1]+axis_newy[2]*axis_newy[2]);
02158         int ellipse_length_y_int = int(ellipse_length_y);
02159         float ellipse_step_y = 0.5f*(sizeofprojection*npad)/float(ellipse_length_y_int);
02160         float yscale = ellipse_step_y;
02161         //end of scaling factor calculation
02162         std::complex<float> c1;
02163         int nxyz = sizeofprojection*npad;
02164         Ctf* ctf = myfft->get_attr( "ctf" );
02165         ctf_store_new::init( nxyz, ctf );
02166         if(ctf) {delete ctf; ctf=0;}
02167         int remove = myfft->get_attr_default( "remove", 0 );
02168 
02169         float r2=0.25f*sizeofprojection*npad*sizeofprojection*npad;
02170         float r2_at_point;
02171         
02172         for(int i=0;i<ellipse_length_x_int;i++) {
02173                 for(int j=-1*ellipse_length_y_int+1; j<=ellipse_length_y_int; j++) {
02174                     
02175                         r2_at_point=i*xscale*i*xscale+j*yscale*j*yscale;
02176                         if(r2_at_point<=r2 && ! ((0==i) && (j<0))) {
02177                                 
02178                                 float ctf_value = ctf_store_new::get_ctf( r2_at_point );
02179                                 coordinate_2d_square[0] = xscale*float(i);
02180                                 coordinate_2d_square[1] = yscale*float(j);
02181                                 float xnew = coordinate_2d_square[0]*trans[0][0] + coordinate_2d_square[1]*trans[1][0];
02182                                 float ynew = coordinate_2d_square[0]*trans[0][1] + coordinate_2d_square[1]*trans[1][1];
02183                                 float znew = coordinate_2d_square[0]*trans[0][2] + coordinate_2d_square[1]*trans[1][2];
02184                                 coordinate_3dnew[0] = xnew*xratio;
02185                                 coordinate_3dnew[1] = ynew*yratio;
02186                                 coordinate_3dnew[2] = znew*zratio;
02187                                 
02188                                 //bilinear interpolation
02189                                 float xp = coordinate_2d_square[0];
02190                                 float yp = ( coordinate_2d_square[1] >= 0) ? coordinate_2d_square[1]+1 : nxyz+coordinate_2d_square[1]+1;
02191                                 std::complex<float> lin_interpolated(0,0);
02192                                 int xlow=int(xp),xhigh=int(xp)+1;
02193                                 int ylow=int(yp),yhigh=int(yp)+1;
02194                                 float tx=xp-xlow,ty=yp-ylow;
02195 
02196                                 
02197                                 if(j == -1) {
02198                                         
02199                                         if(ylow<yp)
02200                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)*(1-ty) + myfft->cmplx(xlow,yhigh)*(1-tx)*ty
02201                                                 + myfft->cmplx(xhigh,ylow)*tx*(1-ty) + myfft->cmplx(xhigh,yhigh)*tx*ty;
02202                                         else
02203                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)
02204                                                 + myfft->cmplx(xhigh,ylow)*tx;
02205                                                                         
02206                                 } else {
02207                                                 lin_interpolated=myfft->cmplx(xlow,ylow)*(1-tx)*(1-ty) + myfft->cmplx(xlow,yhigh)*(1-tx)*ty
02208                                                 + myfft->cmplx(xhigh,ylow)*tx*(1-ty)+ myfft->cmplx(xhigh,yhigh)*tx*ty;
02209                                 }
02210                                         
02211                                 c1 = lin_interpolated;
02212                                 
02213                                 //now nearest neighborhood interpolation
02214                                 
02215                                 std::complex<float> btq;
02216                                 if ( coordinate_3dnew[0] < 0.) {
02217                                         coordinate_3dnew[0] = -coordinate_3dnew[0];
02218                                         coordinate_3dnew[1] = -coordinate_3dnew[1];
02219                                         coordinate_3dnew[2] = -coordinate_3dnew[2];
02220                                         btq = conj(c1);
02221                                         } else {
02222                                                 btq = c1;
02223                                         }
02224                                 int ixn = int(coordinate_3dnew[0] + 0.5 + nx) - nx;
02225                                 int iyn = int(coordinate_3dnew[1] + 0.5 + ny) - ny;
02226                                 int izn = int(coordinate_3dnew[2] + 0.5 + nz) - nz;
02227 
02228                                 int iza, iya;
02229                                 if (izn >= 0)  iza = izn + 1;
02230                                 else           iza = nz + izn + 1;
02231 
02232                                 if (iyn >= 0) iya = iyn + 1;
02233                                 else          iya = ny + iyn + 1;
02234 
02235                                 if(remove > 0 ) {
02236                                         cmplx(ixn,iya,iza) -= btq * mult;
02237                                         (*w)(ixn,iya,iza) -= ctf_value*ctf_value*mult;
02238                                         } else {
02239                                         cmplx(ixn,iya,iza) += btq * mult;
02240                                         (*w)(ixn,iya,iza) += ctf_value*ctf_value*mult;
02241                                         }
02242                                         
02243                                 }
02244                         }
02245                             
02246                 }
02247 
02248 
02249         //end insert rectanular fft
02250                 
02251         set_array_offsets(saved_offsets);
02252         myfft->set_array_offsets(myfft_saved_offsets);
02253         EXITFUNC;
02254 
02255 }
02256 
02257 
02258 /*
02259 Data::onelinenn_ctf(int j, int n, int n2, EMData* w, EMData* bi, const Transform& tf, int mult) {
02260 //std::cout<<"   onelinenn_ctf  "<<j<<"  "<<n<<"  "<<n2<<"  "<<std::endl;
02261 
02262         int remove = bi->get_attr_default( "remove", 0 );
02263 
02264         int jp = (j >= 0) ? j+1 : n+j+1;
02265         // loop over x
02266         for (int i = 0; i <= n2; i++) {
02267                 int r2 = i*i+j*j;
02268                 if ( (r2<n*n/4) && !( (0==i) && (j<0) ) ) {
02269                         float  ctf = ctf_store::get_ctf( r2 );
02270                         float xnew = i*tf[0][0] + j*tf[1][0];
02271                         float ynew = i*tf[0][1] + j*tf[1][1];
02272                         float znew = i*tf[0][2] + j*tf[1][2];
02273                         std::complex<float> btq;
02274                         if (xnew < 0.) {
02275                                 xnew = -xnew;
02276                                 ynew = -ynew;
02277                                 znew = -znew;
02278                                 btq = conj(bi->cmplx(i,jp));
02279                         } else  btq = bi->cmplx(i,jp);
02280                         int ixn = int(xnew + 0.5 + n) - n;
02281                         int iyn = int(ynew + 0.5 + n) - n;
02282                         int izn = int(znew + 0.5 + n) - n;
02283                         if ((ixn <= n2) && (iyn >= -n2) && (iyn <= n2) && (izn >= -n2) && (izn <= n2)) {
02284                                 if (ixn >= 0) {
02285                                         int iza, iya;
02286                                         if (izn >= 0)  iza = izn + 1;
02287                                         else           iza = n + izn + 1;
02288 
02289                                         if (iyn >= 0) iya = iyn + 1;
02290                                         else          iya = n + iyn + 1;
02291 
02292                                         if(remove > 0 ) {
02293                                                 cmplx(ixn,iya,iza) -= btq*ctf*float(mult);
02294                                                 (*w)(ixn,iya,iza)  -= ctf*ctf*mult;
02295                                         } else {
02296                                                 cmplx(ixn,iya,iza) += btq*ctf*float(mult);
02297                                                 (*w)(ixn,iya,iza)  += ctf*ctf*mult;
02298                                         }
02299 
02300                                        //       std::cout<<"    "<<j<<"  "<<ixn<<"  "<<iya<<"  "<<iza<<"  "<<ctf<<std::endl;
02301                                 } else {
02302                                         int izt, iyt;
02303                                         if (izn > 0) izt = n - izn + 1;
02304                                         else         izt = -izn + 1;
02305 
02306                                         if (iyn > 0) iyt = n - iyn + 1;
02307                                         else         iyt = -iyn + 1;
02308 
02309                     if( remove > 0 ) {
02310                                             cmplx(-ixn,iyt,izt) -= conj(btq)*ctf*float(mult);
02311                                             (*w)(-ixn,iyt,izt)  -= ctf*ctf*float(mult);
02312                     } else {
02313                                             cmplx(-ixn,iyt,izt) += conj(btq)*ctf*float(mult);
02314                                             (*w)(-ixn,iyt,izt)  += ctf*ctf*float(mult);
02315                                         }
02316 
02317                                         //      std::cout<<" *  " << j << "  " <<-ixn << "  " << iyt << "  " << izt << "  " << ctf <<std::endl;
02318                                 }
02319                         }
02320                 }
02321         }
02322 }
02323 */
02324 
02325 
02326 void EMData::nn_SSNR_ctf(EMData* wptr, EMData* wptr2, EMData* wptr3, EMData* myfft, const Transform& tf, float)
02327 {
02328         /***   Preparing terms for SSNR
02329               m_wvolume F^3D Wiener volume
02330              wptr   ctf^2
02331             wptr5  ctf^2*|P^2D->3D(F^3D)|^2
02332            wptr4  2*Real(conj(F_k^2D)*ctf*P^2D->3D(F^3D))
02333           wptr2  F_k^2D*conj(F_k^2D) or |F_k^2D|^2
02334           Kn is counted in the previous routine, and won't be
02335          calculated any more.
02336                                                     ***/
02337         ENTERFUNC;
02338         int nxc = attr_dict["nxc"];
02339         vector<int> saved_offsets = get_array_offsets();
02340         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
02341         set_array_offsets(0,1,1);
02342         myfft->set_array_offsets(0,1);
02343 
02344         Ctf* ctf = myfft->get_attr("ctf");
02345         ctf_store::init( ny, ctf );
02346         int iymin = is_fftodd() ? -ny/2 : -ny/2 + 1;
02347         int iymax = ny/2;
02348         int izmin = is_fftodd() ? -nz/2 : -nz/2 + 1;
02349         int izmax = nz/2;
02350 //      std::complex<float> tmpq, tmp2;
02351         for (int iy = iymin; iy <= iymax; iy++) {
02352                 int jp = iy >= 0 ? iy+1 : ny+iy+1; //checked, works for both odd and even
02353                 for (int ix = 0; ix <= nxc; ix++) {
02354                         int r2 = ix*ix+iy*iy;
02355                         if (( 4*r2 < ny*ny ) && !( ix == 0 && iy < 0 ) ) {
02356                                 float  ctf = ctf_store::get_ctf( r2, ix, iy )*10.f;// ???PAP
02357                                 float xnew = ix*tf[0][0] + iy*tf[1][0];
02358                                 float ynew = ix*tf[0][1] + iy*tf[1][1];
02359                                 float znew = ix*tf[0][2] + iy*tf[1][2];
02360                                 std::complex<float> btq;
02361                                 if (xnew < 0.0) {
02362                                         xnew = -xnew; // ensures xnew>=0.0
02363                                         ynew = -ynew;
02364                                         znew = -znew;
02365                                         btq = conj(myfft->cmplx(ix,jp));
02366                                 } else  {
02367                                         btq = myfft->cmplx(ix,jp);
02368                                 }
02369                                 int ixn = int(xnew + 0.5 + nx) - nx; // ensures ixn >= 0
02370                                 int iyn = int(ynew + 0.5 + ny) - ny;
02371                                 int izn = int(znew + 0.5 + nz) - nz;
02372                                 if ((ixn <= nxc) && (iyn >= iymin) && (iyn <= iymax) && (izn >= izmin) && (izn <= izmax)) {
02373                                         if (ixn >= 0) {
02374                                                 int iza, iya;
02375                                                 if (izn >= 0) iza = izn + 1;
02376                                                 else          iza = nz + izn + 1;
02377 
02378                                                 if (iyn >= 0) iya = iyn + 1;
02379                                                 else          iya = ny + iyn + 1;
02380 
02381                                                 cmplx(ixn,iya,iza)    += btq*ctf;
02382                                                 (*wptr)(ixn,iya,iza)  += ctf*ctf;
02383                                                 (*wptr2)(ixn,iya,iza) += std::norm(btq);
02384                                                 (*wptr3)(ixn,iya,iza) += 1;
02385                                         } else {
02386                                                 int izt, iyt;
02387                                                 if (izn > 0)  izt = nz - izn + 1;
02388                                                 else          izt = -izn + 1;
02389 
02390                                                 if (iyn > 0) iyt = ny - iyn + 1;
02391                                                 else         iyt = -iyn + 1;
02392 
02393                                                 cmplx(-ixn,iyt,izt)    += std::conj(btq)*ctf;
02394                                                 (*wptr) (-ixn,iyt,izt) += ctf*ctf;
02395                                                 (*wptr2)(-ixn,iyt,izt) += std::norm(btq);
02396                                                 (*wptr3)(-ixn,iyt,izt) += 1;
02397                                         }
02398                                 }
02399                         }
02400                 }
02401         }
02402         set_array_offsets(saved_offsets);
02403         myfft->set_array_offsets(myfft_saved_offsets);
02404         if(ctf) {delete ctf; ctf=0;}
02405         EXITFUNC;
02406 }
02407 
02408 /*void EMData::nn_wiener(EMData* wptr, EMData* wptr3, EMData* myfft, const Transform& tf, int)
02409 {
02410      // Wiener volume calculating routine Counting Kn
02411 
02412         ENTERFUNC;
02413         int nxc = attr_dict["nxc"];
02414         vector<int> saved_offsets = get_array_offsets();
02415         vector<int> myfft_saved_offsets = myfft->get_array_offsets();
02416         set_array_offsets(0,1,1);
02417         myfft->set_array_offsets(0,1);
02418         // if( ! ctf_store::inited() )
02419         float Cs           = myfft->get_attr( "Cs" );
02420         float pixel        = myfft->get_attr( "Pixel_size" );
02421         float voltage      = myfft->get_attr( "voltage");
02422         float amp_contrast = myfft->get_attr( "amp_contrast" );
02423         float b_factor     = 0.0;
02424         ctf_store::init( ny, voltage, pixel, Cs, amp_contrast, b_factor );
02425         float defocus = myfft->get_attr( "defocus" );
02426         int iymin = is_fftodd() ? -ny/2 : -ny/2 + 1 ;
02427         int iymax = ny/2;
02428         int izmin = is_fftodd() ? -nz/2 : -nz/2 + 1 ;
02429         int izmax = nz/2;
02430         for (int iy = iymin; iy <= iymax; iy++) {
02431                 int jp = iy >= 0 ? iy+1 : ny+iy+1; //checked, works for both odd and even
02432                 for (int ix = 0; ix <= nxc; ix++) {
02433                         int r2 = ix*ix+iy*iy;
02434                         if (( 4*r2 < ny*ny ) && !( ix == 0 && iy < 0 ) )
02435                         {
02436                                 float  ctf = ctf_store::get_ctf( defocus, r2 );
02437                                 float xnew = ix*tf[0][0] + iy*tf[1][0];
02438                                 float ynew = ix*tf[0][1] + iy*tf[1][1];
02439                                 float znew = ix*tf[0][2] + iy*tf[1][2];
02440                                 std::complex<float> btq;
02441                                 if (xnew < 0.0) {
02442                                         xnew = -xnew; // ensures xnew>=0.0
02443                                         ynew = -ynew;
02444                                         znew = -znew;
02445                                         btq = conj(myfft->cmplx(ix,jp));
02446                                 } else {
02447                                         btq = myfft->cmplx(ix,jp);
02448                                 }
02449                                 int ixn = int(xnew + 0.5 + nx) - nx; // ensures ixn >= 0
02450                                 int iyn = int(ynew + 0.5 + ny) - ny;
02451                                 int izn = int(znew + 0.5 + nz) - nz;
02452                                 if ((ixn <= nxc) && (iyn >= iymin) && (iyn <= iymax) && (izn >= izmin) && (izn <= izmax)) {
02453                                         if (ixn >= 0) {
02454                                                 int iza, iya;
02455                                                 if (izn >= 0)   iza = izn + 1;
02456                                                 else                    iza = nz + izn + 1;
02457 
02458                                                 if (iyn >= 0)   iya = iyn + 1;
02459                                                 else                    iya = ny + iyn + 1;
02460 
02461                                                 cmplx(ixn,iya,iza)    += btq*ctf;
02462                                                 (*wptr)(ixn,iya,iza)  += ctf*ctf;
02463                                                 (*wptr3)(ixn,iya,iza) += 1.0;
02464                                         } else {
02465                                                 int izt, iyt;
02466                                                 if (izn > 0)    izt = nz - izn + 1;
02467                                                 else                    izt = -izn + 1;
02468 
02469                                                 if (iyn > 0)    iyt = ny - iyn + 1;
02470                                                 else                    iyt = -iyn + 1;
02471 
02472 \                                               cmplx(-ixn,iyt,izt)    += conj(btq)*ctf;
02473                                                 (*wptr)(-ixn,iyt,izt)  += ctf*ctf;
02474                                                 (*wptr3)(-ixn,iyt,izt) += 1.0;
02475                                         }
02476                                 }
02477                         }
02478                 }
02479         }
02480         set_array_offsets(saved_offsets);
02481         myfft->set_array_offsets(myfft_saved_offsets);
02482         EXITFUNC;
02483 }*/
02484 
02485 void EMData::symplane0_ctf(EMData* w) {
02486         ENTERFUNC;
02487         int nxc = attr_dict["nxc"];
02488         int n = nxc*2;
02489         // let's treat the local data as a matrix
02490         vector<int> saved_offsets = get_array_offsets();
02491         set_array_offsets(0,1,1);
02492         for (int iza = 2; iza <= nxc; iza++) {
02493                 for (int iya = 2; iya <= nxc; iya++) {
02494                         cmplx(0,iya,iza) += conj(cmplx(0,n-iya+2,n-iza+2));
02495                         (*w)(0,iya,iza) += (*w)(0,n-iya+2,n-iza+2);
02496                         cmplx(0,n-iya+2,n-iza+2) = conj(cmplx(0,iya,iza));
02497                         (*w)(0,n-iya+2,n-iza+2) = (*w)(0,iya,iza);
02498                         cmplx(0,n-iya+2,iza) += conj(cmplx(0,iya,n-iza+2));
02499                         (*w)(0,n-iya+2,iza) += (*w)(0,iya,n-iza+2);
02500                         cmplx(0,iya,n-iza+2) = conj(cmplx(0,n-iya+2,iza));
02501                         (*w)(0,iya,n-iza+2) = (*w)(0,n-iya+2,iza);
02502                 }
02503         }
02504         for (int iya = 2; iya <= nxc; iya++) {
02505                 cmplx(0,iya,1) += conj(cmplx(0,n-iya+2,1));
02506                 (*w)(0,iya,1) += (*w)(0,n-iya+2,1);
02507                 cmplx(0,n-iya+2,1) = conj(cmplx(0,iya,1));
02508                 (*w)(0,n-iya+2,1) = (*w)(0,iya,1);
02509         }
02510         for (int iza = 2; iza <= nxc; iza++) {
02511                 cmplx(0,1,iza) += conj(cmplx(0,1,n-iza+2));
02512                 (*w)(0,1,iza) += (*w)(0,1,n-iza+2);
02513                 cmplx(0,1,n-iza+2) = conj(cmplx(0,1,iza));
02514                 (*w)(0,1,n-iza+2) = (*w)(0,1,iza);
02515         }
02516         EXITFUNC;
02517 }
02518 
02519 void EMData::symplane0_rect(EMData* w) {
02520         ENTERFUNC;
02521         nx=get_xsize();
02522         ny=get_ysize();
02523         nz=get_zsize();
02524         int nzc=nz/2;
02525         int nyc=ny/2;
02526         
02527         // let's treat the local data as a matrix
02528         vector<int> saved_offsets = get_array_offsets();
02529         set_array_offsets(0,1,1);
02530         for (int iza = 2; iza <= nzc; iza++) {
02531                 for (int iya = 2; iya <= nyc; iya++) {
02532                         cmplx(0,iya,iza) += conj(cmplx(0,ny-iya+2,nz-iza+2));
02533                         (*w)(0,iya,iza) += (*w)(0,ny-iya+2,nz-iza+2);
02534                         cmplx(0,ny-iya+2,nz-iza+2) = conj(cmplx(0,iya,iza));
02535                         (*w)(0,ny-iya+2,nz-iza+2) = (*w)(0,iya,iza);
02536                         cmplx(0,ny-iya+2,iza) += conj(cmplx(0,iya,nz-iza+2));
02537                         (*w)(0,ny-iya+2,iza) += (*w)(0,iya,nz-iza+2);
02538                         cmplx(0,iya,nz-iza+2) = conj(cmplx(0,ny-iya+2,iza));
02539                         (*w)(0,iya,nz-iza+2) = (*w)(0,ny-iya+2,iza);
02540                 }
02541         }
02542         for (int iya = 2; iya <= nyc; iya++) {
02543                 cmplx(0,iya,1) += conj(cmplx(0,ny-iya+2,1));
02544                 (*w)(0,iya,1) += (*w)(0,ny-iya+2,1);
02545                 cmplx(0,ny-iya+2,1) = conj(cmplx(0,iya,1));
02546                 (*w)(0,ny-iya+2,1) = (*w)(0,iya,1);
02547         }
02548         for (int iza = 2; iza <= nzc; iza++) {
02549                 cmplx(0,1,iza) += conj(cmplx(0,1,nz-iza+2));
02550                 (*w)(0,1,iza) += (*w)(0,1,nz-iza+2);
02551                 cmplx(0,1,nz-iza+2) = conj(cmplx(0,1,iza));
02552                 (*w)(0,1,nz-iza+2) = (*w)(0,1,iza);
02553         }
02554         EXITFUNC;
02555 }
02556 
02557 EMData* EMData::rot_scale_trans2D(float angDeg, float delx, float dely, float scale) { // quadratic, no background, 2D
02558         float ang=angDeg*M_PI/180.0f;
02559         if (1 >= ny)
02560                 throw ImageDimensionException("Can't rotate 1D image");
02561         if (nz<2) {
02562                 vector<int> saved_offsets = get_array_offsets();
02563                 set_array_offsets(0,0,0);
02564                 if (0.0f == scale) scale = 1.0f; // silently fix common user error
02565                 EMData* ret = copy_head();
02566                 delx = restrict2(delx, nx);
02567                 dely = restrict2(dely, ny);
02568                 // center of image
02569                 int xc = nx/2;
02570                 int yc = ny/2;
02571                 // shifted center for rotation
02572                 float shiftxc = xc + delx;
02573                 float shiftyc = yc + dely;
02574                 // trig
02575                 float cang = cos(ang);
02576                 float sang = sin(ang);
02577                         for (int iy = 0; iy < ny; iy++) {
02578                                 float y = float(iy) - shiftyc;
02579                                 float ycang = y*cang/scale + yc;
02580                                 float ysang = -y*sang/scale + xc;
02581                                 for (int ix = 0; ix < nx; ix++) {
02582                                         float x = float(ix) - shiftxc;
02583                                         float xold = x*cang/scale + ysang ;
02584                                         float yold = x*sang/scale + ycang ;
02585                                         //  quadri is taking care of cyclic count
02586                                         (*ret)(ix,iy) = Util::quadri(xold+1.0f, yold+1.0f, nx, ny, get_data());
02587                                            //have to add one as quadri uses Fortran counting
02588                                 }
02589                         }
02590                 set_array_offsets(saved_offsets);
02591                 return ret;
02592         } else {
02593                 throw ImageDimensionException("Volume not currently supported");
02594         }
02595 }
02596 
02597 EMData* EMData::rot_scale_trans2D_background(float angDeg, float delx, float dely, float scale) { // quadratic, no background, 2D
02598     float ang=angDeg*M_PI/180.0f;
02599         if (1 >= ny)
02600                 throw ImageDimensionException("Can't rotate 1D image");
02601         if (nz<2) {
02602                 vector<int> saved_offsets = get_array_offsets();
02603                 set_array_offsets(0,0,0);
02604                 if (0.0f == scale) scale = 1.0f; // silently fix common user error
02605                 EMData* ret = copy_head();
02606                 delx = restrict2(delx, nx);
02607                 dely = restrict2(dely, ny);
02608                 // center of image
02609                 int xc = nx/2;
02610                 int yc = ny/2;
02611                 // shifted center for rotation
02612                 float shiftxc = xc + delx;
02613                 float shiftyc = yc + dely;
02614                 // trig
02615                 float cang = cos(ang);
02616                 float sang = sin(ang);
02617                         for (int iy = 0; iy < ny; iy++) {
02618                                 float y = float(iy) - shiftyc;
02619                                 float ycang = y*cang/scale + yc;
02620                                 float ysang = -y*sang/scale + xc;
02621                                 for (int ix = 0; ix < nx; ix++) {
02622                                         float x = float(ix) - shiftxc;
02623                                         float xold = x*cang/scale + ysang ;
02624                                         float yold = x*sang/scale + ycang ;
02625                                         //  in quadri_background, wrap around is not done circulantly; if (xold,yold) is not in the image, then it's replaced by (ix,iy)
02626                                         (*ret)(ix,iy) = Util::quadri_background(xold+1.0f, yold+1.0f, nx, ny, get_data(),ix+1,iy+1);
02627                                            //have to add one as quadri uses Fortran counting
02628                                 }
02629                         }
02630                 set_array_offsets(saved_offsets);
02631                 return ret;
02632         } else {
02633                 throw ImageDimensionException("Volume not currently supported");
02634         }
02635 }
02636 
02637 #define in(i,j,k)          in[i+(j+(k*ny))*(size_t)nx]
02638 EMData*
02639 EMData::rot_scale_trans(const Transform &RA) {
02640 
02641         EMData* ret = copy_head();
02642         float *in = this->get_data();
02643         vector<int> saved_offsets = get_array_offsets();
02644         set_array_offsets(0,0,0);
02645         Vec3f translations = RA.get_trans();
02646         Transform RAinv = RA.inverse();
02647 
02648         if (1 >= ny)  throw ImageDimensionException("Can't rotate 1D image");
02649         if (nz < 2) {
02650         float  p1, p2, p3, p4;
02651         float delx = translations.at(0);
02652         float dely = translations.at(1);
02653         delx = restrict2(delx, nx);
02654         dely = restrict2(dely, ny);
02655         int xc = nx/2;
02656         int yc = ny/2;
02657 //         shifted center for rotation
02658         float shiftxc = xc + delx;
02659         float shiftyc = yc + dely;
02660                 for (int iy = 0; iy < ny; iy++) {
02661                         float y = float(iy) - shiftyc;
02662                         float ysang = y*RAinv[0][1]+xc;
02663                         float ycang = y*RAinv[1][1]+yc;
02664                         for (int ix = 0; ix < nx; ix++) {
02665                                 float x = float(ix) - shiftxc;
02666                                 float xold = x*RAinv[0][0] + ysang;
02667                                 float yold = x*RAinv[1][0] + ycang;
02668 
02669                                 xold = restrict1(xold, nx);
02670                                 yold = restrict1(yold, ny);
02671 
02672                                 int xfloor = int(xold);
02673                                 int yfloor = int(yold);
02674                                 float t = xold-xfloor;
02675                                 float u = yold-yfloor;
02676                                 if(xfloor == nx -1 && yfloor == ny -1) {
02677 
02678                                     p1 =in[xfloor   + yfloor*ny];
02679                                         p2 =in[ yfloor*ny];
02680                                         p3 =in[0];
02681                                         p4 =in[xfloor];
02682                                 } else if(xfloor == nx - 1) {
02683 
02684                                         p1 =in[xfloor   + yfloor*ny];
02685                                         p2 =in[           yfloor*ny];
02686                                         p3 =in[          (yfloor+1)*ny];
02687                                         p4 =in[xfloor   + (yfloor+1)*ny];
02688                                 } else if(yfloor == ny - 1) {
02689 
02690                                         p1 =in[xfloor   + yfloor*ny];
02691                                         p2 =in[xfloor+1 + yfloor*ny];
02692                                         p3 =in[xfloor+1 ];
02693                                         p4 =in[xfloor   ];
02694                                 } else {
02695                                         p1 =in[xfloor   + yfloor*ny];
02696                                         p2 =in[xfloor+1 + yfloor*ny];
02697                                         p3 =in[xfloor+1 + (yfloor+1)*ny];
02698                                         p4 =in[xfloor   + (yfloor+1)*ny];
02699                                 }
02700                                 (*ret)(ix,iy) = p1 + u * ( p4 - p1) + t * ( p2 - p1 + u *(p3-p2-p4+p1));
02701                         } //ends x loop
02702                 } // ends y loop
02703                 set_array_offsets(saved_offsets);
02704                 return ret;
02705         } else {
02706 //               This begins the 3D version trilinear interpolation.
02707 
02708         float delx = translations.at(0);
02709         float dely = translations.at(1);
02710         float delz = translations.at(2);
02711         delx = restrict2(delx, nx);
02712         dely = restrict2(dely, ny);
02713         delz = restrict2(delz, nz);
02714         int xc = nx/2;
02715         int yc = ny/2;
02716         int zc = nz/2;
02717 //         shifted center for rotation
02718         float shiftxc = xc + delx;
02719         float shiftyc = yc + dely;
02720         float shiftzc = zc + delz;
02721 
02722                 for (int iz = 0; iz < nz; iz++) {
02723                         float z = float(iz) - shiftzc;
02724                         float xoldz = z*RAinv[0][2]+xc;
02725                         float yoldz = z*RAinv[1][2]+yc;
02726                         float zoldz = z*RAinv[2][2]+zc;
02727                         for (int iy = 0; iy < ny; iy++) {
02728                                 float y = float(iy) - shiftyc;
02729                                 float xoldzy = xoldz + y*RAinv[0][1] ;
02730                                 float yoldzy = yoldz + y*RAinv[1][1] ;
02731                                 float zoldzy = zoldz + y*RAinv[2][1] ;
02732                                 for (int ix = 0; ix < nx; ix++) {
02733                                         float x = float(ix) - shiftxc;
02734                                         float xold = xoldzy + x*RAinv[0][0] ;
02735                                         float yold = yoldzy + x*RAinv[1][0] ;
02736                                         float zold = zoldzy + x*RAinv[2][0] ;
02737 
02738                                         xold = restrict1(xold, nx);
02739                                         yold = restrict1(yold, ny);
02740                                         zold = restrict1(zold, nz);
02741 
02742 
02743                                         int IOX = int(xold);
02744                                         int IOY = int(yold);
02745                                         int IOZ = int(zold);
02746 
02747                                         #ifdef _WIN32
02748                                         int IOXp1 = _cpp_min( nx-1 ,IOX+1);
02749                                         #else
02750                                         int IOXp1 = std::min( nx-1 ,IOX+1);
02751                                         #endif  //_WIN32
02752 
02753                                         #ifdef _WIN32
02754                                         int IOYp1 = _cpp_min( ny-1 ,IOY+1);
02755                                         #else
02756                                         int IOYp1 = std::min( ny-1 ,IOY+1);
02757                                         #endif  //_WIN32
02758 
02759                                         #ifdef _WIN32
02760                                         int IOZp1 = _cpp_min( nz-1 ,IOZ+1);
02761                                         #else
02762                                         int IOZp1 = std::min( nz-1 ,IOZ+1);
02763                                         #endif  //_WIN32
02764 
02765                                         float dx = xold-IOX;
02766                                         float dy = yold-IOY;
02767                                         float dz = zold-IOZ;
02768 
02769                                         float a1 = in(IOX,IOY,IOZ);
02770                                         float a2 = in(IOXp1,IOY,IOZ) - in(IOX,IOY,IOZ);
02771                                         float a3 = in(IOX,IOYp1,IOZ) - in(IOX,IOY,IOZ);
02772                                         float a4 = in(IOX,IOY,IOZp1) - in(IOX,IOY,IOZ);
02773                                         float a5 = in(IOX,IOY,IOZ) - in(IOXp1,IOY,IOZ) - in(IOX,IOYp1,IOZ) + in(IOXp1,IOYp1,IOZ);
02774                                         float a6 = in(IOX,IOY,IOZ) - in(IOXp1,IOY,IOZ) - in(IOX,IOY,IOZp1) + in(IOXp1,IOY,IOZp1);
02775                                         float a7 = in(IOX,IOY,IOZ) - in(IOX,IOYp1,IOZ) - in(IOX,IOY,IOZp1) + in(IOX,IOYp1,IOZp1);
02776                                         float a8 = in(IOXp1,IOY,IOZ) + in(IOX,IOYp1,IOZ)+ in(IOX,IOY,IOZp1)
02777                                                         - in(IOX,IOY,IOZ)- in(IOXp1,IOYp1,IOZ) - in(IOXp1,IOY,IOZp1)
02778                                                         - in(IOX,IOYp1,IOZp1) + in(IOXp1,IOYp1,IOZp1);
02779                                         (*ret)(ix,iy,iz) = a1 + dz*(a4 + a6*dx + (a7 + a8*dx)*dy) + a3*dy + dx*(a2 + a5*dy);
02780                                 } //ends x loop
02781                         } // ends y loop
02782                 } // ends z loop
02783 
02784                 set_array_offsets(saved_offsets);
02785                 return ret;
02786 
02787 /*     This entire section has to go somewhere for quadratic 3D interpolation PAP 12/29/07
02788 //               This begins the 3D version triquadratic interpolation.
02789 
02790         float delx = translations.at(0);
02791         float dely = translations.at(1);
02792         float delz = translations.at(2);
02793         if(delx >= 0.0f) { delx = fmod(delx, float(nx));} else {delx = -fmod(-delx, float(nx));}
02794         if(dely >= 0.0f) { dely = fmod(dely, float(ny));} else {dely = -fmod(-dely, float(ny));}
02795         if(dely >= 0.0f) { delz = fmod(delz, float(nz));} else {delz = -fmod(-delz, float(nz));}
02796         int xc = nx/2;
02797         int yc = ny/2;
02798         int zc = nz/2;
02799 //         shifted center for rotation
02800         float shiftxc = xc + delx;
02801         float shiftyc = yc + dely;
02802         float shiftzc = zc + delz;
02803 //                  set up array to use later
02804 //
02805                 int xArr[27];
02806                 int yArr[27];
02807                 int zArr[27];
02808                 float fdata[27];
02809 
02810                 for (int iL=0; iL<27 ; iL++){  // need this indexing array later
02811                         xArr[iL]  =  (int) (fmod((float)iL,3.0f) - 1.0f);
02812                         yArr[iL]  =  (int)( fmod( ((float) (iL/3) ),3.0f)- 1.0f);
02813                         zArr[iL]  = ((int) (iL/9)  ) -1;
02814 //                      printf("iL=%d, \t xArr=%d, \t yArr=%d, \t zArr=%d \n",iL, xArr[iL],yArr[iL],zArr[iL]);
02815                 }
02816 
02817 //              for (int iz = 0; iz < nz; iz++) {for (int iy = 0; iy < ny; iy++) {for (int ix = 0; ix < nx; ix++) {
02818 //                    (*ret)(ix,iy,iz) = 0;}}}   // initialize returned data
02819 
02820                 for (int iz = 0; iz < nz; iz++) {
02821                         float z = float(iz) - shiftzc;
02822                         float xoldz = z*RAinv[0][2]+xc;
02823                         float yoldz = z*RAinv[1][2]+yc;
02824                         float zoldz = z*RAinv[2][2]+zc;
02825                         for (int iy = 0; iy < ny; iy++) {
02826                                 float y = float(iy) - shiftyc;
02827                                 float xoldzy = xoldz + y*RAinv[0][1] ;
02828                                 float yoldzy = yoldz + y*RAinv[1][1] ;
02829                                 float zoldzy = zoldz + y*RAinv[2][1] ;
02830                                 for (int ix = 0; ix < nx; ix++) {
02831                                         float x = float(ix) - shiftxc;
02832                                         float xold = xoldzy + x*RAinv[0][0] ;
02833                                         float yold = yoldzy + x*RAinv[1][0] ;
02834                                         float zold = zoldzy + x*RAinv[2][0] ;
02835 
02836 
02837                                 if (xold < 0.0f) xold = fmod((int(xold/float(nx))+1)*nx-xold, float(nx));
02838                                 else if (xold > (float) (nx-1) ) xold = fmod(xold, float(nx));
02839                                 if (yold < 0.0f) yold =fmod((int(yold/float(ny))+1)*ny-yold, float(ny));
02840                                 else if (yold > (float) (ny-1) ) yold = fmod(yold, float(ny));
02841                                 if (zold < 0.0f) zold =fmod((int(zold/float(nz))+1)*nz-zold, float(nz));
02842                                 else if (zold > (float) (nz-1) ) zold = fmod(zold, float(nz));
02843 
02844                                 //  what follows does not accelerate the code; moreover, I doubt it is correct PAP 12/29/07
02845                                 //while ( xold >= (float)(nx) )  xold -= nx;
02846                                 //while ( xold < 0.0f )         xold += nx;
02847                                 //while ( yold >= (float)(ny) )  yold -= ny;
02848                                 //while ( yold < 0.0f )         yold += ny;
02849                                 //while ( zold >= (float)(nz) )  zold -= nz;
02850                                 //while ( zold < 0.0f )         zold += nz;
02851 
02852 //         This is currently coded the way  SPIDER coded it,
02853 //            changing floor to round  in the next 3 lines below may be better
02854 //                                      int IOX = (int) floor(xold); // This is the center of the array
02855 //                                      int IOY = (int) floor(yold ); // In the next loop we interpolate
02856 //                                      int IOZ = (int) floor(zold ); //  If floor is used dx is positive
02857                                         int IOX = int(xold);
02858                                         int IOY = int(yold);
02859                                         int IOZ = int(zold);
02860 
02861                                         float dx = xold-IOX; //remainder(xold,1);  //  now |dx| <= .5
02862                                         float dy = yold-IOY; //remainder(yold,1);
02863                                         float dz = zold-IOZ; //remainder(zold,1);
02864 
02865 //                                      printf(" IOX=%d \t IOY=%d \t IOZ=%d \n", IOX, IOY, IOZ);
02866 //                                      if (IOX>=0 && IOX<nx  && IOY>=0 && IOY < ny && IOZ >= 0 && IOZ < nz ) {
02867 //                                              ROTATED POSITION IS INSIDE OF VOLUME
02868 //                                              FIND INTENSITIES ON 3x3x3 COORDINATE GRID;
02869 //                                     Solution is wrapped
02870                                                 for  (int iL=0; iL<27 ; iL++){
02871                                                         int xCoor = (int) fmod(IOX+xArr[iL] + nx + .0001f, (float) nx);
02872                                                         int yCoor = (int) fmod(IOY+yArr[iL] + ny + .0001f, (float) ny);
02873                                                         int zCoor = (int) fmod(IOZ+zArr[iL] + nz + .0001f, (float) nz);
02874                                                         fdata[iL] = (*this)( xCoor, yCoor ,zCoor );
02875 //                                                      if (iy==iz && iz==0){printf(" fdata=%f \n", fdata[iL]);}
02876 //                                              }
02877                                         }
02878 
02879                                         (*ret)(ix,iy,iz) = Util::triquad(dx, dy, dz, fdata);
02880 //                                      (*ret)(ix,iy,iz) = Util:: trilinear_interpolate(fdata[13],fdata[14],fdata[16],
02881 //                                                                                      fdata[17],fdata[22],fdata[23],
02882 //                                                                                      fdata[25],fdata[26],dx, dy, dz);
02883 //      p1 iL=13,   xArr= 0,         yArr= 0,         zArr= 0
02884 //      p2 iL=14,   xArr= 1,         yArr= 0,         zArr= 0
02885 //      p3 iL=16,   xArr= 0,         yArr= 1,         zArr= 0
02886 //      p4 iL=17,   xArr= 1,         yArr= 1,         zArr= 0
02887 //      p5 iL=22,   xArr= 0,         yArr= 0,         zArr= 1
02888 //      p6 iL=23,   xArr= 1,         yArr= 0,         zArr= 1
02889 //      p7 iL=25,   xArr= 0,         yArr= 1,         zArr= 1
02890 //      p8 iL=26,   xArr= 1,         yArr= 1,         zArr= 1
02891 
02892 
02893 
02894                                 } //ends x loop
02895                         } // ends y loop
02896                 } // ends z loop
02897 
02898                 set_array_offsets(saved_offsets);
02899                 return ret;
02900 */
02901         }
02902 }
02903 #undef  in
02904 
02905 // new function added for background option
02906 #define in(i,j,k)          in[i+(j+(k*ny))*(size_t)nx]
02907 EMData*
02908 EMData::rot_scale_trans_background(const Transform &RA) {
02909         EMData* ret = copy_head();
02910         float *in = this->get_data();
02911         vector<int> saved_offsets = get_array_offsets();
02912         set_array_offsets(0,0,0);
02913         Vec3f translations = RA.get_trans();
02914         Transform RAinv = RA.inverse();
02915 
02916         if (1 >= ny)  throw ImageDimensionException("Can't rotate 1D image");
02917         if (nz < 2) {
02918         float  p1, p2, p3, p4;
02919         float delx = translations.at(0);
02920         float dely = translations.at(1);
02921         delx = restrict2(delx, nx);
02922         dely = restrict2(dely, ny);
02923         int xc = nx/2;
02924         int yc = ny/2;
02925 //         shifted center for rotation
02926         float shiftxc = xc + delx;
02927         float shiftyc = yc + dely;
02928                 for (int iy = 0; iy < ny; iy++) {
02929                         float y = float(iy) - shiftyc;
02930                         float ysang = y*RAinv[0][1]+xc;
02931                         float ycang = y*RAinv[1][1]+yc;
02932                         for (int ix = 0; ix < nx; ix++) {
02933                                 float x = float(ix) - shiftxc;
02934                                 float xold = x*RAinv[0][0] + ysang;
02935                                 float yold = x*RAinv[1][0] + ycang;
02936 
02937                                 // if (xold,yold) is outside the image, then let xold = ix and yold = iy
02938 
02939                 if ( (xold < 0.0f) || (xold >= (float)(nx)) || (yold < 0.0f) || (yold >= (float)(ny)) ){
02940                                     xold = (float)ix;
02941                                         yold = (float)iy;
02942                                 }
02943 
02944                                 int xfloor = int(xold);
02945                                 int yfloor = int(yold);
02946                                 float t = xold-xfloor;
02947                                 float u = yold-yfloor;
02948                                 if(xfloor == nx -1 && yfloor == ny -1) {
02949 
02950                                     p1 =in[xfloor   + yfloor*ny];
02951                                         p2 =in[ yfloor*ny];
02952                                         p3 =in[0];
02953                                         p4 =in[xfloor];
02954                                 } else if(xfloor == nx - 1) {
02955 
02956                                         p1 =in[xfloor   + yfloor*ny];
02957                                         p2 =in[           yfloor*ny];
02958                                         p3 =in[          (yfloor+1)*ny];
02959                                         p4 =in[xfloor   + (yfloor+1)*ny];
02960                                 } else if(yfloor == ny - 1) {
02961 
02962                                         p1 =in[xfloor   + yfloor*ny];
02963                                         p2 =in[xfloor+1 + yfloor*ny];
02964                                         p3 =in[xfloor+1 ];
02965                                         p4 =in[xfloor   ];
02966                                 } else {
02967 
02968                                         p1 =in[xfloor   + yfloor*ny];
02969                                         p2 =in[xfloor+1 + yfloor*ny];
02970                                         p3 =in[xfloor+1 + (yfloor+1)*ny];
02971                                         p4 =in[xfloor   + (yfloor+1)*ny];
02972                                 }
02973                                 (*ret)(ix,iy) = p1 + u * ( p4 - p1) + t * ( p2 - p1 + u *(p3-p2-p4+p1));
02974                         } //ends x loop
02975                 } // ends y loop
02976                 set_array_offsets(saved_offsets);
02977                 return ret;
02978         } else {
02979 //               This begins the 3D version trilinear interpolation.
02980 
02981         float delx = translations.at(0);
02982         float dely = translations.at(1);
02983         float delz = translations.at(2);
02984         delx = restrict2(delx, nx);
02985         dely = restrict2(dely, ny);
02986         delz = restrict2(delz, nz);
02987         int xc = nx/2;
02988         int yc = ny/2;
02989         int zc = nz/2;
02990 //         shifted center for rotation
02991         float shiftxc = xc + delx;
02992         float shiftyc = yc + dely;
02993         float shiftzc = zc + delz;
02994 
02995                 for (int iz = 0; iz < nz; iz++) {
02996                         float z = float(iz) - shiftzc;
02997                         float xoldz = z*RAinv[0][2]+xc;
02998                         float yoldz = z*RAinv[1][2]+yc;
02999                         float zoldz = z*RAinv[2][2]+zc;
03000                         for (int iy = 0; iy < ny; iy++) {
03001                                 float y = float(iy) - shiftyc;
03002                                 float xoldzy = xoldz + y*RAinv[0][1] ;
03003                                 float yoldzy = yoldz + y*RAinv[1][1] ;
03004                                 float zoldzy = zoldz + y*RAinv[2][1] ;
03005                                 for (int ix = 0; ix < nx; ix++) {
03006                                         float x = float(ix) - shiftxc;
03007                                         float xold = xoldzy + x*RAinv[0][0] ;
03008                                         float yold = yoldzy + x*RAinv[1][0] ;
03009                                         float zold = zoldzy + x*RAinv[2][0] ;
03010 
03011                                         // if (xold,yold,zold) is outside the image, then let xold = ix, yold = iy and zold=iz
03012 
03013                     if ( (xold < 0.0f) || (xold >= (float)(nx)) || (yold < 0.0f) || (yold >= (float)(ny))  || (zold < 0.0f) || (zold >= (float)(nz)) ){
03014                                          xold = (float)ix;
03015                                              yold = (float)iy;
03016                                                  zold = (float)iz;
03017                                         }
03018 
03019                                         int IOX = int(xold);
03020                                         int IOY = int(yold);
03021                                         int IOZ = int(zold);
03022 
03023                                         #ifdef _WIN32
03024                                         int IOXp1 = _cpp_min( nx-1 ,IOX+1);
03025                                         #else
03026                                         int IOXp1 = std::min( nx-1 ,IOX+1);
03027                                         #endif  //_WIN32
03028 
03029                                         #ifdef _WIN32
03030                                         int IOYp1 = _cpp_min( ny-1 ,IOY+1);
03031                                         #else
03032                                         int IOYp1 = std::min( ny-1 ,IOY+1);
03033                                         #endif  //_WIN32
03034 
03035                                         #ifdef _WIN32
03036                                         int IOZp1 = _cpp_min( nz-1 ,IOZ+1);
03037                                         #else
03038                                         int IOZp1 = std::min( nz-1 ,IOZ+1);
03039                                         #endif  //_WIN32
03040 
03041                                         float dx = xold-IOX;
03042                                         float dy = yold-IOY;
03043                                         float dz = zold-IOZ;
03044 
03045                                         float a1 = in(IOX,IOY,IOZ);
03046                                         float a2 = in(IOXp1,IOY,IOZ) - in(IOX,IOY,IOZ);
03047                                         float a3 = in(IOX,IOYp1,IOZ) - in(IOX,IOY,IOZ);
03048                                         float a4 = in(IOX,IOY,IOZp1) - in(IOX,IOY,IOZ);
03049                                         float a5 = in(IOX,IOY,IOZ) - in(IOXp1,IOY,IOZ) - in(IOX,IOYp1,IOZ) + in(IOXp1,IOYp1,IOZ);
03050                                         float a6 = in(IOX,IOY,IOZ) - in(IOXp1,IOY,IOZ) - in(IOX,IOY,IOZp1) + in(IOXp1,IOY,IOZp1);
03051                                         float a7 = in(IOX,IOY,IOZ) - in(IOX,IOYp1,IOZ) - in(IOX,IOY,IOZp1) + in(IOX,IOYp1,IOZp1);
03052                                         float a8 = in(IOXp1,IOY,IOZ) + in(IOX,IOYp1,IOZ)+ in(IOX,IOY,IOZp1)
03053                                                         - in(IOX,IOY,IOZ)- in(IOXp1,IOYp1,IOZ) - in(IOXp1,IOY,IOZp1)
03054                                                         - in(IOX,IOYp1,IOZp1) + in(IOXp1,IOYp1,IOZp1);
03055                                         (*ret)(ix,iy,iz) = a1 + dz*(a4 + a6*dx + (a7 + a8*dx)*dy) + a3*dy + dx*(a2 + a5*dy);
03056                                 } //ends x loop
03057                         } // ends y loop
03058                 } // ends z loop
03059 
03060                 set_array_offsets(saved_offsets);
03061                 return ret;
03062 
03063         }
03064 }
03065 #undef  in
03066 
03067 
03068 /*
03069 EMData*
03070 EMData::rot_scale_conv(float ang, float delx, float dely, Util::KaiserBessel& kb) {
03071         int nxn, nyn, nzn;
03072         const float scale=0.5;
03073         float  sum, w;
03074         if (1 >= ny)
03075                 throw ImageDimensionException("Can't rotate 1D image");
03076         if (1 < nz)
03077                 throw ImageDimensionException("Volume not currently supported");
03078         nxn=nx/2;nyn=ny/2;nzn=nz/2;
03079 
03080         int K = kb.get_window_size();
03081         int kbmin = -K/2;
03082         int kbmax = -kbmin;
03083         int kbc = kbmax+1;
03084         vector<int> saved_offsets = get_array_offsets();
03085         set_array_offsets(0,0,0);
03086         EMData* ret = new EMData();
03087 #ifdef _WIN32
03088         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03089 #else
03090         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03091 #endif  //_WIN32
03092         ret->to_zero();  //we will leave margins zeroed.
03093         delx = fmod(delx, float(nxn));
03094         dely = fmod(dely, float(nyn));
03095         // center of big image,
03096         int xc = nxn;
03097         int ixs = nxn%2;  // extra shift on account of odd-sized images
03098         int yc = nyn;
03099         int iys = nyn%2;
03100         // center of small image
03101         int xcn = nxn/2;
03102         int ycn = nyn/2;
03103         // shifted center for rotation
03104         float shiftxc = xcn + delx;
03105         float shiftyc = ycn + dely;
03106         // bounds if origin at center
03107         float ymin = -ny/2.0f;
03108         float xmin = -nx/2.0f;
03109         float ymax = -ymin;
03110         float xmax = -xmin;
03111         if (0 == nx%2) xmax--;
03112         if (0 == ny%2) ymax--;
03113         // trig
03114         float cang = cos(ang);
03115         float sang = sin(ang);
03116                 for (int iy = 0; iy < nyn; iy++) {
03117                         float y = float(iy) - shiftyc;
03118                         float ycang = y*cang/scale + yc;
03119                         float ysang = -y*sang/scale + xc;
03120                         for (int ix = 0; ix < nxn; ix++) {
03121                                 float x = float(ix) - shiftxc;
03122                                 float xold = x*cang/scale + ysang-ixs;// have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
03123                                 float yold = x*sang/scale + ycang-iys;
03124                                 int inxold = int(Util::round(xold)); int inyold = int(Util::round(yold));
03125                                      sum=0.0f;    w=0.0f;
03126                                 if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2 )  {
03127                                   for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03128                                   float q = kb.i0win_tab(xold - inxold-m1)*kb.i0win_tab(yold - inyold-m2);
03129                                   sum += (*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny)*q; w+=q;}}
03130                                 }else{
03131                                   for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03132                                   float q =kb.i0win_tab(xold - inxold-m1)*kb.i0win_tab(yold - inyold-m2);
03133                                   sum += (*this)(inxold+m1,inyold+m2)*q;w+=q;}}
03134                                 }
03135                                 (*ret)(ix,iy)=sum/w;
03136                         }
03137                 }
03138         set_array_offsets(saved_offsets);
03139         return ret;
03140 }
03141 */
03142 
03143 EMData* EMData::rot_scale_conv(float ang, float delx, float dely, Util::KaiserBessel& kb, float scale_input) {
03144         int nxn, nyn, nzn;
03145         if(scale_input == 0.0f) scale_input = 1.0f;
03146         //const float scale=0.5;
03147         float  scale = 0.5f*scale_input;
03148         float  sum, w;
03149         if (1 >= ny)
03150                 throw ImageDimensionException("Can't rotate 1D image");
03151         if (1 < nz)
03152                 throw ImageDimensionException("Volume not currently supported");
03153         nxn=nx/2;nyn=ny/2;nzn=nz/2;
03154 
03155         int K = kb.get_window_size();
03156         int kbmin = -K/2;
03157         int kbmax = -kbmin;
03158         int kbc = kbmax+1;
03159         vector<int> saved_offsets = get_array_offsets();
03160         set_array_offsets(0,0,0);
03161         EMData* ret = this->copy_head();
03162 #ifdef _WIN32
03163         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03164 #else
03165         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03166 #endif  //_WIN32
03167         //ret->to_zero();  //we will leave margins zeroed.
03168         delx = restrict2(delx, nx);
03169         dely = restrict2(dely, ny);
03170         // center of big image,
03171         int xc = nxn;
03172         int ixs = nxn%2;  // extra shift on account of odd-sized images
03173         int yc = nyn;
03174         int iys = nyn%2;
03175         // center of small image
03176         int xcn = nxn/2;
03177         int ycn = nyn/2;
03178         // shifted center for rotation
03179         float shiftxc = xcn + delx;
03180         float shiftyc = ycn + dely;
03181         // bounds if origin at center
03182         float ymin = -ny/2.0f;
03183         float xmin = -nx/2.0f;
03184         float ymax = -ymin;
03185         float xmax = -xmin;
03186         if (0 == nx%2) xmax--;
03187         if (0 == ny%2) ymax--;
03188 
03189         float   *t = (float*)calloc(kbmax-kbmin+1, sizeof(float));
03190 
03191         // trig
03192         float cang = cos(ang);
03193         float sang = sin(ang);
03194         for (int iy = 0; iy < nyn; iy++) {
03195                 float y = float(iy) - shiftyc;
03196                 float ycang = y*cang/scale + yc;
03197                 float ysang = -y*sang/scale + xc;
03198                 for (int ix = 0; ix < nxn; ix++) {
03199                         float x = float(ix) - shiftxc;
03200                         float xold = x*cang/scale + ysang-ixs;// have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
03201                         float yold = x*sang/scale + ycang-iys;
03202 
03203                         xold = restrict1(xold, nx);
03204                         yold = restrict1(yold, ny);
03205 
03206                         int inxold = int(Util::round(xold)); int inyold = int(Util::round(yold));
03207                         sum=0.0f;    w=0.0f;
03208                         for (int m1 =kbmin; m1 <=kbmax; m1++) t[m1-kbmin] = kb.i0win_tab(xold - inxold-m1);
03209                         if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2 )  {
03210                                 for (int m2 =kbmin; m2 <=kbmax; m2++) {
03211                                         float qt = kb.i0win_tab(yold - inyold-m2);
03212                                         for (int m1 =kbmin; m1 <=kbmax; m1++) {
03213                                                 float q = t[m1-kbmin]*qt;
03214                                                 sum += (*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny)*q; w+=q;
03215                                         }
03216                                 }
03217                         } else {
03218                                 for (int m2 =kbmin; m2 <=kbmax; m2++) {
03219                                         float qt = kb.i0win_tab(yold - inyold-m2);
03220                                         for (int m1 =kbmin; m1 <=kbmax; m1++) {
03221                                                 float q = t[m1-kbmin]*qt;
03222                                                 sum += (*this)(inxold+m1,inyold+m2)*q; w+=q;}
03223                                         }
03224                         }
03225                         (*ret)(ix,iy)=sum/w;
03226                 }
03227         }
03228         if (t) free(t);
03229         set_array_offsets(saved_offsets);
03230         return ret;
03231 }
03232 
03233 // Notes by Yang on 10/02/07
03234 // This function is at first just a test, but I found it is slightly faster (about 10%) than rot_scale_conv_new(), so I decided to retain it.
03235 EMData* EMData::rot_scale_conv7(float ang, float delx, float dely, Util::KaiserBessel& kb, float scale_input) {
03236         int nxn, nyn, nzn;
03237         float  scale = 0.5f*scale_input;
03238         float  sum, w;
03239         if (1 >= ny)
03240                 throw ImageDimensionException("Can't rotate 1D image");
03241         if (1 < nz)
03242                 throw ImageDimensionException("Volume not currently supported");
03243         nxn = nx/2; nyn=ny/2; nzn=nz/2;
03244 
03245         int K = kb.get_window_size();
03246         int kbmin = -K/2;
03247         int kbmax = -kbmin;
03248         int kbc = kbmax+1;
03249         vector<int> saved_offsets = get_array_offsets();
03250         set_array_offsets(0,0,0);
03251         EMData* ret = this->copy_head();
03252 #ifdef _WIN32
03253         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03254 #else
03255         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03256 #endif  //_WIN32
03257         //ret->to_zero();  //we will leave margins zeroed.
03258         delx = restrict2(delx, nx);
03259         dely = restrict2(dely, ny);
03260         // center of big image,
03261         int xc = nxn;
03262         int ixs = nxn%2;  // extra shift on account of odd-sized images
03263         int yc = nyn;
03264         int iys = nyn%2;
03265         // center of small image
03266         int xcn = nxn/2;
03267         int ycn = nyn/2;
03268         // shifted center for rotation
03269         float shiftxc = xcn + delx;
03270         float shiftyc = ycn + dely;
03271         // bounds if origin at center
03272         float ymin = -ny/2.0f;
03273         float xmin = -nx/2.0f;
03274         float ymax = -ymin;
03275         float xmax = -xmin;
03276         if (0 == nx%2) xmax--;
03277         if (0 == ny%2) ymax--;
03278 
03279         float   *t = (float*)calloc(kbmax-kbmin+1, sizeof(float));
03280 
03281         // trig
03282         float cang = cos(ang);
03283         float sang = sin(ang);
03284         for (int iy = 0; iy < nyn; iy++) {
03285                 float y = float(iy) - shiftyc;
03286                 float ycang = y*cang/scale + yc;
03287                 float ysang = -y*sang/scale + xc;
03288                 for (int ix = 0; ix < nxn; ix++) {
03289                         float x = float(ix) - shiftxc;
03290                         float xold = x*cang/scale + ysang-ixs;// have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
03291                         float yold = x*sang/scale + ycang-iys;
03292 
03293                         xold = restrict1(xold, nx);
03294                         yold = restrict1(yold, ny);
03295 
03296                         int inxold = int(Util::round(xold)); int inyold = int(Util::round(yold));
03297                         sum=0.0f;    w=0.0f;
03298 
03299                         float tablex1 = kb.i0win_tab(xold-inxold+3);
03300                         float tablex2 = kb.i0win_tab(xold-inxold+2);
03301                         float tablex3 = kb.i0win_tab(xold-inxold+1);
03302                         float tablex4 = kb.i0win_tab(xold-inxold);
03303                         float tablex5 = kb.i0win_tab(xold-inxold-1);
03304                         float tablex6 = kb.i0win_tab(xold-inxold-2);
03305                         float tablex7 = kb.i0win_tab(xold-inxold-3);
03306 
03307                         float tabley1 = kb.i0win_tab(yold-inyold+3);
03308                         float tabley2 = kb.i0win_tab(yold-inyold+2);
03309                         float tabley3 = kb.i0win_tab(yold-inyold+1);
03310                         float tabley4 = kb.i0win_tab(yold-inyold);
03311                         float tabley5 = kb.i0win_tab(yold-inyold-1);
03312                         float tabley6 = kb.i0win_tab(yold-inyold-2);
03313                         float tabley7 = kb.i0win_tab(yold-inyold-3);
03314 
03315                         int x1, x2, x3, x4, x5, x6, x7, y1, y2, y3, y4, y5, y6, y7;
03316 
03317                         if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2 )  {
03318                                 x1 = (inxold-3+nx)%nx;
03319                                 x2 = (inxold-2+nx)%nx;
03320                                 x3 = (inxold-1+nx)%nx;
03321                                 x4 = (inxold  +nx)%nx;
03322                                 x5 = (inxold+1+nx)%nx;
03323                                 x6 = (inxold+2+nx)%nx;
03324                                 x7 = (inxold+3+nx)%nx;
03325 
03326                                 y1 = (inyold-3+ny)%ny;
03327                                 y2 = (inyold-2+ny)%ny;
03328                                 y3 = (inyold-1+ny)%ny;
03329                                 y4 = (inyold  +ny)%ny;
03330                                 y5 = (inyold+1+ny)%ny;
03331                                 y6 = (inyold+2+ny)%ny;
03332                                 y7 = (inyold+3+ny)%ny;
03333                         } else {
03334                                 x1 = inxold-3;
03335                                 x2 = inxold-2;
03336                                 x3 = inxold-1;
03337                                 x4 = inxold;
03338                                 x5 = inxold+1;
03339                                 x6 = inxold+2;
03340                                 x7 = inxold+3;
03341 
03342                                 y1 = inyold-3;
03343                                 y2 = inyold-2;
03344                                 y3 = inyold-1;
03345                                 y4 = inyold;
03346                                 y5 = inyold+1;
03347                                 y6 = inyold+2;
03348                                 y7 = inyold+3;
03349                         }
03350                         sum    =   ( (*this)(x1,y1)*tablex1 + (*this)(x2,y1)*tablex2 + (*this)(x3,y1)*tablex3 +
03351                                      (*this)(x4,y1)*tablex4 + (*this)(x5,y1)*tablex5 + (*this)(x6,y1)*tablex6 +
03352                                      (*this)(x7,y1)*tablex7 ) * tabley1 +
03353                                    ( (*this)(x1,y2)*tablex1 + (*this)(x2,y2)*tablex2 + (*this)(x3,y2)*tablex3 +
03354                                      (*this)(x4,y2)*tablex4 + (*this)(x5,y2)*tablex5 + (*this)(x6,y2)*tablex6 +
03355                                      (*this)(x7,y2)*tablex7 ) * tabley2 +
03356                                    ( (*this)(x1,y3)*tablex1 + (*this)(x2,y3)*tablex2 + (*this)(x3,y3)*tablex3 +
03357                                      (*this)(x4,y3)*tablex4 + (*this)(x5,y3)*tablex5 + (*this)(x6,y3)*tablex6 +
03358                                      (*this)(x7,y3)*tablex7 ) * tabley3 +
03359                                    ( (*this)(x1,y4)*tablex1 + (*this)(x2,y4)*tablex2 + (*this)(x3,y4)*tablex3 +
03360                                      (*this)(x4,y4)*tablex4 + (*this)(x5,y4)*tablex5 + (*this)(x6,y4)*tablex6 +
03361                                      (*this)(x7,y4)*tablex7 ) * tabley4 +
03362                                    ( (*this)(x1,y5)*tablex1 + (*this)(x2,y5)*tablex2 + (*this)(x3,y5)*tablex3 +
03363                                      (*this)(x4,y5)*tablex4 + (*this)(x5,y5)*tablex5 + (*this)(x6,y5)*tablex6 +
03364                                      (*this)(x7,y5)*tablex7 ) * tabley5 +
03365                                    ( (*this)(x1,y6)*tablex1 + (*this)(x2,y6)*tablex2 + (*this)(x3,y6)*tablex3 +
03366                                      (*this)(x4,y6)*tablex4 + (*this)(x5,y6)*tablex5 + (*this)(x6,y6)*tablex6 +
03367                                      (*this)(x7,y6)*tablex7 ) * tabley6 +
03368                                    ( (*this)(x1,y7)*tablex1 + (*this)(x2,y7)*tablex2 + (*this)(x3,y7)*tablex3 +
03369                                      (*this)(x4,y7)*tablex4 + (*this)(x5,y7)*tablex5 + (*this)(x6,y7)*tablex6 +
03370                                      (*this)(x7,y7)*tablex7 ) * tabley7;
03371 
03372                         w = (tablex1+tablex2+tablex3+tablex4+tablex5+tablex6+tablex7) *
03373                             (tabley1+tabley2+tabley3+tabley4+tabley5+tabley6+tabley7);
03374 
03375                         (*ret)(ix,iy)=sum/w;
03376                 }
03377         }
03378         if (t) free(t);
03379         set_array_offsets(saved_offsets);
03380         return ret;
03381 }
03382 
03383 EMData* EMData::downsample(Util::sincBlackman& kb, float scale) {
03384 
03385         /*int M = kb.get_sB_size();
03386         int kbmin = -M/2;
03387         int kbmax = -kbmin;*/
03388 
03389         int nxn, nyn, nzn;
03390         nxn = (int)(nx*scale); nyn = (int)(ny*scale); nzn = (int)(nz*scale);
03391 
03392         vector<int> saved_offsets = get_array_offsets();
03393         set_array_offsets(0,0,0);
03394         EMData* ret = this->copy_head();
03395 #ifdef _WIN32
03396         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03397 #else
03398         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03399 #endif  //_WIN32
03400         ret->to_zero();  //we will leave margins zeroed.
03401 
03402         // scan new, find pixels in old
03403         if(nz == 1)
03404         {
03405                 for (int iy =0; iy < nyn; iy++) {
03406                         float y = float(iy)/scale;
03407                         for (int ix = 0; ix < nxn; ix++) {
03408                                 float x = float(ix)/scale;
03409                                 (*ret)(ix,iy) = this->get_pixel_filtered(x, y, 1.0f, kb);
03410                         }
03411                 }
03412         }
03413         else{
03414                 
03415                 for (int iz =0; iz < nzn; iz++) {
03416                         float z = float(iz)/scale;
03417                         for (int iy =0; iy < nyn; iy++) {
03418                                 float y = float(iy)/scale;
03419                                 for (int ix = 0; ix < nxn; ix++) {
03420                                         float x = float(ix)/scale;
03421                                         (*ret)(ix,iy,iz) = this->get_pixel_filtered(x, y, z, kb);
03422                                 }
03423                         }
03424                 }
03425         
03426         }
03427         set_array_offsets(saved_offsets);
03428         return ret;
03429 }
03430 
03431 
03432 EMData* EMData::rot_scale_conv_new(float ang, float delx, float dely, Util::KaiserBessel& kb, float scale_input) {
03433 
03434         if (scale_input == 0.0f) scale_input = 1.0f;
03435         float  scale = 0.5f*scale_input;
03436 
03437         if (1 >= ny)
03438                 throw ImageDimensionException("Can't rotate 1D image");
03439         if (1 < nz)
03440                 throw ImageDimensionException("Use rot_scale_conv_new_3D for volumes");
03441         int nxn = nx/2; int nyn = ny/2; int nzn = nz/2;
03442 
03443         vector<int> saved_offsets = get_array_offsets();
03444         set_array_offsets(0,0,0);
03445         EMData* ret = this->copy_head();
03446 #ifdef _WIN32
03447         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03448 #else
03449         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03450 #endif  //_WIN32
03451         //ret->to_zero();  //we will leave margins zeroed.
03452         delx = restrict2(delx, nx);
03453         dely = restrict2(dely, ny);
03454         // center of big image,
03455         int xc = nxn;
03456         int ixs = nxn%2;  // extra shift on account of odd-sized images
03457         int yc = nyn;
03458         int iys = nyn%2;
03459         // center of small image
03460         int xcn = nxn/2;
03461         int ycn = nyn/2;
03462         // shifted center for rotation
03463         float shiftxc = xcn + delx;
03464         float shiftyc = ycn + dely;
03465         // bounds if origin at center
03466         float ymin = -ny/2.0f;
03467         float xmin = -nx/2.0f;
03468         float ymax = -ymin;
03469         float xmax = -xmin;
03470         if (0 == nx%2) xmax--;
03471         if (0 == ny%2) ymax--;
03472 
03473         float* data = this->get_data();
03474 
03475         float cang = cos(ang);
03476         float sang = sin(ang);
03477         for (int iy = 0; iy < nyn; iy++) {
03478                 float y = float(iy) - shiftyc;
03479                 float ycang = y*cang/scale + yc;
03480                 float ysang = -y*sang/scale + xc;
03481                 for (int ix = 0; ix < nxn; ix++) {
03482                         float x = float(ix) - shiftxc;
03483                         float xold = x*cang/scale + ysang-ixs;// have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
03484                         float yold = x*sang/scale + ycang-iys;
03485 
03486                         (*ret)(ix,iy) = Util::get_pixel_conv_new(nx, ny, 1, xold, yold, 1, data, kb);
03487                 }
03488         }
03489         set_array_offsets(saved_offsets);
03490         return ret;
03491 }
03492 
03493 EMData* EMData::rot_scale_conv_new_3D(float phi, float theta, float psi, float delx, float dely, float delz, Util::KaiserBessel& kb, float scale_input, bool wrap) {
03494 
03495         if (scale_input == 0.0f) scale_input = 1.0f;
03496         float  scale = 0.5f*scale_input;
03497 
03498         if (1 >= ny)
03499                 throw ImageDimensionException("Can't rotate 1D image");
03500         int nxn = nx/2; int nyn = ny/2; int nzn = nz/2;
03501 
03502         vector<int> saved_offsets = get_array_offsets();
03503         set_array_offsets(0,0,0);
03504         EMData* ret = this->copy_head();
03505 #ifdef _WIN32
03506         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03507 #else
03508         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03509 #endif  //_WIN32
03510         //ret->to_zero();  //we will leave margins zeroed.
03511         if(wrap){
03512                 delx = restrict2(delx, nx);
03513                 dely = restrict2(dely, ny);
03514                 delz = restrict2(delz, nz);
03515         }
03516         // center of big image,
03517         int xc = nxn;
03518         int ixs = nxn%2;  // extra shift on account of odd-sized images
03519         int yc = nyn;
03520         int iys = nyn%2;
03521         int zc = nzn;
03522         int izs = nzn%2;
03523         // center of small image
03524         int xcn = nxn/2;
03525         int ycn = nyn/2;
03526         int zcn = nzn/2;
03527         // shifted center for rotation
03528         float shiftxc = xcn + delx;
03529         float shiftyc = ycn + dely;
03530         float shiftzc = zcn + delz;
03531         // bounds if origin at center
03532         float zmin = -nz/2.0f;
03533         float ymin = -ny/2.0f;
03534         float xmin = -nx/2.0f;
03535         float zmax = -zmin;
03536         float ymax = -ymin;
03537         float xmax = -xmin;
03538         if (0 == nx%2) xmax--;
03539         if (0 == ny%2) ymax--;
03540         if (0 == nz%2) zmax--;
03541 
03542         float* data = this->get_data();
03543 
03544         float cf = cos(phi);   float sf = sin(phi);
03545         float ct = cos(theta); float st = sin(theta);
03546         float cp = cos(psi);   float sp = sin(psi);
03547         // rotation matrix (the transpose is used in the loop to get (xold,yold,zold)):
03548         float a11 =  cp*ct*cf-sp*sf; float a12 =  cp*ct*sf+sp*cf; float a13 = -cp*st;
03549         float a21 = -sp*ct*cf-cp*sf; float a22 = -sp*ct*sf+cp*cf; float a23 =  sp*st;
03550         float a31 =  st*cf;          float a32 =  st*sf;          float a33 =  ct;
03551         for (int iz = 0; iz < nzn; iz++) {
03552                 float z = (float(iz) - shiftzc)/scale;
03553                 float zco1 = a31*z+xc;
03554                 float zco2 = a32*z+yc;
03555                 float zco3 = a33*z+zc;
03556                 for (int iy = 0; iy < nyn; iy++) {
03557                         float y = (float(iy) - shiftyc)/scale;
03558                         float yco1 = zco1+a21*y;
03559                         float yco2 = zco2+a22*y;
03560                         float yco3 = zco3+a23*y;
03561                         for (int ix = 0; ix < nxn; ix++) {
03562                                 float x = (float(ix) - shiftxc)/scale;
03563                                 float xold = yco1+a11*x-ixs; //have to add the fraction on account of odd-sized images for which Fourier zero-padding changes the center location
03564                                 float yold = yco2+a12*x-iys;
03565                                 float zold = yco3+a13*x-izs;
03566                                 if(!wrap && (xold<0.0 || xold>nx-1 || yold<0.0 || yold>ny-1 || zold<0.0 || zold>nz-1))
03567                                         (*ret)(ix,iy,iz) = 0.0;
03568                                 else
03569                                         (*ret)(ix,iy,iz) = Util::get_pixel_conv_new(nx, ny, nz, xold, yold, zold, data, kb);
03570                         }
03571                 }
03572         }
03573         set_array_offsets(saved_offsets);
03574         return ret;
03575 }
03576 
03577 EMData* EMData::rot_scale_conv_new_background(float ang, float delx, float dely, Util::KaiserBessel& kb, float scale_input) {
03578 
03579         int nxn, nyn, nzn;
03580 
03581         if (scale_input == 0.0f) scale_input = 1.0f;
03582         float  scale = 0.5f*scale_input;
03583 
03584         if (1 >= ny)
03585                 throw ImageDimensionException("Can't rotate 1D image");
03586         if (1 < nz)
03587                 throw ImageDimensionException("Use rot_scale_conv_new_background_3D for volumes");
03588         nxn = nx/2; nyn = ny/2; nzn = nz/2;
03589 
03590         vector<int> saved_offsets = get_array_offsets();
03591         set_array_offsets(0,0,0);
03592         EMData* ret = this->copy_head();
03593 #ifdef _WIN32
03594         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03595 #else
03596         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03597 #endif  //_WIN32
03598         //ret->to_zero();  //we will leave margins zeroed.
03599         delx = restrict2(delx, nx);
03600         dely = restrict2(dely, ny);
03601         // center of big image,
03602         int xc = nxn;
03603         int ixs = nxn%2;  // extra shift on account of odd-sized images
03604         int yc = nyn;
03605         int iys = nyn%2;
03606         // center of small image
03607         int xcn = nxn/2;
03608         int ycn = nyn/2;
03609         // shifted center for rotation
03610         float shiftxc = xcn + delx;
03611         float shiftyc = ycn + dely;
03612         // bounds if origin at center
03613         float ymin = -ny/2.0f;
03614         float xmin = -nx/2.0f;
03615         float ymax = -ymin;
03616         float xmax = -xmin;
03617         if (0 == nx%2) xmax--;
03618         if (0 == ny%2) ymax--;
03619 
03620         float* data = this->get_data();
03621 
03622         // trig
03623         float cang = cos(ang);
03624         float sang = sin(ang);
03625         for (int iy = 0; iy < nyn; iy++) {
03626                 float y = float(iy) - shiftyc;
03627                 float ycang = y*cang/scale + yc;
03628                 float ysang = -y*sang/scale + xc;
03629                 for (int ix = 0; ix < nxn; ix++) {
03630                         float x = float(ix) - shiftxc;
03631                         float xold = x*cang/scale + ysang-ixs;// have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
03632                         float yold = x*sang/scale + ycang-iys;
03633 
03634                         (*ret)(ix,iy) = Util::get_pixel_conv_new_background(nx, ny, 1, xold, yold, 1, data, kb, ix, iy);
03635                 }
03636         }
03637         set_array_offsets(saved_offsets);
03638         return ret;
03639 }
03640 
03641 EMData* EMData::rot_scale_conv_new_background_3D(float phi, float theta, float psi, float delx, float dely, float delz, Util::KaiserBessel& kb, float scale_input, bool wrap) {
03642 
03643         if (scale_input == 0.0f) scale_input = 1.0f;
03644         float  scale = 0.5f*scale_input;
03645 
03646         if (1 >= ny)
03647                 throw ImageDimensionException("Can't rotate 1D image");
03648         int nxn = nx/2; int nyn = ny/2; int nzn = nz/2;
03649 
03650         vector<int> saved_offsets = get_array_offsets();
03651         set_array_offsets(0,0,0);
03652         EMData* ret = this->copy_head();
03653 #ifdef _WIN32
03654         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
03655 #else
03656         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
03657 #endif  //_WIN32
03658         //ret->to_zero();  //we will leave margins zeroed.
03659         if (wrap){
03660                 delx = restrict2(delx, nx);
03661                 dely = restrict2(dely, ny);
03662                 delz = restrict2(delz, nz);
03663         }
03664         // center of big image,
03665         int xc = nxn;
03666         int ixs = nxn%2;  // extra shift on account of odd-sized images
03667         int yc = nyn;
03668         int iys = nyn%2;
03669         int zc = nzn;
03670         int izs = nzn%2;
03671         // center of small image
03672         int xcn = nxn/2;
03673         int ycn = nyn/2;
03674         int zcn = nzn/2;
03675         // shifted center for rotation
03676         float shiftxc = xcn + delx;
03677         float shiftyc = ycn + dely;
03678         float shiftzc = zcn + delz;
03679         // bounds if origin at center
03680         float zmin = -nz/2.0f;
03681         float ymin = -ny/2.0f;
03682         float xmin = -nx/2.0f;
03683         float zmax = -zmin;
03684         float ymax = -ymin;
03685         float xmax = -xmin;
03686         if (0 == nx%2) xmax--;
03687         if (0 == ny%2) ymax--;
03688         if (0 == nz%2) zmax--;
03689 
03690         float* data = this->get_data();
03691 
03692         float cf = cos(phi);   float sf = sin(phi);
03693         float ct = cos(theta); float st = sin(theta);
03694         float cp = cos(psi);   float sp = sin(psi);
03695         // rotation matrix (the transpose is used in the loop to get (xold,yold,zold)):
03696         float a11 =  cp*ct*cf-sp*sf; float a12 =  cp*ct*sf+sp*cf; float a13 = -cp*st;
03697         float a21 = -sp*ct*cf-cp*sf; float a22 = -sp*ct*sf+cp*cf; float a23 =  sp*st;
03698         float a31 =  st*cf;          float a32 =  st*sf;          float a33 =  ct;
03699         for (int iz = 0; iz < nzn; iz++) {
03700                 float z = (float(iz) - shiftzc)/scale;
03701                 float zco1 = a31*z+xc;
03702                 float zco2 = a32*z+yc;
03703                 float zco3 = a33*z+zc;
03704                 for (int iy = 0; iy < nyn; iy++) {
03705                         float y = (float(iy) - shiftyc)/scale;
03706                         float yco1 = zco1+a21*y;
03707                         float yco2 = zco2+a22*y;
03708                         float yco3 = zco3+a23*y;
03709                         for (int ix = 0; ix < nxn; ix++) {
03710                                 float x = (float(ix) - shiftxc)/scale;
03711                                 float xold = yco1+a11*x-ixs; //have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
03712                                 float yold = yco2+a12*x-iys;
03713                                 float zold = yco3+a13*x-izs;
03714                                 if(!wrap && (xold<0.0 || xold>nx-1 || yold<0.0 || yold>ny-1 || zold<0.0 || zold>nz-1))
03715                                         (*ret)(ix,iy,iz) = 0.0;
03716                                 else
03717                                         (*ret)(ix,iy,iz) = Util::get_pixel_conv_new_background(nx, ny, nz, xold, yold, zold, data, kb, ix, iy);
03718                         }
03719                 }
03720         }
03721         set_array_offsets(saved_offsets);
03722         return ret;
03723 }
03724 
03725 
03726 float  EMData::get_pixel_conv(float delx, float dely, float delz, Util::KaiserBessel& kb) {
03727 //  here counting is in C style, so coordinates of the pixel delx should be [0-nx-1]
03728 
03729         int K     = kb.get_window_size();
03730         int kbmin = -K/2;
03731         int kbmax = -kbmin;
03732         int kbc   = kbmax+1;
03733 
03734         float pixel =0.0f;
03735         float w=0.0f;
03736 
03737         delx = restrict2(delx, nx);
03738         int inxold = int(Util::round(delx));
03739         if(ny<2) {  //1D
03740                 if(inxold <= kbc || inxold >=nx-kbc-2 )  {
03741                         //  loop for ends
03742                         for (int m1 =kbmin; m1 <=kbmax; m1++) {
03743                                 float q = kb.i0win_tab(delx - inxold-m1);
03744                                 pixel += (*this)((inxold+m1+nx)%nx)*q; w+=q;
03745                         }
03746                 } else {
03747                         for (int m1 =kbmin; m1 <=kbmax; m1++) {
03748                                 float q = kb.i0win_tab(delx - inxold-m1);
03749                                 pixel += (*this)(inxold+m1)*q; w+=q;
03750                         }
03751                 }
03752 
03753         } else if(nz<2) {  // 2D
03754                 dely = restrict2(dely, ny);
03755                 int inyold = int(Util::round(dely));
03756                 if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2 )  {
03757                         //  loop for strips
03758                         for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03759                                 float q = kb.i0win_tab(delx - inxold-m1)*kb.i0win_tab(dely - inyold-m2);
03760                                 pixel += (*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny)*q; w+=q;}
03761                         }
03762                 } else {
03763                         for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03764                                 float q = kb.i0win_tab(delx - inxold-m1)*kb.i0win_tab(dely - inyold-m2);
03765                                 pixel += (*this)(inxold+m1,inyold+m2)*q; w+=q;}
03766                         }
03767                 }
03768         } else {  //  3D
03769                 dely = restrict2(dely, ny);
03770                 int inyold = int(Util::round(dely));
03771                 delz = restrict2(delz, nz);
03772                 int inzold = int(Util::round(delz));
03773                     //cout << inxold<<"  "<< kbc<<"  "<< nx-kbc-2<<"  "<< endl;
03774                 if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2  || inzold <= kbc || inzold >=nz-kbc-2 )  {
03775                         //  loop for strips
03776                         for (int m3 =kbmin; m3 <=kbmax; m3++){ for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03777                                 float q = kb.i0win_tab(delx - inxold-m1)*kb.i0win_tab(dely - inyold-m2)*kb.i0win_tab(delz - inzold-m3);
03778                                 //cout << "BB  "<<m1<<"  "<< m2<<"  "<< m3<<"  "<< q<<"  "<< q<<"  "<<(*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny,(inzold+m3+nz)%nz)<< endl;
03779                                 pixel += (*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny,(inzold+m3+nz)%nz)*q ;w+=q;}}
03780                         }
03781                 } else {
03782                         for (int m3 =kbmin; m3 <=kbmax; m3++){ for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03783                                 float q = kb.i0win_tab(delx - inxold-m1)*kb.i0win_tab(dely - inyold-m2)*kb.i0win_tab(delz - inzold-m3);
03784                                 //cout << "OO  "<<m1<<"  "<< m2<<"  "<< m3<<"  "<< q<<"  "<< q<<"  "<<(*this)(inxold+m1,inyold+m2,inzold+m3)<< endl;
03785                                 pixel += (*this)(inxold+m1,inyold+m2,inzold+m3)*q; w+=q;}}
03786                         }
03787                 }
03788         }
03789         return pixel/w;
03790 }
03791 
03792 
03793 float  EMData::get_pixel_filtered(float delx, float dely, float delz, Util::sincBlackman& kb) {
03794 //  here counting is in C style, so coordinates of the pixel delx should be [0-nx-1]
03795 
03796         int K     = kb.get_sB_size();
03797         int kbmin = -K/2;
03798         int kbmax = -kbmin;
03799         int kbc   = kbmax+1;
03800 
03801         float pixel =0.0f;
03802         float w=0.0f;
03803 
03804         //delx = restrict2(delx, nx);   //  In this function the old location is always within the      image
03805         int inxold = int(Util::round(delx));
03806         /*if(ny<2) {  //1D
03807                 if(inxold <= kbc || inxold >=nx-kbc-2 )  {
03808                         //  loop for ends
03809                         for (int m1 =kbmin; m1 <=kbmax; m1++) {
03810                                 float q = kb.sBwin_tab(delx - inxold-m1);
03811                                 pixel += (*this)((inxold+m1+nx)%nx)*q; w+=q;
03812                         }
03813                 } else {
03814                         for (int m1 =kbmin; m1 <=kbmax; m1++) {
03815                                 float q = kb.sBwin_tab(delx - inxold-m1);
03816                                 pixel += (*this)(inxold+m1)*q; w+=q;
03817                         }
03818                 }
03819 
03820         } else */
03821         if(nz<2) {  
03822                 //dely = restrict2(dely, ny);
03823                 int inyold = int(Util::round(dely));
03824                 if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2 )  {
03825                         //  loop for strips
03826                         for (int m2 =kbmin; m2 <=kbmax; m2++){
03827                                 float t = kb.sBwin_tab(dely - inyold-m2);
03828                                 for (int m1 =kbmin; m1 <=kbmax; m1++) {
03829                                         float q = kb.sBwin_tab(delx - inxold-m1)*t;
03830                                         pixel += (*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny)*q;
03831                                         w += q;
03832                                 }
03833                         }
03834                 } else {
03835                         for (int m2 =kbmin; m2 <=kbmax; m2++){
03836                                 float t = kb.sBwin_tab(dely - inyold-m2);
03837                                 for (int m1 =kbmin; m1 <=kbmax; m1++) {
03838                                         float q = kb.sBwin_tab(delx - inxold-m1)*t;
03839                                         pixel += (*this)(inxold+m1,inyold+m2)*q;
03840                                         w += q;
03841                                 }
03842                         }
03843                 }
03844         } else {  //  3D
03845                 //std::cout<<"pixel_filtered 3D"<<std::endl;
03846                 dely = restrict2(dely, ny);
03847                 int inyold = int(Util::round(dely));
03848                 delz = restrict2(delz, nz);
03849                 int inzold = int(Util::round(delz));
03850                     //cout << inxold<<"  "<< kbc<<"  "<< nx-kbc-2<<"  "<< endl;
03851                 if(inxold <= kbc || inxold >=nx-kbc-2 || inyold <= kbc || inyold >=ny-kbc-2  || inzold <= kbc || inzold >=nz-kbc-2 )  {
03852                         //  loop for strips
03853                         for (int m3 =kbmin; m3 <=kbmax; m3++){ for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03854                                 float q = kb.sBwin_tab(delx - inxold-m1)*kb.sBwin_tab(dely - inyold-m2)*kb.sBwin_tab(delz - inzold-m3);
03855                                 //cout << "BB  "<<m1<<"  "<< m2<<"  "<< m3<<"  "<< q<<"  "<< q<<"  "<<(*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny,(inzold+m3+nz)%nz)<< endl;
03856                                 pixel += (*this)((inxold+m1+nx)%nx,(inyold+m2+ny)%ny,(inzold+m3+nz)%nz)*q ;w+=q;}}
03857                         }
03858                 } else {
03859                         for (int m3 =kbmin; m3 <=kbmax; m3++){ for (int m2 =kbmin; m2 <=kbmax; m2++){ for (int m1 =kbmin; m1 <=kbmax; m1++) {
03860                                 float q = kb.sBwin_tab(delx - inxold-m1)*kb.sBwin_tab(dely - inyold-m2)*kb.sBwin_tab(delz - inzold-m3);
03861                                 //cout << "OO  "<<m1<<"  "<< m2<<"  "<< m3<<"  "<< q<<"  "<< q<<"  "<<(*this)(inxold+m1,inyold+m2,inzold+m3)<< endl;
03862                                 pixel += (*this)(inxold+m1,inyold+m2,inzold+m3)*q; w+=q;}}
03863                         }
03864                 }
03865         }
03866         return pixel/w;
03867 }
03868 
03869 // Note by Yang on 10/02/07
03870 // get_pixel_conv7() is equivalent to get_pixel_conv_new(), however, it is written in this way such that it can be used in python directly
03871 // By the way, get_pixel_conv_new() is a faster version of get_pixel_conv(), I have done a lot of testing and show that their results are the same.
03872 float  EMData::get_pixel_conv7(float delx, float dely, float delz, Util::KaiserBessel& kb) {
03873 //  here counting is in C style, so coordinates of the pixel delx should be [0-nx-1]
03874 
03875         float *image=(this->get_data());
03876         int nx = this->get_xsize();
03877         int ny = this->get_ysize();
03878         int nz = this->get_zsize();
03879 
03880         float result;
03881 
03882         result = Util::get_pixel_conv_new(nx,ny,nz,delx,dely,delz,image,kb);
03883         return result;
03884 }
03885 
03886 float EMData::getconvpt2d_kbi0(float x, float y, Util::KaiserBessel::kbi0_win win, int size) {
03887         const int nxhalf = nx/2;
03888         const int nyhalf = ny/2;
03889         const int bd = size/2;
03890         float* wxarr = new float[size];
03891         float* wyarr = new float[size];
03892         float* wx = wxarr + bd; // wx[-bd] = wxarr[0]
03893         float* wy = wyarr + bd;
03894         int ixc = int(x + 0.5f*Util::sgn(x));
03895         int iyc = int(y + 0.5f*Util::sgn(y));
03896         if (abs(ixc) > nxhalf)
03897                 throw InvalidValueException(ixc, "getconv: X value out of range");
03898         if (abs(iyc) > nyhalf)
03899                 throw InvalidValueException(ixc, "getconv: Y value out of range");
03900         for (int i = -bd; i <= bd; i++) {
03901                 int iyp = iyc + i;
03902                 wy[i] = win(y - iyp);
03903                 int ixp = ixc + i;
03904                 wx[i] = win(x - ixp);
03905         }
03906         vector<int> saved_offsets = get_array_offsets();
03907         set_array_offsets(-nxhalf, -nyhalf);
03908         float conv = 0.f, wsum = 0.f;
03909         for (int iy = -bd; iy <= bd; iy++) {
03910                 int iyp = iyc + iy;
03911                 for (int ix = -bd; ix <= bd; ix++) {
03912                         int ixp = ixc + ix;
03913                         float wg = wx[ix]*wy[iy];
03914                         conv += (*this)(ixp,iyp)*wg;
03915                         wsum += wg;
03916                 }
03917         }
03918         set_array_offsets(saved_offsets);
03919         delete [] wxarr;
03920         delete [] wyarr;
03921         //return conv/wsum;
03922         return conv;
03923 }
03924 
03925 std::complex<float> EMData::extractpoint(float nuxnew, float nuynew, Util::KaiserBessel& kb) {
03926         if (2 != get_ndim())
03927                 throw ImageDimensionException("extractpoint needs a 2-D image.");
03928         if (!is_complex())
03929                 throw ImageFormatException("extractpoint requires a fourier image");
03930         int nxreal = nx - 2;
03931         if (nxreal != ny)
03932                 throw ImageDimensionException("extractpoint requires ny == nx");
03933         int nhalf = nxreal/2;
03934         int kbsize = kb.get_window_size();
03935         int kbmin = -kbsize/2;
03936         int kbmax = -kbmin;
03937         bool flip = (nuxnew < 0.f);
03938         if (flip) {
03939                 nuxnew *= -1;
03940                 nuynew *= -1;
03941         }
03942         // put (xnew,ynew) on a grid.  The indices will be wrong for
03943         // the Fourier elements in the image, but the grid sizing will
03944         // be correct.
03945         int ixn = int(Util::round(nuxnew));
03946         int iyn = int(Util::round(nuynew));
03947         // set up some temporary weighting arrays
03948         float* wy0 = new float[kbmax - kbmin + 1];
03949         float* wy = wy0 - kbmin; // wy[kbmin:kbmax]
03950         float* wx0 = new float[kbmax - kbmin + 1];
03951         float* wx = wx0 - kbmin;
03952         for (int i = kbmin; i <= kbmax; i++) {
03953                         int iyp = iyn + i;
03954                         wy[i] = kb.i0win_tab(nuynew - iyp);
03955                         int ixp = ixn + i;
03956                         wx[i] = kb.i0win_tab(nuxnew - ixp);
03957         }
03958         // restrict loops to non-zero elements
03959         int iymin = 0;
03960         for (int iy = kbmin; iy <= -1; iy++) {
03961                 if (wy[iy] != 0.f) {
03962                         iymin = iy;
03963                         break;
03964                 }
03965         }
03966         int iymax = 0;
03967         for (int iy = kbmax; iy >= 1; iy--) {
03968                 if (wy[iy] != 0.f) {
03969                         iymax = iy;
03970                         break;
03971                 }
03972         }
03973         int ixmin = 0;
03974         for (int ix = kbmin; ix <= -1; ix++) {
03975                 if (wx[ix] != 0.f) {
03976                         ixmin = ix;
03977                         break;
03978                 }
03979         }
03980         int ixmax = 0;
03981         for (int ix = kbmax; ix >= 1; ix--) {
03982                 if (wx[ix] != 0.f) {
03983                         ixmax = ix;
03984                         break;
03985                 }
03986         }
03987         float wsum = 0.0f;
03988         for (int iy = iymin; iy <= iymax; iy++)
03989                 for (int ix = ixmin; ix <= ixmax; ix++)
03990                         wsum += wx[ix]*wy[iy];
03991         std::complex<float> result(0.f,0.f);
03992         if ((ixn >= -kbmin) && (ixn <= nhalf-1-kbmax) && (iyn >= -nhalf-kbmin) && (iyn <= nhalf-1-kbmax)) {
03993                 // (xin,yin) not within window border from the edge
03994                 for (int iy = iymin; iy <= iymax; iy++) {
03995                         int iyp = iyn + iy;
03996                         for (int ix = ixmin; ix <= ixmax; ix++) {
03997                                 int ixp = ixn + ix;
03998                                 float w = wx[ix]*wy[iy];
03999                                 std::complex<float> val = cmplx(ixp,iyp);
04000                                 result += val*w;
04001                         }
04002                 }
04003         } else {
04004                 // points that "stick out"
04005                 for (int iy = iymin; iy <= iymax; iy++) {
04006                         int iyp = iyn + iy;
04007                         for (int ix = ixmin; ix <= ixmax; ix++) {
04008                                 int ixp = ixn + ix;
04009                                 bool mirror = false;
04010                                 int ixt= ixp, iyt= iyp;
04011                                 if (ixt < 0) {
04012                                         ixt = -ixt;
04013                                         iyt = -iyt;
04014                                         mirror = !mirror;
04015                                 }
04016                                 if (ixt > nhalf) {
04017                                         ixt = nxreal - ixt;
04018                                         iyt = -iyt;
04019                                         mirror = !mirror;
04020                                 }
04021                                 if (iyt > nhalf-1)  iyt -= nxreal;
04022                                 if (iyt < -nhalf)   iyt += nxreal;
04023                                 float w = wx[ix]*wy[iy];
04024                                 std::complex<float> val = this->cmplx(ixt,iyt);
04025                                 if (mirror)  result += conj(val)*w;
04026                                 else         result += val*w;
04027                         }
04028                 }
04029         }
04030         if (flip)  result = conj(result)/wsum;
04031         else       result /= wsum;
04032         delete [] wx0;
04033         delete [] wy0;
04034         return result;
04035 }
04036 
04037 EMData* EMData::extractline(Util::KaiserBessel& kb, float nuxnew, float nuynew)
04038 {
04039         if (!is_complex())
04040                 throw ImageFormatException("extractline requires a fourier image");
04041         if (nx%2 != 0)
04042                 throw ImageDimensionException("extractline requires nx to be even");
04043         int nxreal = nx - 2;
04044         if (nxreal != ny)
04045                 throw ImageDimensionException("extractline requires ny == nx");
04046         // build complex result image
04047         EMData* res = new EMData();
04048         res->set_size(nx,1,1);
04049         res->to_zero();
04050         res->set_complex(true);
04051         res->set_fftodd(false);
04052         res->set_fftpad(true);
04053         res->set_ri(true);
04054         // Array offsets: (0..nhalf,-nhalf..nhalf-1)
04055         int n = nxreal;
04056         int nhalf = n/2;
04057         vector<int> saved_offsets = get_array_offsets();
04058         set_array_offsets(0,-nhalf,-nhalf);
04059 
04060         // set up some temporary weighting arrays
04061         int kbsize = kb.get_window_size();
04062         int kbmin = -kbsize/2;
04063         int kbmax = -kbmin;
04064         float* wy0 = new float[kbmax - kbmin + 1];
04065         float* wy = wy0 - kbmin; // wy[kbmin:kbmax]
04066         float* wx0 = new float[kbmax - kbmin + 1];
04067         float* wx = wx0 - kbmin;
04068 
04069         int   count = 0;
04070         float wsum = 0.f;
04071         bool  flip = (nuxnew < 0.f);
04072 
04073         for (int jx = 0; jx <= nhalf; jx++) {
04074                 float xnew = jx*nuxnew, ynew = jx*nuynew;
04075                 count++;
04076                 std::complex<float> btq(0.f,0.f);
04077                 if (flip) {
04078                         xnew = -xnew;
04079                         ynew = -ynew;
04080                 }
04081                 int ixn = int(Util::round(xnew));
04082                 int iyn = int(Util::round(ynew));
04083                 // populate weight arrays
04084                 for (int i=kbmin; i <= kbmax; i++) {
04085                         int iyp = iyn + i;
04086                         wy[i] = kb.i0win_tab(ynew - iyp);
04087                         int ixp = ixn + i;
04088                         wx[i] = kb.i0win_tab(xnew - ixp);
04089                 }
04090                 // restrict weight arrays to non-zero elements
04091 
04092                 int lnby = 0;
04093                 for (int iy = kbmin; iy <= -1; iy++) {
04094                         if (wy[iy] != 0.f) {
04095                                 lnby = iy;
04096                                 break;
04097                         }
04098                 }
04099                 int lney = 0;
04100                 for (int iy = kbmax; iy >= 1; iy--) {
04101                         if (wy[iy] != 0.f) {
04102                                 lney = iy;
04103                                 break;
04104                         }
04105                 }
04106                 int lnbx = 0;
04107                 for (int ix = kbmin; ix <= -1; ix++) {
04108                         if (wx[ix] != 0.f) {
04109                                 lnbx = ix;
04110                                 break;
04111                         }
04112                 }
04113                 int lnex = 0;
04114                 for (int ix = kbmax; ix >= 1; ix--) {
04115                         if (wx[ix] != 0.f) {
04116                                 lnex = ix;
04117                                 break;
04118                         }
04119                 }
04120                 if (ixn >= -kbmin && ixn <= nhalf-1-kbmax
04121                                 && iyn >= -nhalf-kbmin && iyn <= nhalf-1-kbmax) {
04122                         // interior points
04123                         for (int ly=lnby; ly<=lney; ly++) {
04124                                 int iyp = iyn + ly;
04125                                 for (int lx=lnbx; lx<=lnex; lx++) {
04126                                         int ixp = ixn + lx;
04127                                         float wg = wx[lx]*wy[ly];
04128                                         btq += cmplx(ixp,iyp)*wg;
04129                                         wsum += wg;
04130                                 }
04131                         }
04132                 } else {
04133                         // points "sticking out"
04134                         for (int ly=lnby; ly<=lney; ly++) {
04135                                 int iyp = iyn + ly;
04136                                 for (int lx=lnbx; lx<=lnex; lx++) {
04137                                         int ixp = ixn + lx;
04138                                         float wg = wx[lx]*wy[ly];
04139                                         bool mirror = false;
04140                                         int ixt(ixp), iyt(iyp);
04141                                         if (ixt > nhalf || ixt < -nhalf) {
04142                                                 ixt = Util::sgn(ixt)*(n - abs(ixt));
04143                                                 iyt = -iyt;
04144                                                 mirror = !mirror;
04145                                         }
04146                                         if (iyt >= nhalf || iyt < -nhalf) {
04147                                                 if (ixt != 0) {
04148                                                         ixt = -ixt;
04149                                                         iyt = Util::sgn(iyt)*(n - abs(iyt));
04150                                                         mirror = !mirror;
04151                                                 } else {
04152                                                         iyt -= n*Util::sgn(iyt);
04153                                                 }
04154                                         }
04155                                         if (ixt < 0) {
04156                                                 ixt = -ixt;
04157                                                 iyt = -iyt;
04158                                                 mirror = !mirror;
04159                                         }
04160                                         if (iyt == nhalf) iyt = -nhalf;
04161                                         if (mirror) btq += conj(cmplx(ixt,iyt))*wg;
04162                                         else        btq += cmplx(ixt,iyt)*wg;
04163                                         wsum += wg;
04164                                 }
04165                         }
04166                 }
04167                 if (flip) res->cmplx(jx) = conj(btq);
04168                 else      res->cmplx(jx) = btq;
04169         }
04170         for (int jx = 0; jx <= nhalf; jx++)  res->cmplx(jx) *= count/wsum;
04171 
04172         delete[] wx0; delete[] wy0;
04173         set_array_offsets(saved_offsets);
04174         res->set_array_offsets(0,0,0);
04175         return res;
04176 }
04177 
04178 
04180 inline void swapx(float* a, float* b, float* temp, size_t nbytes) {
04181         memcpy(temp, a, nbytes);
04182         memcpy(a, b, nbytes);
04183         memcpy(b, temp, nbytes);
04184 }
04185 
04186 void EMData::fft_shuffle() {
04187         if (!is_complex())
04188                 throw ImageFormatException("fft_shuffle requires a fourier image");
04189         vector<int> offsets = get_array_offsets();
04190         set_array_offsets(); // clear offsets before shuffling
04191         EMData& self = *this;
04192         int nyhalf = ny/2;
04193         int nzhalf = nz/2;
04194         int nbytes = nx*sizeof(float);
04195         float* temp = new float[nx];
04196         for (int iz=0; iz < nz; iz++)
04197                 for (int iy=0; iy < nyhalf; iy++)
04198                         swapx(&self(0,iy,iz),&self(0,iy+nyhalf,iz),temp,nbytes);
04199         if (nz > 1) {
04200                 for (int iy=0; iy < ny; iy++)
04201                         for (int iz=0; iz < nzhalf; iz++)
04202                                 swapx(&self(0,iy,iz),&self(0,iy,iz+nzhalf),temp,nbytes);
04203         }
04204         set_shuffled(!is_shuffled()); // toggle
04205         set_array_offsets(offsets); // reset offsets
04206         update();
04207         delete[] temp;
04208 }
04209 
04210 void EMData::pad_corner(float *pad_image) {
04211         size_t nbytes = nx*sizeof(float);
04212         for (int iy=0; iy<ny; iy++)
04213                 memcpy(&(*this)(0,iy), pad_image+3+(iy+3)*nx, nbytes);
04214 }
04215 
04216 void EMData::shuffle_pad_corner(float *pad_image) {
04217         int nyhalf = ny/2;
04218         size_t nbytes = nx*sizeof(float);
04219         for (int iy = 0; iy < nyhalf; iy++)
04220                 memcpy(&(*this)(0,iy), pad_image+6+(iy+nyhalf+3)*nx, nbytes);
04221         for (int iy = nyhalf; iy < ny; iy++)
04222                 memcpy(&(*this)(0,iy), pad_image+6+(iy-nyhalf+3)*nx, nbytes);
04223 }
04224 
04225 #define    QUADPI                       3.141592653589793238462643383279502884197
04226 #define    DGR_TO_RAD                   QUADPI/180
04227 
04228 // We tried to pad the Fourier image to reduce the stick out points, howover it is not very efficient.
04229 /*
04230 EMData* EMData::fouriergridrot2d(float ang, float scale, Util::KaiserBessel& kb) {
04231         if (2 != get_ndim())
04232                 throw ImageDimensionException("fouriergridrot2d needs a 2-D image.");
04233         if (!is_complex())
04234                 throw ImageFormatException("fouriergridrot2d requires a fourier image");
04235         int nxreal = nx - 2 + int(is_fftodd());
04236         if (nxreal != ny)
04237                 throw ImageDimensionException("fouriergridrot2d requires ny == nx(real)");
04238         if (0 != nxreal%2)
04239                 throw ImageDimensionException("fouriergridrot2d needs an even image.");
04240         if (scale == 0.0f) scale = 1.0f;
04241         int nxhalf = nxreal/2;
04242         int nyhalf = ny/2;
04243 
04244         EMData *pad_this = new EMData();
04245         pad_this->set_size(nx+12, ny+6);
04246         //pad_this->to_zero();
04247         float* pad_image = pad_this-> get_data();
04248 
04249         if (!is_shuffled()) {
04250                 shuffle_pad_corner(pad_image);
04251         } else {
04252                 pad_corner(pad_image);
04253         }
04254         pad_this -> set_array_offsets(-6, -nyhalf-3);
04255 
04256         EMData* result = copy_head();
04257         set_array_offsets(0,-nyhalf);
04258         result->set_array_offsets(0,-nyhalf);
04259 
04260         ang = ang*DGR_TO_RAD;
04261         float cang = cos(ang);
04262         float sang = sin(ang);
04263         for (int iy = -nyhalf; iy < nyhalf; iy++) {
04264                 float ycang = iy*cang;
04265                 float ysang = iy*sang;
04266                 for (int ix = 0; ix <= nxhalf; ix++) {
04267                         float nuxold = (ix*cang - ysang)*scale;
04268                         float nuyold = (ix*sang + ycang)*scale;
04269                         result->cmplx(ix,iy) = Util::extractpoint2(nx, ny, nuxold, nuyold, pad_this, kb);
04270                 }
04271         }
04272         result->set_array_offsets();
04273         result->fft_shuffle(); // reset to an unshuffled result
04274         result->update();
04275         set_array_offsets();
04276         fft_shuffle(); // reset to an unshuffled complex image
04277         return result;
04278 }*/
04279 
04280 
04281 EMData* EMData::fouriergridrot2d(float ang, float scale, Util::KaiserBessel& kb) {
04282         if (2 != get_ndim())
04283                 throw ImageDimensionException("fouriergridrot2d needs a 2-D image.");
04284         if (!is_complex())
04285                 throw ImageFormatException("fouriergridrot2d requires a fourier image");
04286         int nxreal = nx - 2 + int(is_fftodd());
04287         if (nxreal != ny)
04288                 throw ImageDimensionException("fouriergridrot2d requires ny == nx(real)");
04289         if (0 != nxreal%2)
04290                 throw ImageDimensionException("fouriergridrot2d needs an even image.");
04291         if (scale == 0.0f) scale = 1.0f;
04292         int nxhalf = nxreal/2;
04293         int nyhalf = ny/2;
04294         float cir = (float)((nxhalf-1)*(nxhalf-1));
04295 
04296         if (!is_shuffled()) fft_shuffle();
04297 
04298         EMData* result = copy_head();
04299         set_array_offsets(0,-nyhalf);
04300         result->set_array_offsets(0,-nyhalf);
04301 
04302 
04303 
04304         ang = ang*(float)DGR_TO_RAD;
04305         float cang = cos(ang);
04306         float sang = sin(ang);
04307         for (int iy = -nyhalf; iy < nyhalf; iy++) {
04308                 float ycang = iy*cang;
04309                 float ysang = iy*sang;
04310                 for (int ix = 0; ix <= nxhalf; ix++) {
04311                         float nuxold = (ix*cang - ysang)*scale;
04312                         float nuyold = (ix*sang + ycang)*scale;
04313                         if (nuxold*nuxold+nuyold*nuyold<cir) result->cmplx(ix,iy) = Util::extractpoint2(nx, ny, nuxold, nuyold, this, kb);
04314                         //result->cmplx(ix,iy) = extractpoint(nuxold, nuyold, kb);
04315                 }
04316         }
04317         result->set_array_offsets();
04318         result->fft_shuffle(); // reset to an unshuffled result
04319         result->update();
04320         set_array_offsets();
04321         fft_shuffle(); // reset to an unshuffled complex image
04322         return result;
04323 }
04324 
04325 EMData* EMData::fouriergridrot_shift2d(float ang, float sx, float sy, Util::KaiserBessel& kb) {
04326         if (2 != get_ndim())
04327                 throw ImageDimensionException("fouriergridrot_shift2d needs a 2-D image.");
04328         if (!is_complex())
04329                 throw ImageFormatException("fouriergridrot_shift2d requires a fourier image");
04330         int nxreal = nx - 2 + int(is_fftodd());
04331         if (nxreal != ny)
04332                 throw ImageDimensionException("fouriergridrot_shift2d requires ny == nx(real)");
04333         if (0 != nxreal%2)
04334                 throw ImageDimensionException("fouriergridrot_shift2d needs an even image.");
04335         int nxhalf = nxreal/2;
04336         int nyhalf = ny/2;
04337 
04338         if (!is_shuffled()) fft_shuffle();
04339 
04340         EMData* result = copy_head();
04341         set_array_offsets(0, -nyhalf);
04342         result->set_array_offsets(0, -nyhalf);
04343 
04344         ang = ang*(float)DGR_TO_RAD;
04345         float cang = cos(ang);
04346         float sang = sin(ang);
04347         float temp = -2.0f*M_PI/nxreal;
04348         for (int iy = -nyhalf; iy < nyhalf; iy++) {
04349                 float ycang = iy*cang;
04350                 float ysang = iy*sang;
04351                 for (int ix = 0; ix <= nxhalf; ix++) {
04352                         float nuxold = ix*cang - ysang;
04353                         float nuyold = ix*sang + ycang;
04354                         result->cmplx(ix,iy) = Util::extractpoint2(nx, ny, nuxold, nuyold, this, kb);
04355                         //result->cmplx(ix,iy) = extractpoint(nuxold, nuyold, kb);
04356                         float phase_ang = temp*(sx*ix+sy*iy);
04357                         result->cmplx(ix,iy) *= complex<float>(cos(phase_ang), sin(phase_ang));
04358                 }
04359         }
04360         result->set_array_offsets();
04361         result->fft_shuffle(); // reset to an unshuffled result
04362         result->update();
04363         set_array_offsets();
04364         fft_shuffle(); // reset to an unshuffled complex image
04365         return result;
04366 }
04367 
04368 #undef QUADPI
04369 #undef DGR_TO_RAD
04370 
04371 void EMData::divkbsinh(const Util::KaiserBessel& kb) {
04372         
04373         if (is_complex())
04374                 throw ImageFormatException("divkbsinh requires a real image.");
04375         vector<int> saved_offsets = get_array_offsets();
04376         set_array_offsets(0,0,0);
04377         // Note that the following loops will work for 1-, 2-, and 3-D
04378         // images, since the "extra" weights will be 1.0.  (For example,
04379         // for a 2-d image iz=0, nz=1, so iz-nz/2 = 0 - 1/2 = 0, since
04380         // the division is an integer division.)
04381         for (int iz=0; iz < nz; iz++) {
04382                 float wz = kb.sinhwin(static_cast<float>(iz-nz/2));
04383                 for (int iy=0; iy < ny; iy++) {
04384                         float wy = kb.sinhwin(static_cast<float>(iy-ny/2));
04385                         for (int ix=0; ix < nx; ix++) {
04386                                 float wx = kb.sinhwin(static_cast<float>(ix-nx/2));
04387                                 float w = wx*wy*wz;
04388                                 (*this)(ix,iy,iz) /= w;
04389                         }
04390                 }
04391         }
04392         set_array_offsets(saved_offsets);
04393 }
04394 
04395 void EMData::divkbsinh_rect(const Util::KaiserBessel& kbx, const Util::KaiserBessel& kby, const Util::KaiserBessel& kbz) {
04396 
04397         if (is_complex())
04398                 throw ImageFormatException("divkbsinh requires a real image.");
04399         vector<int> saved_offsets = get_array_offsets();
04400         set_array_offsets(0,0,0);
04401         // Note that the following loops will work for 1-, 2-, and 3-D
04402         // images, since the "extra" weights will be 1.0.  (For example,
04403         // for a 2-d image iz=0, nz=1, so iz-nz/2 = 0 - 1/2 = 0, since
04404         // the division is an integer division.)
04405         for (int iz=0; iz < nz; iz++) {
04406                 float wz = kbz.sinhwin(static_cast<float>(iz-nz/2));
04407                 for (int iy=0; iy < ny; iy++) {
04408                         float wy = kby.sinhwin(static_cast<float>(iy-ny/2));
04409                         for (int ix=0; ix < nx; ix++) {
04410                                 float wx = kbx.sinhwin(static_cast<float>(ix-nx/2));
04411                                 float w = wx*wy*wz;
04412                                 (*this)(ix,iy,iz) /= w;
04413                         }
04414                 }
04415         }
04416         
04417         set_array_offsets(saved_offsets);
04418 }
04419 
04420 /* OBSOLETED  PAP
04421 Dict EMData::masked_stats(const EMData* mask) {
04422         if (is_complex())
04423                 throw ImageFormatException(
04424                                 "Complex images not supported by EMData::masked_stats");
04425         float* ptr = get_data();
04426         float* mptr = mask->get_data();
04427         long double sum1 = 0.L;
04428         long double sum2 = 0.L;
04429         long nmask = 0L;
04430         for (long i = 0; i < nx*ny*nz; i++,ptr++,mptr++) {
04431                 if (*mptr > 0.5f) {
04432                         nmask++;
04433                         sum1 += *ptr;
04434                         sum2 += (*ptr)*(*ptr);
04435                 }
04436         }
04437         float avg = static_cast<float>(sum1/nmask);
04438         float sig2 = static_cast<float>(sum2/nmask - avg*avg);
04439         float sig = sqrt(sig2);
04440         Dict mydict;
04441         mydict["avg"] = avg; mydict["sigma"] = sig; mydict["nmask"] = int(nmask);
04442         return mydict;
04443 }
04444 */
04445 
04446 EMData* EMData::extract_plane(const Transform& tf, Util::KaiserBessel& kb) {
04447         if (!is_complex())
04448                 throw ImageFormatException("extractplane requires a complex image");
04449         if (nx%2 != 0)
04450                 throw ImageDimensionException("extractplane requires nx to be even");
04451         int nxreal = nx - 2;
04452         if (nxreal != ny || nxreal != nz)
04453                 throw ImageDimensionException("extractplane requires ny == nx == nz");
04454         // build complex result image
04455         EMData* res = new EMData();
04456         res->set_size(nx,ny,1);
04457         res->to_zero();
04458         res->set_complex(true);
04459         res->set_fftodd(false);
04460         res->set_fftpad(true);
04461         res->set_ri(true);
04462         // Array offsets: (0..nhalf,-nhalf..nhalf-1,-nhalf..nhalf-1)
04463         int n = nxreal;
04464         int nhalf = n/2;
04465         vector<int> saved_offsets = get_array_offsets();
04466         set_array_offsets(0,-nhalf,-nhalf);
04467         res->set_array_offsets(0,-nhalf,0);
04468         // set up some temporary weighting arrays
04469         int kbsize =  kb.get_window_size();
04470         int kbmin  = -kbsize/2;
04471         int kbmax  = -kbmin;
04472         float* wy0 = new float[kbmax - kbmin + 1];
04473         float* wy  = wy0 - kbmin; // wy[kbmin:kbmax]
04474         float* wx0 = new float[kbmax - kbmin + 1];
04475         float* wx  = wx0 - kbmin;
04476         float* wz0 = new float[kbmax - kbmin + 1];
04477         float* wz  = wz0 - kbmin;
04478         float rim = nhalf*float(nhalf);
04479         int count = 0;
04480         float wsum = 0.f;
04481         Transform tftrans = tf; // need transpose of tf here for consistency
04482         tftrans.invert();      // with spider
04483         for (int jy = -nhalf; jy < nhalf; jy++) 
04484         {
04485                 for (int jx = 0; jx <= nhalf; jx++) 
04486                 {
04487                         Vec3f nucur((float)jx, (float)jy, 0.f);
04488                         Vec3f nunew = tftrans*nucur;
04489                         float xnew = nunew[0], ynew = nunew[1], znew = nunew[2];
04490                         if (xnew*xnew+ynew*ynew+znew*znew <= rim) 
04491                         {
04492                                 count++;
04493                                 std::complex<float> btq(0.f,0.f);
04494                                 bool flip = false;
04495                                 if (xnew < 0.f) {
04496                                         flip = true;
04497                                         xnew = -xnew;
04498                                         ynew = -ynew;
04499                                         znew = -znew;
04500                                 }
04501                                 int ixn = int(Util::round(xnew));
04502                                 int iyn = int(Util::round(ynew));
04503                                 int izn = int(Util::round(znew));
04504                                 // populate weight arrays
04505                                 for (int i=kbmin; i <= kbmax; i++) {
04506                                         int izp = izn + i;
04507                                         wz[i] = kb.i0win_tab(znew - izp);
04508                                         int iyp = iyn + i;
04509                                         wy[i] = kb.i0win_tab(ynew - iyp);
04510                                         int ixp = ixn + i;
04511                                         wx[i] = kb.i0win_tab(xnew - ixp);
04512 
04513                                 }
04514                                 // restrict weight arrays to non-zero elements
04515                                 int lnbz = 0;
04516                                 for (int iz = kbmin; iz <= -1; iz++) {
04517                                         if (wz[iz] != 0.f) {
04518                                                 lnbz = iz;
04519                                                 break;
04520                                         }
04521                                 }
04522                                 int lnez = 0;
04523                                 for (int iz = kbmax; iz >= 1; iz--) {
04524                                         if (wz[iz] != 0.f) {
04525                                                 lnez = iz;
04526                                                 break;
04527                                         }
04528                                 }
04529                                 int lnby = 0;
04530                                 for (int iy = kbmin; iy <= -1; iy++) {
04531                                         if (wy[iy] != 0.f) {
04532                                                 lnby = iy;
04533                                                 break;
04534                                         }
04535                                 }
04536                                 int lney = 0;
04537                                 for (int iy = kbmax; iy >= 1; iy--) {
04538                                         if (wy[iy] != 0.f) {
04539                                                 lney = iy;
04540                                                 break;
04541                                         }
04542                                 }
04543                                 int lnbx = 0;
04544                                 for (int ix = kbmin; ix <= -1; ix++) {
04545                                         if (wx[ix] != 0.f) {
04546                                                 lnbx = ix;
04547                                                 break;
04548                                         }
04549                                 }
04550                                 int lnex = 0;
04551                                 for (int ix = kbmax; ix >= 1; ix--) {
04552                                         if (wx[ix] != 0.f) {
04553                                                 lnex = ix;
04554                                                 break;
04555                                         }
04556                                 }
04557                                 if    (ixn >= -kbmin      && ixn <= nhalf-1-kbmax
04558                                    && iyn >= -nhalf-kbmin && iyn <= nhalf-1-kbmax
04559                                    && izn >= -nhalf-kbmin && izn <= nhalf-1-kbmax) {
04560                                         // interior points
04561                                         for (int lz = lnbz; lz <= lnez; lz++) {
04562                                                 int izp = izn + lz;
04563                                                 for (int ly=lnby; ly<=lney; ly++) {
04564                                                         int iyp = iyn + ly;
04565                                                         float ty = wz[lz]*wy[ly];
04566                                                         for (int lx=lnbx; lx<=lnex; lx++) {
04567                                                                 int ixp = ixn + lx;
04568                                                                 float wg = wx[lx]*ty;
04569                                                                 btq += cmplx(ixp,iyp,izp)*wg;
04570                                                                 wsum += wg;
04571                                                         }
04572                                                 }
04573                                         }
04574                                 } else {
04575                                         // points "sticking out"
04576                                         for (int lz = lnbz; lz <= lnez; lz++) {
04577                                                 int izp = izn + lz;
04578                                                 for (int ly=lnby; ly<=lney; ly++) {
04579                                                         int iyp = iyn + ly;
04580                                                         float ty = wz[lz]*wy[ly];
04581                                                         for (int lx=lnbx; lx<=lnex; lx++) {
04582                                                                 int ixp = ixn + lx;
04583                                                                 float wg = wx[lx]*ty;
04584                                                                 bool mirror = false;
04585                                                                 int ixt(ixp), iyt(iyp), izt(izp);
04586                                                                 if (ixt > nhalf || ixt < -nhalf) {
04587                                                                         ixt = Util::sgn(ixt)
04588                                                                                   *(n - abs(ixt));
04589                                                                         iyt = -iyt;
04590                                                                         izt = -izt;
04591                                                                         mirror = !mirror;
04592                                                                 }
04593                                                                 if (iyt >= nhalf || iyt < -nhalf) {
04594                                                                         if (ixt != 0) {
04595                                                                                 ixt = -ixt;
04596                                                                                 iyt = Util::sgn(iyt)
04597                                                                                           *(n - abs(iyt));
04598                                                                                 izt = -izt;
04599                                                                                 mirror = !mirror;
04600                                                                         } else {
04601                                                                                 iyt -= n*Util::sgn(iyt);
04602                                                                         }
04603                                                                 }
04604                                                                 if (izt >= nhalf || izt < -nhalf) {
04605                                                                         if (ixt != 0) {
04606                                                                                 ixt = -ixt;
04607                                                                                 iyt = -iyt;
04608                                                                                 izt = Util::sgn(izt)
04609                                                                                           *(n - abs(izt));
04610                                                                                 mirror = !mirror;
04611                                                                         } else {
04612                                                                                 izt -= Util::sgn(izt)*n;
04613                                                                         }
04614                                                                 }
04615                                                                 if (ixt < 0) {
04616                                                                         ixt = -ixt;
04617                                                                         iyt = -iyt;
04618                                                                         izt = -izt;
04619                                                                         mirror = !mirror;
04620                                                                 }
04621                                                                 if (iyt == nhalf) iyt = -nhalf;
04622                                                                 if (izt == nhalf) izt = -nhalf;
04623                                                                 if (mirror)   btq += conj(cmplx(ixt,iyt,izt))*wg;
04624                                                                 else          btq += cmplx(ixt,iyt,izt)*wg;
04625                                                                 wsum += wg;
04626                                                         }
04627                                                 }
04628                                         }
04629                                 }
04630                                 if (flip)  res->cmplx(jx,jy) = conj(btq);
04631                                 else       res->cmplx(jx,jy) = btq;
04632                         }
04633                 }
04634         }
04635         for (int jy = -nhalf; jy < nhalf; jy++)
04636                 for (int jx = 0; jx <= nhalf; jx++)
04637                         res->cmplx(jx,jy) *= count/wsum;
04638         delete[] wx0; delete[] wy0; delete[] wz0;
04639         set_array_offsets(saved_offsets);
04640         res->set_array_offsets(0,0,0);
04641         res->set_shuffled(true);
04642         return res;
04643 }
04644 
04645 
04647 
04648 
04649 
04650 EMData* EMData::extract_plane_rect(const Transform& tf, Util::KaiserBessel& kbx,Util::KaiserBessel& kby, Util::KaiserBessel& kbz) {
04651         
04652 
04653         if (!is_complex())
04654                 throw ImageFormatException("extractplane requires a complex image");
04655         if (nx%2 != 0)
04656                 throw ImageDimensionException("extractplane requires nx to be even");
04657 
04658         int nxfromxyz = max( max(nx-2,ny), nz) + 2;
04659         //int nxfromz = nz+2;
04660         //int nxcircal = nxfromz - 2;
04661         int nxcircal = nxfromxyz - 2;
04662         EMData* res = new EMData();
04663         //res->set_size(nxfromz,nz,1);
04664         res->set_size(nxfromxyz,nxcircal,1);
04665         res->to_zero();
04666         res->set_complex(true);
04667         res->set_fftodd(false);
04668         res->set_fftpad(true);
04669         res->set_ri(true);
04670         // Array offsets: (0..nhalf,-nhalf..nhalf-1,-nhalf..nhalf-1)
04671         int n = nxcircal;
04672         int nhalf = n/2;
04673         int nxhalf = (nx-2)/2;
04674         int nyhalf = ny/2;
04675         int nzhalf = nz/2;
04676         
04677         vector<int> saved_offsets = get_array_offsets();
04678         set_array_offsets(0, -nyhalf, -nzhalf);
04679         res->set_array_offsets(0,-nhalf,0);
04680         // set up some temporary weighting arrays
04681         int kbxsize =  kbx.get_window_size();
04682         int kbxmin  = -kbxsize/2;
04683         int kbxmax  = -kbxmin;
04684 
04685         int kbysize =  kby.get_window_size();
04686         int kbymin  = -kbysize/2;
04687         int kbymax  = -kbymin;
04688 
04689         int kbzsize =  kbz.get_window_size();
04690         int kbzmin  = -kbzsize/2;
04691         int kbzmax  = -kbzmin;
04692 
04693         //std::cout<<"kb size x,y,z=="<<kbxsize<<" "<<kbysize<<" "<<kbzsize<<std::endl;
04694         float* wy0 = new float[kbymax - kbymin + 1];
04695         float* wy  = wy0 - kbymin; // wy[kbmin:kbmax]
04696         float* wx0 = new float[kbxmax - kbxmin + 1];
04697         float* wx  = wx0 - kbxmin;
04698         float* wz0 = new float[kbzmax - kbzmin + 1];
04699         float* wz  = wz0 - kbzmin;
04700         float rim = nhalf*float(nhalf);
04701         int count = 0;
04702         float wsum = 0.f;
04703         Transform tftrans = tf; // need transpose of tf here for consistency
04704         tftrans.invert();      // with spider
04705         float xratio=float(nx-2)/float(nxcircal);
04706         float yratio=float(ny)/float(nxcircal);
04707         float zratio=float(nz)/float(nxcircal);
04708         //std::cout<<"xratio,yratio=="<<xratio<<" "<<yratio<<std::endl;
04709         for (int jy = -nhalf; jy < nhalf; jy++) 
04710         {
04711                 for (int jx = 0; jx <= nhalf; jx++) 
04712                 {
04713                         Vec3f nucur((float)jx, (float)jy, 0.f);
04714                         Vec3f nunew = tftrans*nucur;
04715                         float xnew = nunew[0]*xratio, ynew = nunew[1]*yratio, znew = nunew[2]*zratio;
04716                         
04717                         if (nunew[0]*nunew[0]+nunew[1]*nunew[1]+nunew[2]*nunew[2] <= rim)
04718                         {
04719                                 count++;
04720                                 std::complex<float> btq(0.f,0.f);
04721                                 bool flip = false;
04722                                 if (xnew < 0.f) {
04723                                         flip = true;
04724                                         xnew = -xnew;
04725                                         ynew = -ynew;
04726                                         znew = -znew;
04727                                 }
04728                                 int ixn = int(Util::round(xnew));
04729                                 int iyn = int(Util::round(ynew));
04730                                 int izn = int(Util::round(znew));
04731                                 // populate weight arrays
04732                                 for (int i=kbzmin; i <= kbzmax; i++) {
04733                                         int izp = izn + i;
04734                                         wz[i] = kbz.i0win_tab(znew - izp);
04735                                         }
04736                                 for (int i=kbymin; i <= kbymax; i++) {
04737                                         int iyp = iyn + i;
04738                                         wy[i] = kby.i0win_tab(ynew - iyp);
04739                                         }
04740                                 for (int i=kbxmin; i <= kbxmax; i++) {
04741                                         int ixp = ixn + i;
04742                                         wx[i] = kbx.i0win_tab(xnew - ixp);
04743                                         }
04744                 
04745 
04746                                 
04747                                 // restrict weight arrays to non-zero elements
04748                                 int lnbz = 0;
04749                                 for (int iz = kbzmin; iz <= -1; iz++) {
04750                                         if (wz[iz] != 0.f) {
04751                                                 lnbz = iz;
04752                                                 break;
04753                                         }
04754                                 }
04755                                 int lnez = 0;
04756                                 for (int iz = kbzmax; iz >= 1; iz--) {
04757                                         if (wz[iz] != 0.f) {
04758                                                 lnez = iz;
04759                                                 break;
04760                                         }
04761                                 }
04762                                 int lnby = 0;
04763                                 for (int iy = kbymin; iy <= -1; iy++) {
04764                                         if (wy[iy] != 0.f) {
04765                                                 lnby = iy;
04766                                                 break;
04767                                         }
04768                                 }
04769                                 int lney = 0;
04770                                 for (int iy = kbymax; iy >= 1; iy--) {
04771                                         if (wy[iy] != 0.f) {
04772                                                 lney = iy;
04773                                                 break;
04774                                         }
04775                                 }
04776                                 int lnbx = 0;
04777                                 for (int ix = kbxmin; ix <= -1; ix++) {
04778                                         if (wx[ix] != 0.f) {
04779                                                 lnbx = ix;
04780                                                 break;
04781                                         }
04782                                 }
04783                                 int lnex = 0;
04784                                 for (int ix = kbxmax; ix >= 1; ix--) {
04785                                         if (wx[ix] != 0.f) {
04786                                                 lnex = ix;
04787                                                 break;
04788                                         }
04789                                 }
04790                                 if    (ixn >= -kbxmin      && ixn <= nxhalf-1-kbxmax
04791                                    && iyn >= -nyhalf-kbymin && iyn <= nyhalf-1-kbymax
04792                                    && izn >= -nzhalf-kbzmin && izn <= nzhalf-1-kbzmax) {
04793                                         // interior points
04794                                         for (int lz = lnbz; lz <= lnez; lz++) {
04795                                                 int izp = izn + lz;
04796                                                 for (int ly=lnby; ly<=lney; ly++) {
04797                                                         int iyp = iyn + ly;
04798                                                         float ty = wz[lz]*wy[ly];
04799                                                         for (int lx=lnbx; lx<=lnex; lx++) {
04800                                                                 int ixp = ixn + lx;
04801                                                                 float wg = wx[lx]*ty;
04802                                                                 btq += cmplx(ixp,iyp,izp)*wg;
04803                                                                 wsum += wg;
04804                                                         }
04805                                                 }
04806                                         }
04807                                 } 
04808                                 else {
04809                                         // points "sticking out"
04810                                         for (int lz = lnbz; lz <= lnez; lz++) {
04811                                                 int izp = izn + lz;
04812                                                 for (int ly=lnby; ly<=lney; ly++) {
04813                                                         int iyp = iyn + ly;
04814                                                         float ty = wz[lz]*wy[ly];
04815                                                         for (int lx=lnbx; lx<=lnex; lx++) {
04816                                                                 int ixp = ixn + lx;
04817                                                                 float wg = wx[lx]*ty;
04818                                                                 bool mirror = false;
04819                                                                 int ixt(ixp), iyt(iyp), izt(izp);
04820                                                                 if (ixt > nxhalf || ixt < -nxhalf) {
04821                                                                         ixt = Util::sgn(ixt)
04822                                                                                   *(nx-2-abs(ixt));
04823                                                                         iyt = -iyt;
04824                                                                         izt = -izt;
04825                                                                         mirror = !mirror;
04826                                                                 }
04827                                                                 if (iyt >= nyhalf || iyt < -nyhalf) {
04828                                                                         if (ixt != 0) {
04829                                                                                 ixt = -ixt;
04830                                                                                 iyt = Util::sgn(iyt)
04831                                                                                           *(ny - abs(iyt));
04832                                                                                 izt = -izt;
04833                                                                                 mirror = !mirror;
04834                                                                         } else {
04835                                                                                 iyt -= ny*Util::sgn(iyt);
04836                                                                         }
04837                                                                 }
04838                                                                 if (izt >= nzhalf || izt < -nzhalf) {
04839                                                                         if (ixt != 0) {
04840                                                                                 ixt = -ixt;
04841                                                                                 iyt = -iyt;
04842                                                                                 izt = Util::sgn(izt)
04843                                                                                           *(nz - abs(izt));
04844                                                                                 mirror = !mirror;
04845                                                                         } else {
04846                                                                                 izt -= Util::sgn(izt)*nz;
04847                                                                         }
04848                                                                 }
04849                                                                 if (ixt < 0) {
04850                                                                         ixt = -ixt;
04851                                                                         iyt = -iyt;
04852                                                                         izt = -izt;
04853                                                                         mirror = !mirror;
04854                                                                 }
04855                                                                 if (iyt == nyhalf) iyt = -nyhalf;
04856                                                                 if (izt == nzhalf) izt = -nzhalf;
04857                                                                 if (mirror)   btq += conj(cmplx(ixt,iyt,izt))*wg;
04858                                                                 else          btq += cmplx(ixt,iyt,izt)*wg;
04859                                                                 wsum += wg;
04860                                                         }
04861                                                 }
04862                                         }
04863                                 }
04864                                 if (flip)  res->cmplx(jx,jy) = conj(btq);
04865                                 else       res->cmplx(jx,jy) = btq;
04866                         }
04867                 }
04868         }
04869         for (int jy = -nhalf; jy < nhalf; jy++)
04870                 for (int jx = 0; jx <= nhalf; jx++)
04871                         res->cmplx(jx,jy) *= count/wsum;
04872         delete[] wx0; delete[] wy0; delete[] wz0;
04873         set_array_offsets(saved_offsets);
04874         res->set_array_offsets(0,0,0);
04875         res->set_shuffled(true);
04876         return res;
04877 }
04878 
04879 
04880 
04881 EMData* EMData::extract_plane_rect_fast(const Transform& tf, Util::KaiserBessel& kbx,Util::KaiserBessel& kby, Util::KaiserBessel& kbz) {
04882         
04883         
04884 
04885         if (!is_complex())
04886                 throw ImageFormatException("extractplane requires a complex image");
04887         if (nx%2 != 0)
04888                 throw ImageDimensionException("extractplane requires nx to be even");
04889 
04890         int nxfromz=nz+2;
04891         int nxcircal = nxfromz - 2;
04892 
04893         // build complex result image
04894         float xratio=float(nx-2)/float(nz);
04895         float yratio=float(ny)/float(nz);
04896         Vec3f axis_newx,axis_newy;
04897         axis_newx[0] = xratio*0.5f*nz*tf[0][0];
04898         axis_newx[1] = yratio*0.5f*nz*tf[0][1];
04899         axis_newx[2] = 0.5f*nz*tf[0][2];
04900 
04901 
04902         float ellipse_length_x=std::sqrt(axis_newx[0]*axis_newx[0]+axis_newx[1]*axis_newx[1]+axis_newx[2]*axis_newx[2]);
04903         
04904         int ellipse_length_x_int=int(ellipse_length_x);
04905         float ellipse_step_x=0.5f*nz/float(ellipse_length_x_int);
04906         float xscale=ellipse_step_x;//scal increased
04907 
04908         axis_newy[0] = xratio*0.5f*nz*tf[1][0];
04909         axis_newy[1] = yratio*0.5f*nz*tf[1][1];
04910         axis_newy[2] = 0.5f*nz*tf[1][2];
04911 
04912 
04913         float ellipse_length_y=std::sqrt(axis_newy[0]*axis_newy[0]+axis_newy[1]*axis_newy[1]+axis_newy[2]*axis_newy[2]);
04914         int ellipse_length_y_int=int(ellipse_length_y);
04915         float ellipse_step_y=0.5f*nz/float(ellipse_length_y_int);
04916         float yscale=ellipse_step_y;
04917         //end of scaling factor calculation
04918         int nx_e=ellipse_length_x_int*2;
04919         int ny_e=ellipse_length_y_int*2;
04920         int nx_ec=nx_e+2;       
04921 
04922         EMData* res = new EMData();
04923         res->set_size(nx_ec,ny_e,1);
04924         res->to_zero();
04925         res->set_complex(true);
04926         res->set_fftodd(false);
04927         res->set_fftpad(true);
04928         res->set_ri(true);
04929         //std::cout<<"cpp fast extract_plane is called"<<std::endl;
04930         //std::cout<<"nx_e,ny_e===="<<nx_e<<"  "<<ny_e<<std::endl;
04931         // Array offsets: (0..nhalf,-nhalf..nhalf-1,-nhalf..nhalf-1)
04932         int n = nxcircal;
04933         int nhalf = n/2;
04934         int nhalfx_e = nx_e/2;
04935         int nhalfy_e = ny_e/2;
04936         int nxhalf=(nx-2)/2;
04937         int nyhalf=ny/2;
04938         int nzhalf=nz/2;
04939         //std::cout<<"nhalf,nxhalf,nyhalf,nzhalf=="<<nhalf<<" "<<nxhalf<<" "<<nyhalf<<" "<<nzhalf<<std::endl;
04940         vector<int> saved_offsets = get_array_offsets();
04941         set_array_offsets(0,-nyhalf,-nzhalf);
04942         res->set_array_offsets(0,-nhalfy_e,0);
04943         // set up some temporary weighting arrays
04944         int kbxsize =  kbx.get_window_size();
04945         int kbxmin  = -kbxsize/2;
04946         int kbxmax  = -kbxmin;
04947 
04948         int kbysize =  kby.get_window_size();
04949         int kbymin  = -kbysize/2;
04950         int kbymax  = -kbymin;
04951 
04952         int kbzsize =  kbz.get_window_size();
04953         int kbzmin  = -kbzsize/2;
04954         int kbzmax  = -kbzmin;
04955 
04956         //std::cout<<"kb size x,y,z=="<<kbxsize<<" "<<kbysize<<" "<<kbzsize<<std::endl;
04957         float* wy0 = new float[kbymax - kbymin + 1];
04958         float* wy  = wy0 - kbymin; // wy[kbmin:kbmax]
04959         float* wx0 = new float[kbxmax - kbxmin + 1];
04960         float* wx  = wx0 - kbxmin;
04961         float* wz0 = new float[kbzmax - kbzmin + 1];
04962         float* wz  = wz0 - kbzmin;
04963         float rim = nhalf*float(nhalf);
04964         int count = 0;
04965         float wsum = 0.f;
04966         Transform tftrans = tf; // need transpose of tf here for consistency
04967         tftrans.invert();      // with spider
04968 
04969         //std::cout<<"xratio,yratio=="<<xratio<<" "<<yratio<<std::endl;
04970         for (int jy = -nhalfy_e; jy < nhalfy_e; jy++) 
04971         {
04972                 for (int jx = 0; jx <= nhalfx_e; jx++) 
04973                 {
04974                         Vec3f nucur((float)jx, (float)jy, 0.f);
04975                         nucur[0]=nucur[0]*xscale;nucur[1]=nucur[1]*yscale;;
04976                         Vec3f nunew = tftrans*nucur;
04977                         float xnew = nunew[0]*xratio, ynew = nunew[1]*yratio, znew = nunew[2];
04978                         
04979                         if (nunew[0]*nunew[0]+nunew[1]*nunew[1]+nunew[2]*nunew[2] <= rim)
04980                         {
04981                                 count++;
04982                                 std::complex<float> btq(0.f,0.f);
04983                                 bool flip = false;
04984                                 if (xnew < 0.f) {
04985                                         flip = true;
04986                                         xnew = -xnew;
04987                                         ynew = -ynew;
04988                                         znew = -znew;
04989                                 }
04990                                 int ixn = int(Util::round(xnew));
04991                                 int iyn = int(Util::round(ynew));
04992                                 int izn = int(Util::round(znew));
04993                                 // populate weight arrays
04994                                 for (int i=kbzmin; i <= kbzmax; i++) {
04995                                         int izp = izn + i;
04996                                         wz[i] = kbz.i0win_tab(znew - izp);
04997                                         }
04998                                 for (int i=kbymin; i <= kbymax; i++) {
04999                                         int iyp = iyn + i;
05000                                         wy[i] = kby.i0win_tab(ynew - iyp);
05001                                         }
05002                                 for (int i=kbxmin; i <= kbxmax; i++) {
05003                                         int ixp = ixn + i;
05004                                         wx[i] = kbx.i0win_tab(xnew - ixp);
05005                                         }
05006                 
05007 
05008                                 
05009                                 // restrict weight arrays to non-zero elements
05010                                 int lnbz = 0;
05011                                 for (int iz = kbzmin; iz <= -1; iz++) {
05012                                         if (wz[iz] != 0.f) {
05013                                                 lnbz = iz;
05014                                                 break;
05015                                         }
05016                                 }
05017                                 int lnez = 0;
05018                                 for (int iz = kbzmax; iz >= 1; iz--) {
05019                                         if (wz[iz] != 0.f) {
05020                                                 lnez = iz;
05021                                                 break;
05022                                         }
05023                                 }
05024                                 int lnby = 0;
05025                                 for (int iy = kbymin; iy <= -1; iy++) {
05026                                         if (wy[iy] != 0.f) {
05027                                                 lnby = iy;
05028                                                 break;
05029                                         }
05030                                 }
05031                                 int lney = 0;
05032                                 for (int iy = kbymax; iy >= 1; iy--) {
05033                                         if (wy[iy] != 0.f) {
05034                                                 lney = iy;
05035                                                 break;
05036                                         }
05037                                 }
05038                                 int lnbx = 0;
05039                                 for (int ix = kbxmin; ix <= -1; ix++) {
05040                                         if (wx[ix] != 0.f) {
05041                                                 lnbx = ix;
05042                                                 break;
05043                                         }
05044                                 }
05045                                 int lnex = 0;
05046                                 for (int ix = kbxmax; ix >= 1; ix--) {
05047                                         if (wx[ix] != 0.f) {
05048                                                 lnex = ix;
05049                                                 break;
05050                                         }
05051                                 }
05052                                 if    (ixn >= -kbxmin      && ixn <= nxhalf-1-kbxmax
05053                                    && iyn >= -nyhalf-kbymin && iyn <= nyhalf-1-kbymax
05054                                    && izn >= -nzhalf-kbzmin && izn <= nzhalf-1-kbzmax) {
05055                                         // interior points
05056                                         for (int lz = lnbz; lz <= lnez; lz++) {
05057                                                 int izp = izn + lz;
05058                                                 for (int ly=lnby; ly<=lney; ly++) {
05059                                                         int iyp = iyn + ly;
05060                                                         float ty = wz[lz]*wy[ly];
05061                                                         for (int lx=lnbx; lx<=lnex; lx++) {
05062                                                                 int ixp = ixn + lx;
05063                                                                 float wg = wx[lx]*ty;
05064                                                                 btq += cmplx(ixp,iyp,izp)*wg;
05065                                                                 wsum += wg;
05066                                                         }
05067                                                 }
05068                                         }
05069                                 } 
05070                                 else {
05071                                         // points "sticking out"
05072                                         for (int lz = lnbz; lz <= lnez; lz++) {
05073                                                 int izp = izn + lz;
05074                                                 for (int ly=lnby; ly<=lney; ly++) {
05075                                                         int iyp = iyn + ly;
05076                                                         float ty = wz[lz]*wy[ly];
05077                                                         for (int lx=lnbx; lx<=lnex; lx++) {
05078                                                                 int ixp = ixn + lx;
05079                                                                 float wg = wx[lx]*ty;
05080                                                                 bool mirror = false;
05081                                                                 int ixt(ixp), iyt(iyp), izt(izp);
05082                                                                 if (ixt > nxhalf || ixt < -nxhalf) {
05083                                                                         ixt = Util::sgn(ixt)
05084                                                                                   *(nx-2-abs(ixt));
05085                                                                         iyt = -iyt;
05086                                                                         izt = -izt;
05087                                                                         mirror = !mirror;
05088                                                                 }
05089                                                                 if (iyt >= nyhalf || iyt < -nyhalf) {
05090                                                                         if (ixt != 0) {
05091                                                                                 ixt = -ixt;
05092                                                                                 iyt = Util::sgn(iyt)
05093                                                                                           *(ny - abs(iyt));
05094                                                                                 izt = -izt;
05095                                                                                 mirror = !mirror;
05096                                                                         } else {
05097                                                                                 iyt -= ny*Util::sgn(iyt);
05098                                                                         }
05099                                                                 }
05100                                                                 if (izt >= nzhalf || izt < -nzhalf) {
05101                                                                         if (ixt != 0) {
05102                                                                                 ixt = -ixt;
05103                                                                                 iyt = -iyt;
05104                                                                                 izt = Util::sgn(izt)
05105                                                                                           *(nz - abs(izt));
05106                                                                                 mirror = !mirror;
05107                                                                         } else {
05108                                                                                 izt -= Util::sgn(izt)*nz;
05109                                                                         }
05110                                                                 }
05111                                                                 if (ixt < 0) {
05112                                                                         ixt = -ixt;
05113                                                                         iyt = -iyt;
05114                                                                         izt = -izt;
05115                                                                         mirror = !mirror;
05116                                                                 }
05117                                                                 if (iyt == nyhalf) iyt = -nyhalf;
05118                                                                 if (izt == nzhalf) izt = -nzhalf;
05119                                                                 if (mirror)   btq += conj(cmplx(ixt,iyt,izt))*wg;
05120                                                                 else          btq += cmplx(ixt,iyt,izt)*wg;
05121                                                                 wsum += wg;
05122                                                         }
05123                                                 }
05124                                         }
05125                                 }
05126                                 if (flip)  res->cmplx(jx,jy) = conj(btq);
05127                                 else       res->cmplx(jx,jy) = btq;
05128                         }
05129                 }
05130         }
05131         for (int jy = -nhalfy_e; jy < nhalfy_e; jy++)
05132                 for (int jx = 0; jx <= nhalfx_e; jx++)
05133                         res->cmplx(jx,jy) *= count/wsum;
05134         delete[] wx0; delete[] wy0; delete[] wz0;
05135         set_array_offsets(saved_offsets);
05136         res->set_array_offsets(0,0,0);
05137         res->set_shuffled(true);
05138         return res;
05139 }
05140 
05141 
05142 
05143 
05144 bool EMData::peakcmp(const Pixel& p1, const Pixel& p2) {
05145     return (p1.value > p2.value);
05146 }
05147 
05148 ostream& operator<< (ostream& os, const Pixel& peak) {
05149     os <<  peak.x <<  peak.y << peak.z  << peak.value;
05150     return os;
05151 }
05152 
05153 /*vector<float> EMData::max_search() {
05154 
05155         EMData& buf = *this;
05156 
05157         int nx = buf.get_xsize();
05158         int ny = buf.get_ysize();
05159         int nz = buf.get_zsize();
05160 
05161         int dim = buf.get_ndim();
05162 
05163         vector<float> result;
05164 
05165         if (dim == 1) {
05166                 float max = -1e20f;
05167                 int index = -1;
05168                 for (int i=0; i<nx; i++) {
05169                         if (buf(i)>max) {
05170                                 max = buf(i);
05171                                 index = i;
05172                         }
05173                 }
05174                 result.push_back((float)index);
05175                 result.push_back(max);
05176         } else if (dim == 2) {
05177                 float max = -1e20f;
05178                 int index1 = -1;
05179                 int index2 = -1;
05180                 for (int i=0; i<nx; i++) {
05181                         for (int j=0; j<ny; j++) {
05182                                 if (buf(i, j)>max) {
05183                                         max = buf(i, j);
05184                                         index1 = i;
05185                                         index2 = j;
05186                                 }
05187                         }
05188                 }
05189                 result.push_back((float)index1);
05190                 result.push_back((float)index2);
05191                 result.push_back(max);
05192         } else {
05193                 float max = -1e20f;
05194                 int index1 = -1;
05195                 int index2 = -1;
05196                 int index3 = -1;
05197                 for (int i=0; i<nx; i++) {
05198                         for (int j=0; j<ny; j++) {
05199                                 for (int k=0; k<nz; k++) {
05200                                         if (buf(i, j, k)>max) {
05201                                                 max = buf(i, j, k);
05202                                                 index1 = i;
05203                                                 index2 = j;
05204                                                 index3 = k;
05205                                         }
05206                                 }
05207                         }
05208                 }
05209                 result.push_back((float)index1);
05210                 result.push_back((float)index2);
05211                 result.push_back((float)index3);
05212                 result.push_back(max);
05213         }
05214         return result;
05215 }*/
05216 
05217 vector<float> EMData::peak_search(int ml, float invert) {
05218 
05219         EMData& buf = *this;
05220         vector<Pixel> peaks;
05221         int img_dim;
05222         int i, j, k;
05223         int i__1, i__2;
05224         int j__1, j__2;
05225         //int k__1, k__2;
05226         bool peak_check;
05227         img_dim=buf.get_ndim();
05228         vector<int> ix, jy, kz;
05229         vector<float>res;
05230         int nx = buf.get_xsize();
05231         int ny = buf.get_ysize();
05232         int nz = buf.get_zsize();
05233         if(invert <= 0.0f)  invert=-1.0f;
05234         else                invert=1.0f ;
05235         int count = 0;
05236         switch (img_dim)  {
05237         case(1):
05238                 for(i=0;i<=nx-1;++i)  {
05239                         i__1 = (i-1+nx)%nx;
05240                         i__2 = (i+1)%nx;
05241                         // Commented by Yang on 05/14/07
05242                         // I changed the following line from > to >=, or in some rare cases (the peak happens to be flat), it will fail to find the peak.
05243                         //  03/07/08  I undid the change.  If you change the comparison, it changes the meaning of peak definition.
05244                         float qbf = buf(i)*invert;
05245                         peak_check = qbf > buf(i__1)*invert && qbf > buf(i__2)*invert;
05246                         if(peak_check) {
05247                                 if(count < ml) {
05248                                         count++;
05249                                         peaks.push_back( Pixel(i, 0, 0, qbf) );
05250                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05251                                 } else {
05252                                         if( qbf > (peaks.back()).value ) {
05253                                                 //  do the switch and sort again
05254                                                 peaks.pop_back();
05255                                                 peaks.push_back( Pixel(i, 0, 0, qbf) );
05256                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05257                                         }
05258                                 }
05259                         }
05260                 }
05261         break;
05262         case(2):
05263         /*  Removed boundary conditions, PAP 03/10/08
05264                 for(j=0;j<=ny-1;++j)  {
05265                         j__1 = (j-1+ny)%ny;
05266                         j__2 = (j+1)%ny;
05267                         for(i=0;i<=nx-1;++i) {
05268                                 i__1 = (i-1+nx)%nx;
05269                                 i__2 = (i+1)%nx;
05270         */
05271                 for(j=1;j<=ny-2;++j)  {
05272                         j__1 = j-1;
05273                         j__2 = j+1;
05274                         for(i=1;i<=nx-2;++i) {
05275                                 i__1 = i-1;
05276                                 i__2 = i+1;
05277                                 float qbf = buf(i,j)*invert;
05278                                 peak_check = (qbf > buf(i,j__1)*invert) && (qbf > buf(i,j__2)*invert);
05279                                 if(peak_check) {
05280                                         peak_check = (qbf > buf(i__1,j)*invert) && (qbf > buf(i__2,j)*invert);
05281                                         if(peak_check) {
05282                                                 peak_check = (qbf > buf(i__1,j__1)*invert) && (qbf > buf(i__1,j__2)*invert);
05283                                                 if(peak_check) {
05284                                                         peak_check = (qbf > buf(i__2,j__1)*invert) && (qbf > buf(i__2,j__2)*invert);
05285                                                         if(peak_check) {
05286                                                                 if(count < ml) {
05287                                                                         count++;
05288                                                                         peaks.push_back( Pixel(i, j, 0, qbf) );
05289                                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05290                                                                 } else {
05291                                                                         if( qbf > (peaks.back()).value ) {
05292                                                                                 //  do the switch and sort again
05293                                                                                 peaks.pop_back();
05294                                                                                 peaks.push_back( Pixel(i, j, 0, qbf) );
05295                                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05296                                                                         }
05297                                                                 }
05298                                                         }
05299                                                 }
05300                                         }
05301                                 }
05302                         }
05303                 }
05304         break;
05305         case(3):  //looks ugly, but it is the best I can do,  PAP 03/07/08
05306         /*  Removed boundary conditions, PAP 03/10/08
05307                 for(k=0;k<=nz-1;++k) {
05308                         kz.clear();
05309                         k__1 = (k-1+nz)%nz;
05310                         k__2 = (k+1)%nz;
05311                         kz.push_back(k__1);
05312                         kz.push_back(k);
05313                         kz.push_back(k__2);
05314                         for(j=0;j<=ny-1;++j) {
05315                                 jy.clear();
05316                                 j__1 = (j-1+ny)%ny;
05317                                 j__2 = (j+1)%ny;
05318                                 jy.push_back(j__1);
05319                                 jy.push_back(j);
05320                                 jy.push_back(j__2);
05321                                 for(i=0;i<=nx-1;++i) {
05322                                         ix.clear();
05323                                         i__1 = (i-1+nx)%nx;
05324                                         i__2 = (i+1)%nx;
05325         */
05326                 for(k=1; k<=nz-2; ++k) {
05327                         kz.clear();
05328                         kz.push_back(k-1);
05329                         kz.push_back(k);
05330                         kz.push_back(k+1);
05331                         for(j=1; j<=ny-2; ++j) {
05332                                 jy.clear();
05333                                 jy.push_back(j-1);
05334                                 jy.push_back(j);
05335                                 jy.push_back(j+1);
05336                                 for(i=1; i<=nx-2; ++i) {
05337                                         ix.clear();
05338                                         ix.push_back(i-1);
05339                                         ix.push_back(i);
05340                                         ix.push_back(i+1);
05341                                         float qbf = buf(i,j,k)*invert;
05342                                         peak_check = qbf > buf(ix[0],jy[0],kz[0])*invert;
05343                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0])*invert;
05344                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0])*invert;
05345                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0])*invert;
05346                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0])*invert;
05347                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0])*invert;
05348                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0])*invert;
05349                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0])*invert;
05350                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0])*invert;
05351                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1])*invert;
05352                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1])*invert;
05353                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1])*invert;
05354                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1])*invert;
05355                                         //if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1])*invert;
05356                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1])*invert;
05357                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1])*invert;
05358                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1])*invert;
05359                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1])*invert;
05360                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2])*invert;
05361                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2])*invert;
05362                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2])*invert;
05363                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2])*invert;
05364                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2])*invert;
05365                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2])*invert;
05366                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2])*invert;
05367                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2])*invert;
05368                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2])*invert;
05369                                         if(peak_check) {
05370                                                 if(count < ml) {
05371                                                         count++;
05372                                                         peaks.push_back( Pixel(i, j, k, qbf) );
05373                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05374                                                 } else {
05375                                                         if( qbf > (peaks.back()).value ) {
05376                                                                 //  do the switch and sort again
05377                                                                 //cout << qbf<<"   "<< (peaks.back()).value <<"   "<< (*peaks.begin()).value <<endl;
05378                                                                 peaks.pop_back();
05379                                                                 peaks.push_back( Pixel(i, j, k, qbf) );
05380                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05381                                                         }
05382                                                 }
05383                                         }
05384                                         }}}}}}}}}}}}}}}}}}}}}}}}}
05385                                 }
05386                         }
05387                 }
05388                 //  Add circular closure for x direction: needed for circular ccf,
05389                 //  should not have adverse impact on other code.  PAP -7/22/08
05390                 for(k=1; k<=nz-2; ++k) {
05391                         kz.clear();
05392                         kz.push_back(k-1);
05393                         kz.push_back(k);
05394                         kz.push_back(k+1);
05395                         for(j=1; j<=ny-2; ++j) {
05396                                 jy.clear();
05397                                 jy.push_back(j-1);
05398                                 jy.push_back(j);
05399                                 jy.push_back(j+1);
05400                                 for(i=0; i<=0; ++i) {
05401                                         ix.clear();
05402                                         ix.push_back(nx-1);
05403                                         ix.push_back(i);
05404                                         ix.push_back(i+1);
05405                                         float qbf = buf(i,j,k)*invert;
05406                                         peak_check = qbf > buf(ix[0],jy[0],kz[0])*invert;
05407                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0])*invert;
05408                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0])*invert;
05409                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0])*invert;
05410                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0])*invert;
05411                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0])*invert;
05412                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0])*invert;
05413                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0])*invert;
05414                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0])*invert;
05415                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1])*invert;
05416                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1])*invert;
05417                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1])*invert;
05418                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1])*invert;
05419                                         //if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1])*invert;
05420                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1])*invert;
05421                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1])*invert;
05422                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1])*invert;
05423                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1])*invert;
05424                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2])*invert;
05425                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2])*invert;
05426                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2])*invert;
05427                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2])*invert;
05428                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2])*invert;
05429                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2])*invert;
05430                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2])*invert;
05431                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2])*invert;
05432                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2])*invert;
05433                                         if(peak_check) {
05434                                                 if(count < ml) {
05435                                                         count++;
05436                                                         peaks.push_back( Pixel(i, j, k, qbf) );
05437                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05438                                                 } else {
05439                                                         if( qbf > (peaks.back()).value ) {
05440                                                                 //  do the switch and sort again
05441                                                                 //cout << qbf<<"   "<< (peaks.back()).value <<"   "<< (*peaks.begin()).value <<endl;
05442                                                                 peaks.pop_back();
05443                                                                 peaks.push_back( Pixel(i, j, k, qbf) );
05444                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05445                                                         }
05446                                                 }
05447                                         }
05448                                         }}}}}}}}}}}}}}}}}}}}}}}}}
05449                                 }
05450                                 for(i=nx-1; i<=nx-1; ++i) {
05451                                         ix.clear();
05452                                         ix.push_back(i-1);
05453                                         ix.push_back(i);
05454                                         ix.push_back(0);
05455                                         float qbf = buf(i,j,k)*invert;
05456                                         peak_check = qbf > buf(ix[0],jy[0],kz[0])*invert;
05457                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0])*invert;
05458                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0])*invert;
05459                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0])*invert;
05460                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0])*invert;
05461                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0])*invert;
05462                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0])*invert;
05463                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0])*invert;
05464                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0])*invert;
05465                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1])*invert;
05466                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1])*invert;
05467                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1])*invert;
05468                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1])*invert;
05469                                         //if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1])*invert;
05470                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1])*invert;
05471                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1])*invert;
05472                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1])*invert;
05473                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1])*invert;
05474                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2])*invert;
05475                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2])*invert;
05476                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2])*invert;
05477                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2])*invert;
05478                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2])*invert;
05479                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2])*invert;
05480                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2])*invert;
05481                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2])*invert;
05482                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2])*invert;
05483                                         if(peak_check) {
05484                                                 if(count < ml) {
05485                                                         count++;
05486                                                         peaks.push_back( Pixel(i, j, k, qbf) );
05487                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05488                                                 } else {
05489                                                         if( qbf > (peaks.back()).value ) {
05490                                                                 //  do the switch and sort again
05491                                                                 //cout << qbf<<"   "<< (peaks.back()).value <<"   "<< (*peaks.begin()).value <<endl;
05492                                                                 peaks.pop_back();
05493                                                                 peaks.push_back( Pixel(i, j, k, qbf) );
05494                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05495                                                         }
05496                                                 }
05497                                         }
05498                                         }}}}}}}}}}}}}}}}}}}}}}}}}
05499                                 }
05500                         }
05501                 }
05502         break;
05503 /*      case(5):  //looks ugly, but it is the best I can do,  PAP 03/07/08
05504         int nu = buf.get_usize();
05505         int nv = buf.get_vsize();
05506         vector<int> lu, mv;
05507                 for(m=1; m<=nv-2; ++m) {
05508                         mv.clear();
05509                         mv.push_back(m-1);
05510                         mv.push_back(m);
05511                         mv.push_back(m+1);
05512                 for(l=1; l<=nu-2; ++l) {
05513                         lu.clear();
05514                         lu.push_back(l-1);
05515                         lu.push_back(l);
05516                         lu.push_back(l+1);
05517                 for(k=1; k<=nz-2; ++k) {
05518                         kz.clear();
05519                         kz.push_back(k-1);
05520                         kz.push_back(k);
05521                         kz.push_back(k+1);
05522                         for(j=1; j<=ny-2; ++j) {
05523                                 jy.clear();
05524                                 jy.push_back(j-1);
05525                                 jy.push_back(j);
05526                                 jy.push_back(j+1);
05527                                 for(i=1; i<=nx-2; ++i) {
05528                                         ix.clear();
05529                                         ix.push_back(i-1);
05530                                         ix.push_back(i);
05531                                         ix.push_back(i+1);
05532                                         float qbf = buf(i,j,k,l,m)*invert;
05533                                         peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[0],mv[0])*invert;
05534                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[0],mv[0])*invert;
05535                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[0],mv[0])*invert;
05536                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[0],mv[0])*invert;
05537                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[0],mv[0])*invert;
05538                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[0],mv[0])*invert;
05539                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[0],mv[0])*invert;
05540                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[0],mv[0])*invert;
05541                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[0],mv[0])*invert;
05542                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[0],mv[0])*invert;
05543                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[0],mv[0])*invert;
05544                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[0],mv[0])*invert;
05545                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[0],mv[0])*invert;
05546                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[0],mv[0])*invert;
05547                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[0],mv[0])*invert;
05548                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[0],mv[0])*invert;
05549                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[0],mv[0])*invert;
05550                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[0],mv[0])*invert;
05551                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[0],mv[0])*invert;
05552                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[0],mv[0])*invert;
05553                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[0],mv[0])*invert;
05554                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[0],mv[0])*invert;
05555                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[0],mv[0])*invert;
05556                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[0],mv[0])*invert;
05557                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[0],mv[0])*invert;
05558                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[0],mv[0])*invert;
05559                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[0],mv[0])*invert;
05560 
05561                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[1],mv[0])*invert;
05562                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[1],mv[0])*invert;
05563                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[1],mv[0])*invert;
05564                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[1],mv[0])*invert;
05565                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[1],mv[0])*invert;
05566                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[1],mv[0])*invert;
05567                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[1],mv[0])*invert;
05568                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[1],mv[0])*invert;
05569                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[1],mv[0])*invert;
05570                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[1],mv[0])*invert;
05571                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[1],mv[0])*invert;
05572                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[1],mv[0])*invert;
05573                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[1],mv[0])*invert;
05574                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[1],mv[0])*invert;
05575                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[1],mv[0])*invert;
05576                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[1],mv[0])*invert;
05577                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[1],mv[0])*invert;
05578                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[1],mv[0])*invert;
05579                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[1],mv[0])*invert;
05580                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[1],mv[0])*invert;
05581                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[1],mv[0])*invert;
05582                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[1],mv[0])*invert;
05583                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[1],mv[0])*invert;
05584                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[1],mv[0])*invert;
05585                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[1],mv[0])*invert;
05586                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[1],mv[0])*invert;
05587                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[1],mv[0])*invert;
05588 
05589                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[2],mv[0])*invert;
05590                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[2],mv[0])*invert;
05591                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[2],mv[0])*invert;
05592                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[2],mv[0])*invert;
05593                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[2],mv[0])*invert;
05594                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[2],mv[0])*invert;
05595                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[2],mv[0])*invert;
05596                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[2],mv[0])*invert;
05597                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[2],mv[0])*invert;
05598                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[2],mv[0])*invert;
05599                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[2],mv[0])*invert;
05600                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[2],mv[0])*invert;
05601                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[2],mv[0])*invert;
05602                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[2],mv[0])*invert;
05603                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[2],mv[0])*invert;
05604                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[2],mv[0])*invert;
05605                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[2],mv[0])*invert;
05606                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[2],mv[0])*invert;
05607                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[2],mv[0])*invert;
05608                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[2],mv[0])*invert;
05609                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[2],mv[0])*invert;
05610                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[2],mv[0])*invert;
05611                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[2],mv[0])*invert;
05612                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[2],mv[0])*invert;
05613                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[2],mv[0])*invert;
05614                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[2],mv[0])*invert;
05615                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[2],mv[0])*invert;
05616 
05617 
05618                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[0],mv[1])*invert;
05619                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[0],mv[1])*invert;
05620                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[0],mv[1])*invert;
05621                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[0],mv[1])*invert;
05622                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[0],mv[1])*invert;
05623                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[0],mv[1])*invert;
05624                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[0],mv[1])*invert;
05625                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[0],mv[1])*invert;
05626                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[0],mv[1])*invert;
05627                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[0],mv[1])*invert;
05628                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[0],mv[1])*invert;
05629                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[0],mv[1])*invert;
05630                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[0],mv[1])*invert;
05631                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[0],mv[1])*invert;
05632                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[0],mv[1])*invert;
05633                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[0],mv[1])*invert;
05634                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[0],mv[1])*invert;
05635                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[0],mv[1])*invert;
05636                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[0],mv[1])*invert;
05637                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[0],mv[1])*invert;
05638                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[0],mv[1])*invert;
05639                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[0],mv[1])*invert;
05640                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[0],mv[1])*invert;
05641                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[0],mv[1])*invert;
05642                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[0],mv[1])*invert;
05643                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[0],mv[1])*invert;
05644                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[0],mv[1])*invert;
05645 
05646                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[1],mv[1])*invert;
05647                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[1],mv[1])*invert;
05648                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[1],mv[1])*invert;
05649                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[1],mv[1])*invert;
05650                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[1],mv[1])*invert;
05651                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[1],mv[1])*invert;
05652                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[1],mv[1])*invert;
05653                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[1],mv[1])*invert;
05654                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[1],mv[1])*invert;
05655                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[1],mv[1])*invert;
05656                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[1],mv[1])*invert;
05657                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[1],mv[1])*invert;
05658                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[1],mv[1])*invert;
05659                                         //if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[1],mv[1])*invert;
05660                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[1],mv[1])*invert;
05661                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[1],mv[1])*invert;
05662                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[1],mv[1])*invert;
05663                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[1],mv[1])*invert;
05664                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[1],mv[1])*invert;
05665                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[1],mv[1])*invert;
05666                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[1],mv[1])*invert;
05667                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[1],mv[1])*invert;
05668                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[1],mv[1])*invert;
05669                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[1],mv[1])*invert;
05670                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[1],mv[1])*invert;
05671                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[1],mv[1])*invert;
05672                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[1],mv[1])*invert;
05673 
05674                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[2],mv[1])*invert;
05675                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[2],mv[1])*invert;
05676                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[2],mv[1])*invert;
05677                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[2],mv[1])*invert;
05678                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[2],mv[1])*invert;
05679                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[2],mv[1])*invert;
05680                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[2],mv[1])*invert;
05681                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[2],mv[1])*invert;
05682                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[2],mv[1])*invert;
05683                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[2],mv[1])*invert;
05684                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[2],mv[1])*invert;
05685                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[2],mv[1])*invert;
05686                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[2],mv[1])*invert;
05687                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[2],mv[1])*invert;
05688                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[2],mv[1])*invert;
05689                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[2],mv[1])*invert;
05690                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[2],mv[1])*invert;
05691                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[2],mv[1])*invert;
05692                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[2],mv[1])*invert;
05693                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[2],mv[1])*invert;
05694                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[2],mv[1])*invert;
05695                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[2],mv[1])*invert;
05696                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[2],mv[1])*invert;
05697                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[2],mv[1])*invert;
05698                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[2],mv[1])*invert;
05699                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[2],mv[1])*invert;
05700                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[2],mv[1])*invert;
05701 
05702 
05703                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[0],mv[2])*invert;
05704                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[0],mv[2])*invert;
05705                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[0],mv[2])*invert;
05706                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[0],mv[2])*invert;
05707                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[0],mv[2])*invert;
05708                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[0],mv[2])*invert;
05709                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[0],mv[2])*invert;
05710                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[0],mv[2])*invert;
05711                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[0],mv[2])*invert;
05712                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[0],mv[2])*invert;
05713                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[0],mv[2])*invert;
05714                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[0],mv[2])*invert;
05715                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[0],mv[2])*invert;
05716                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[0],mv[2])*invert;
05717                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[0],mv[2])*invert;
05718                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[0],mv[2])*invert;
05719                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[0],mv[2])*invert;
05720                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[0],mv[2])*invert;
05721                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[0],mv[2])*invert;
05722                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[0],mv[2])*invert;
05723                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[0],mv[2])*invert;
05724                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[0],mv[2])*invert;
05725                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[0],mv[2])*invert;
05726                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[0],mv[2])*invert;
05727                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[0],mv[2])*invert;
05728                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[0],mv[2])*invert;
05729                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[0],mv[2])*invert;
05730 
05731                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[1],mv[2])*invert;
05732                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[1],mv[2])*invert;
05733                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[1],mv[2])*invert;
05734                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[1],mv[2])*invert;
05735                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[1],mv[2])*invert;
05736                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[1],mv[2])*invert;
05737                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[1],mv[2])*invert;
05738                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[1],mv[2])*invert;
05739                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[1],mv[2])*invert;
05740                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[1],mv[2])*invert;
05741                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[1],mv[2])*invert;
05742                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[1],mv[2])*invert;
05743                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[1],mv[2])*invert;
05744                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[1],mv[2])*invert;
05745                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[1],mv[2])*invert;
05746                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[1],mv[2])*invert;
05747                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[1],mv[2])*invert;
05748                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[1],mv[2])*invert;
05749                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[1],mv[2])*invert;
05750                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[1],mv[2])*invert;
05751                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[1],mv[2])*invert;
05752                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[1],mv[2])*invert;
05753                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[1],mv[2])*invert;
05754                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[1],mv[2])*invert;
05755                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[1],mv[2])*invert;
05756                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[1],mv[2])*invert;
05757                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[1],mv[2])*invert;
05758 
05759                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[0],lu[2],mv[2])*invert;
05760                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0],lu[2],mv[2])*invert;
05761                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0],lu[2],mv[2])*invert;
05762                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0],lu[2],mv[2])*invert;
05763                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0],lu[2],mv[2])*invert;
05764                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0],lu[2],mv[2])*invert;
05765                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0],lu[2],mv[2])*invert;
05766                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0],lu[2],mv[2])*invert;
05767                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0],lu[2],mv[2])*invert;
05768                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1],lu[2],mv[2])*invert;
05769                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1],lu[2],mv[2])*invert;
05770                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1],lu[2],mv[2])*invert;
05771                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1],lu[2],mv[2])*invert;
05772                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1],lu[2],mv[2])*invert;
05773                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1],lu[2],mv[2])*invert;
05774                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1],lu[2],mv[2])*invert;
05775                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1],lu[2],mv[2])*invert;
05776                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1],lu[2],mv[2])*invert;
05777                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2],lu[2],mv[2])*invert;
05778                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2],lu[2],mv[2])*invert;
05779                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2],lu[2],mv[2])*invert;
05780                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2],lu[2],mv[2])*invert;
05781                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2],lu[2],mv[2])*invert;
05782                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2],lu[2],mv[2])*invert;
05783                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2],lu[2],mv[2])*invert;
05784                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2],lu[2],mv[2])*invert;
05785                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],lu[2],mv[2])*invert;
05786                                         if(peak_check) {
05787                                                 if(count < ml) {
05788                                                         count++;
05789                                                         //peaks.push_back( Pixel(i, j, k, l, m, qbf) );
05790                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05791                                                 } else {
05792                                                         if( qbf > (peaks.back()).value ) {
05793                                                                 //  do the switch and sort again
05794                                                                 //cout << qbf<<"   "<< (peaks.back()).value <<"   "<< (*peaks.begin()).value <<endl;
05795                                                                 peaks.pop_back();
05796                                                                 //peaks.push_back( Pixel(i, j, k, l, m, qbf) );
05797                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05798                                                         }
05799                                                 }
05800                                         }
05801                                         }}}}}}}}}}}}}}}}}}}}}}}}}}
05802                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05803                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05804                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05805                                         }}}}}}}}}}}}}}}}}}}}}}}}}}
05806                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05807                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05808                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05809                                         }}}}}}}}}}}}}}}}}}}}}}}}}}}
05810                                 }
05811                         }
05812                 }
05813                 }
05814                 }
05815                 //  Add circular closure for x, y, and z directions: needed for circular ccf,
05816                 //  should not have adverse impact on other code.  PAP 11/7/08
05817                 for(m=1; m<=nv-2; ++m) {
05818                         mv.clear();
05819                         mv.push_back(m-1);
05820                         mv.push_back(m);
05821                         mv.push_back(m+1);
05822                 for(l=1; l<=nu-2; ++l) {
05823                         lu.clear();
05824                         lu.push_back(l-1);
05825                         lu.push_back(l);
05826                         lu.push_back(l+1);
05827                 for(k=1; k<=nz-2; ++k) {
05828                         kz.clear();
05829                         kz.push_back(k-1);
05830                         kz.push_back(k);
05831                         kz.push_back(k+1);
05832                         for(j=1; j<=ny-2; ++j) {
05833                                 jy.clear();
05834                                 jy.push_back(j-1);
05835                                 jy.push_back(j);
05836                                 jy.push_back(j+1);
05837                                 for(i=0; i<=0; ++i) {
05838                                         ix.clear();
05839                                         ix.push_back(nx-1);
05840                                         ix.push_back(i);
05841                                         ix.push_back(i+1);
05842                                         float qbf = buf(i,j,k)*invert;
05843                                         peak_check = qbf > buf(ix[0],jy[0],kz[0])*invert;
05844                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0])*invert;
05845                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0])*invert;
05846                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0])*invert;
05847                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0])*invert;
05848                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0])*invert;
05849                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0])*invert;
05850                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0])*invert;
05851                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0])*invert;
05852                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1])*invert;
05853                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1])*invert;
05854                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1])*invert;
05855                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1])*invert;
05856                                         //if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1])*invert;
05857                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1])*invert;
05858                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1])*invert;
05859                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1])*invert;
05860                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1])*invert;
05861                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2])*invert;
05862                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2])*invert;
05863                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2])*invert;
05864                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2])*invert;
05865                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2])*invert;
05866                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2])*invert;
05867                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2])*invert;
05868                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2])*invert;
05869                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2])*invert;
05870                                         if(peak_check) {
05871                                                 if(count < ml) {
05872                                                         count++;
05873                                                         peaks.push_back( Pixel(i, j, k, qbf) );
05874                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05875                                                 } else {
05876                                                         if( qbf > (peaks.back()).value ) {
05877                                                                 //  do the switch and sort again
05878                                                                 //cout << qbf<<"   "<< (peaks.back()).value <<"   "<< (*peaks.begin()).value <<endl;
05879                                                                 peaks.pop_back();
05880                                                                 peaks.push_back( Pixel(i, j, k, qbf) );
05881                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05882                                                         }
05883                                                 }
05884                                         }
05885                                         }}}}}}}}}}}}}}}}}}}}}}}}}
05886                                 }
05887                                 for(i=nx-1; i<=nx-1; ++i) {
05888                                         ix.clear();
05889                                         ix.push_back(i-1);
05890                                         ix.push_back(i);
05891                                         ix.push_back(0);
05892                                         float qbf = buf(i,j,k)*invert;
05893                                         peak_check = qbf > buf(ix[0],jy[0],kz[0])*invert;
05894                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[0])*invert;
05895                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[0])*invert;
05896                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[0])*invert;
05897                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[0])*invert;
05898                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[0])*invert;
05899                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[0])*invert;
05900                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[0])*invert;
05901                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[0])*invert;
05902                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[1])*invert;
05903                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[1])*invert;
05904                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[1])*invert;
05905                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[1])*invert;
05906                                         //if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[1])*invert;
05907                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[1])*invert;
05908                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[1])*invert;
05909                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[1])*invert;
05910                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[1])*invert;
05911                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[0],kz[2])*invert;
05912                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[0],kz[2])*invert;
05913                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[0],kz[2])*invert;
05914                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[1],kz[2])*invert;
05915                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[1],kz[2])*invert;
05916                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[1],kz[2])*invert;
05917                                         if( peak_check ) {peak_check = qbf > buf(ix[0],jy[2],kz[2])*invert;
05918                                         if( peak_check ) {peak_check = qbf > buf(ix[1],jy[2],kz[2])*invert;
05919                                         if( peak_check ) {peak_check = qbf > buf(ix[2],jy[2],kz[2],3,3)*invert;
05920                                         if(peak_check) {
05921                                                 if(count < ml) {
05922                                                         count++;
05923                                                         peaks.push_back( Pixel(i, j, k, qbf) );
05924                                                         if(count == ml-1) sort(peaks.begin(), peaks.end(), peakcmp);
05925                                                 } else {
05926                                                         if( qbf > (peaks.back()).value ) {
05927                                                                 //  do the switch and sort again
05928                                                                 //cout << qbf<<"   "<< (peaks.back()).value <<"   "<< (*peaks.begin()).value <<endl;
05929                                                                 peaks.pop_back();
05930                                                                 peaks.push_back( Pixel(i, j, k, qbf) );
05931                                                                 if(ml > 1) sort(peaks.begin(), peaks.end(), peakcmp);
05932                                                         }
05933                                                 }
05934                                         }
05935                                         }}}}}}}}}}}}}}}}}}}}}}}}}
05936                                 }
05937                         }
05938                 }
05939                 }
05940                 }
05941         break;*/
05942         }
05943         // do we have a peak list yet?
05944         if (peaks.begin() != peaks.end()) {
05945           // yes. sort it
05946           sort(peaks.begin(), peaks.end(), peakcmp);
05947 
05948           int count = 0;
05949 
05950           float xval = (*peaks.begin()).value;
05951           // loop over all peaks
05952           for (vector<Pixel>::iterator it = peaks.begin(); it != peaks.end(); it++)  {
05953             // current peak count
05954             count++;
05955             // is current peak count below max?
05956             if(count <= ml) {
05957               // yes, so append it
05958               res.push_back((*it).value);
05959               res.push_back(static_cast<float>((*it).x));
05960 
05961               if(img_dim > 1) {
05962                 res.push_back(static_cast<float>((*it).y));
05963                 if(nz > 1) res.push_back(static_cast<float>((*it).z));
05964               }
05965 
05966               if(xval != 0.0) res.push_back((*it).value/xval);
05967               else            res.push_back((*it).value);
05968               res.push_back((*it).x-float(int(nx/2)));
05969               if(img_dim >1) {
05970                 res.push_back((*it).y-float(int(ny/2)));
05971                 if(nz>1)   res.push_back((*it).z-float(nz/2));
05972               }
05973             }
05974           }
05975           res.insert(res.begin(),1,img_dim);
05976         } else {
05977           // no peak list. build empty list
05978           res.push_back(buf(0,0,0));
05979           res.insert(res.begin(),1,0.0);
05980         }
05981 
05982         // return results list
05983         return res;
05984 }
05985 
05986 #define rdata(i,j,k) rdata[(i-1)+((j-1)+(k-1)*ny)*(size_t)nx]
05987 #define X(i) X[i-1]
05988 #define Y(j) Y[j-1]
05989 #define Z(k) Z[k-1]
05990 vector<float> EMData::phase_cog()
05991 {
05992         vector<float> ph_cntog;
05993         int i=1,j=1,k=1;
05994         float C=0.f,S=0.f,P=0.f,F1=0.f,SNX;
05995         if (get_ndim()==1) {
05996                 P = 8*atan(1.0f)/nx;
05997                 for (i=1;i<=nx;i++) {
05998                         C += cos(P * (i-1)) * rdata(i,j,k);
05999                         S += sin(P * (i-1)) * rdata(i,j,k);
06000                 }
06001                 F1 = atan2(S,C);
06002                 if (F1 < 0.0)  F1 += 8*atan(1.0f);
06003                 SNX = F1/P +1.0f;
06004                 SNX = SNX - ((nx/2)+1);
06005                 ph_cntog.push_back(SNX);
06006 #ifdef _WIN32
06007                 ph_cntog.push_back((float)Util::round(SNX));
06008 #else
06009                 ph_cntog.push_back(round(SNX));
06010 #endif //_WIN32
06011         } else if (get_ndim()==2)  {
06012 #ifdef _WIN32
06013                 float SNY;
06014                 float T=0.0f;
06015                 vector<float> X;
06016                 X.resize(nx);
06017 #else
06018                 float SNY,X[nx],T=0.f;
06019 #endif  //_WIN32
06020                 for ( i=1;i<=nx;i++) X(i)=0.0;
06021                 P = 8*atan(1.0f)/ny;
06022                 for(j=1;j<=ny;j++) {
06023                         T=0.f;
06024                         for(i=1;i<=nx;i++) {
06025                                 T += rdata(i,j,k);
06026                                 X(i)+=rdata(i,j,k);
06027                         }
06028                         C += cos(P*(j-1))*T;
06029                         S += sin(P*(j-1))*T;
06030                 }
06031                 F1=atan2(S,C);
06032                 if(F1<0.0)  F1 += 8*atan(1.0f);
06033                 SNY = F1/P +1.0f;
06034                 C=0.f;  S=0.f;
06035                 P = 8*atan(1.0f)/nx;
06036                 for(i=1;i<=nx;i++) {
06037                         C += cos(P*(i-1))*X(i);
06038                         S += sin(P*(i-1))*X(i);
06039                 }
06040                 F1=atan2(S,C);
06041                 if(F1<0.0) F1 += 8*atan(1.0f);
06042                 SNX = F1/P +1.0f;
06043                 SNX = SNX - ((nx/2)+1);
06044                 SNY = SNY - ((ny/2)+1);
06045                 ph_cntog.push_back(SNX); ph_cntog.push_back(SNY);
06046 #ifdef _WIN32
06047                 ph_cntog.push_back((float)Util::round(SNX)); ph_cntog.push_back((float)Util::round(SNY));
06048 #else
06049                 ph_cntog.push_back(round(SNX)); ph_cntog.push_back(round(SNY));
06050 #endif  //_WIN32
06051         } else {
06052 #ifdef _WIN32
06053                 float val=0.f,sum1=0.f, SNY,SNZ;
06054                 vector<float> X;
06055                 X.resize(nx);
06056                 vector<float> Y;
06057                 Y.resize(ny);
06058                 vector<float> Z;
06059                 Z.resize(nz);
06060 #else
06061                 float val=0.f, sum1=0.f, X[nx], Y[ny], Z[nz], SNY, SNZ;
06062 #endif  //_WIN32
06063                  for (i=1;i<=nx;i++)  X(i)=0.0;
06064                  for (j=1;j<=ny;j++)  Y(j)=0.0;
06065                  for (k=1;k<=nz;k++)  Z(k)=0.0;
06066                  for(k=1;k<=nz;k++)  {
06067                         for(j=1;j<=ny;j++) {
06068                                 sum1=0.f;
06069                                 for(i=1;i<=nx;i++)  {
06070                                         val = rdata(i,j,k);
06071                                         sum1 += val;
06072                                         X(i) += val;
06073                                 }
06074                                 Y(j) += sum1;
06075                                 Z(k) += sum1;
06076                         }
06077                 }
06078                 P = 8*atan(1.0f)/nx;
06079                 for (i=1;i<=nx;i++) {
06080                         C += cos(P*(i-1))*X(i);
06081                         S += sin(P*(i-1))*X(i);
06082                 }
06083                 F1=atan2(S,C);
06084                 if(F1<0.0) F1 += 8*atan(1.0f);
06085                 SNX = F1/P +1.0f;
06086                 C=0.f;  S=0.f;
06087                 P = 8*atan(1.0f)/ny;
06088                 for(j=1;j<=ny;j++) {
06089                         C += cos(P*(j-1))*Y(j);
06090                         S += sin(P*(j-1))*Y(j);
06091                 }
06092                 F1=atan2(S,C);
06093                 if(F1<0.0)  F1 += 8*atan(1.0f);
06094                 SNY = F1/P +1.0f;
06095                 C=0.f;  S=0.f;
06096                 P = 8*atan(1.0f)/nz;
06097                 for(k=1;k<=nz;k++) {
06098                         C += cos(P*(k-1))*Z(k);
06099                         S += sin(P*(k-1))*Z(k);
06100                 }
06101                 F1=atan2(S,C);
06102                 if(F1<0.0)  F1 += 8*atan(1.0f);
06103                 SNZ = F1/P +1.0f;
06104                 SNX = SNX - ((nx/2)+1);
06105                 SNY = SNY - ((ny/2)+1);
06106                 SNZ = SNZ - ((nz/2)+1);
06107                 ph_cntog.push_back(SNX); ph_cntog.push_back(SNY); ph_cntog.push_back(SNZ);
06108 #ifdef _WIN32
06109                 ph_cntog.push_back((float)Util::round(SNX)); ph_cntog.push_back((float)Util::round(SNY)); ph_cntog.push_back((float)Util::round(SNZ));
06110 #else
06111                 ph_cntog.push_back(round(SNX)); ph_cntog.push_back(round(SNY));ph_cntog.push_back(round(SNZ));
06112 #endif
06113         }
06114         return ph_cntog;
06115 }
06116 #undef rdata
06117 #undef X
06118 #undef Y
06119 #undef Z
06120 
06121 #define avagadro (6.023*(double)pow(10.0,23.0))
06122 #define density_protein (1.36)
06123 #define R (0.61803399f)
06124 #define C (1.f-R)
06125 float EMData::find_3d_threshold(float mass, float pixel_size)
06126 {
06127         /* Exception Handle */
06128         if(get_ndim()!=3)
06129                 throw ImageDimensionException("The image should be 3D");
06130         /* ===============================================================*/
06131 
06132         /* Calculation of the volume of the voxels */
06133         float density_1_mole, vol_1_mole, vol_angstrom;
06134         int  vol_voxels;
06135         density_1_mole = static_cast<float>( (mass*1000.0f)/avagadro );
06136         vol_1_mole =  static_cast<float>( density_1_mole/density_protein );
06137         vol_angstrom =  static_cast<float>( vol_1_mole*(double)pow((double)pow(10.0,8),3) );
06138         vol_voxels = static_cast<int> (vol_angstrom/(double)pow(pixel_size,3));
06139         /* ===============================================================*/
06140 
06141 
06142         float thr1 = get_attr("maximum");
06143         float thr3 = get_attr("minimum");
06144         float thr2 = (thr1-thr3)/2 + thr3;
06145         size_t size = (size_t)nx*ny*nz;
06146         float x0 = thr1,x3 = thr3,x1,x2,THR=0;
06147 
06148         #ifdef _WIN32
06149                 int ILE = _cpp_min(nx*ny*nx,_cpp_max(1,vol_voxels));
06150         #else
06151                 int ILE = std::min(nx*ny*nx,std::max(1,vol_voxels));
06152         #endif  //_WIN32
06153 
06154         if (abs(thr3-thr2)>abs(thr2-thr1)) {
06155                 x1=thr2;
06156                 x2=thr2+C*(thr3-thr2);
06157         } else {
06158                 x2=thr2;
06159                 x1=thr2-C*(thr2-thr1);
06160         }
06161 
06162         int cnt1=0,cnt2=0;
06163         for (size_t i=0;i<size;++i) {
06164                 if(rdata[i]>=x1)  cnt1++;
06165                 if(rdata[i]>=x2)  cnt2++;
06166         }
06167         float LF1 = static_cast<float>( cnt1 - ILE );
06168         float F1 = LF1*LF1;
06169         float LF2 = static_cast<float>( cnt2 - ILE );
06170         float F2 = LF2*LF2;
06171 
06172         while ((LF1 != 0 || LF2 != 0) && (fabs(LF1-LF2) >= 1.f) && (abs(x1-x2) > (double)pow(10.0,-5) && abs(x1-x3) > (double)pow(10.0,-5) && abs(x2-x3) > (double)pow(10.0,-5)))
06173         {
06174                 if(F2 < F1) {
06175                         x0=x1;
06176                         x1=x2;
06177                         x2 = R*x1 + C*x3;
06178                         F1=F2;
06179                         int cnt=0;
06180                         for(size_t i=0;i<size;++i)
06181                                 if(rdata[i]>=x2)
06182                                         cnt++;
06183                         LF2 = static_cast<float>( cnt - ILE );
06184                         F2 = LF2*LF2;
06185                 } else {
06186                         x3=x2;
06187                         x2=x1;
06188                         x1=R*x2 + C*x0;
06189                         F2=F1;
06190                         int cnt=0;
06191                         for(size_t i=0;i<size;++i)
06192                                 if(rdata[i]>=x1)
06193                                         cnt++;
06194                         LF1 = static_cast<float>( cnt - ILE );
06195                         F1 = LF1*LF1;
06196                 }
06197         }
06198 
06199         if(F1 < F2) {
06200                 ILE = static_cast<int> (LF1 + ILE);
06201                 THR = x1;
06202         } else {
06203                 ILE = static_cast<int> (LF2 + ILE);
06204                 THR = x2;
06205         }
06206         return THR;
06207 
06208 }
06209 #undef avagadro
06210 #undef density_protein
06211 #undef R
06212 #undef C
06213 
06214 
06215 // reworked peak_ccf uses max queue length for peak objects, i.e. lowest
06216 //    peaks are deleted if queue length is exceeded and a new peak is inserted
06217 //    instead.
06218 
06219 
06220 vector<float> EMData::peak_ccf(float hf_p)
06221 {
06222 
06223   // cout << "peak ccf starting up" << endl;
06224 
06225   EMData & buf = *this;
06226   vector<Pixel> peaks;
06227   int half=int(hf_p);
06228   float hf_p2 = hf_p*hf_p;
06229   int i,j;
06230   int i__1,i__2;
06231   int j__1,j__2;
06232   vector<float>res;
06233   int nx = buf.get_xsize()-half;
06234   int ny = buf.get_ysize()-half;
06235   // iterate over image
06236   for(i=half; i<=nx; ++i) {
06237     // static assignment so we don't have to re-evaluate
06238     i__1 = i-1;
06239     i__2 = i+1;
06240     for (j=half;j<=ny;++j) {
06241       j__1 = j-1;
06242       j__2 = j+1;
06243 
06244       if((buf(i,j)>0.0f)&&buf(i,j)>buf(i,j__1)) {
06245         if(buf(i,j)>buf(i,j__2)) {
06246           if(buf(i,j)>buf(i__1,j)) {
06247             if(buf(i,j)>buf(i__2,j)) {
06248               if(buf(i,j)>buf(i__1,j__1)) {
06249                 if((buf(i,j))> buf(i__1,j__2)) {
06250                   if(buf(i,j)>buf(i__2,j__1)) {
06251                     if(buf(i,j)> buf(i__2,j__2)) {
06252 
06253                       // found a peak
06254                       // empty list?
06255                       if (peaks.size()==0) {
06256                         // yes, so just push the peak onto the list
06257                         peaks.push_back(Pixel(i,j,0,buf(i,j)));
06258 
06259                       } else {
06260                         // not empty list. check neighbourhood for peaks
06261                         // logical not in the name is awkward. renamed to overlap
06262                         bool overlap = false;
06263                         //int  size = peaks.size();
06264 
06265                         // list of peaks to be deleted, if the current peak is the largest (see below).
06266                         //    list contains iterators to the original list, which will have to be processed
06267                         //    back to front (i.e. LIFO: stl::stack)
06268                         std::stack <vector<Pixel>::iterator> delete_stack;
06269 
06270                         // loop over all peaks found so far. this would be nicer with iterators
06271                         for (vector<Pixel>::iterator it=peaks.begin();it!=peaks.end();++it) {
06272                         // for ( int kk= 0; kk< size; kk++) {
06273                         //  vector<Pixel>::iterator it = peaks.begin()+kk;
06274 
06275                           // calc L2 distance
06276                           float radius=((*it).x-float(i))*((*it).x-float(i))+((*it).y-float(j))*((*it).y-float(j));
06277                           if (radius <= hf_p2 ) {
06278                             // peaks overlap
06279                             if( buf(i,j) > (*it).value) {
06280                               // this peak (indexed by (i,j)) is larger, mark the old for deletion
06281                               //    however, we have to be careful. if there is a larger peak within the vicinity of
06282                               //    the new one, this new peak is not marked as such, and the deletion of prior low
06283                               //    peaks should not continued. to make sure this deletion does not happen, we have
06284                               //    to make sure we cycle through all peaks within the vicinity, and only delete smaller
06285                               //    peaks if this new one is the largest in the vicinity.
06286                               delete_stack.push(it);
06287 
06288                               //(*it).x = -half; // this marks entry to be deleted, since it's smaller than the new one
06289 
06290 
06291                             } else {
06292                               overlap = true;
06293                               // old peak is larger, ignore this one. since it's enough to know there is some peak larger
06294                               //    than this one, we can break out of the peak list loop, instead of continuing.
06295                               break;
06296                             }
06297                           }
06298                         }
06299 
06300                         // check whether we need to delete anything. this is marked by the flag overlap == false
06301                         // loop over all peaks and clean out redundant ones
06302                         if (false == overlap) {
06303                           vector<Pixel>::iterator delete_iterator;
06304                           while (!delete_stack.empty()) {
06305                             // pop empties the stack from the back. since we are dealing with iterators, we need to delete
06306                             //    from the back, so as to keep the rest stack intact upon deletion.
06307                             delete_iterator = delete_stack.top();
06308                             peaks.erase(delete_iterator);
06309                             delete_stack.pop();
06310                           }
06311                           // before pushing the peak, we need to check whether max queue length is exceeded and delete
06312                           //     peaks if necessary.
06313                           // XXX: remove hardcoded value!
06314                           if (! (peaks.size() < 2000 )) {
06315 
06316                             //cout << ".";
06317                             // we need to delete a peak first.
06318                             // - resort list to get lowest peak at the back
06319                             sort(peaks.begin(), peaks.end(), peakcmp);
06320 
06321                             // - remove lowest peak
06322                             peaks.pop_back();
06323                           }
06324 
06325                           // push the new peak onto the list of peaks
06326                           peaks.push_back(Pixel(i,j,0,buf(i,j)));
06327                           //cout << "done." << endl;
06328 
06329                         } else {
06330                           // this peak too small and is ignored, so delete_list is ignored as well. make sure delete_list
06331                           //    is empty. probably redundant because of scope, but better safe than sorry.....
06332                           while (!delete_stack.empty()) delete_stack.pop();
06333                         }
06334                       }
06335                     }
06336                   }}}}}}}
06337     }
06338   }
06339 
06340   // we have peaks, so build a results vector.
06341   if(peaks.size()>0) {
06342     // sort peaks by size
06343     sort(peaks.begin(),peaks.end(), peakcmp);
06344     // and push all peaks to the results vector
06345     for (vector<Pixel>::iterator it = peaks.begin(); it != peaks.end(); it++) {
06346       // XXX: this format is necessary for Boost to work???
06347       res.push_back((*it).value);
06348       res.push_back(static_cast<float>((*it).x));
06349       res.push_back(static_cast<float>((*it).y));
06350     }
06351   } else {
06352     // only one or zero (?) entries
06353     res.push_back(buf(0,0,0));
06354     res.insert(res.begin(),1,0.0);
06355   }
06356   return res;
06357 }
06358 
06359 EMData* EMData::get_pow(float n_pow)
06360 {
06361         EMData* buf_new = this->copy_head();
06362         float *in  = this->get_data();
06363         float *out = buf_new->get_data();
06364         for(size_t i=0; i<(size_t)nx*ny*nz; ++i) out[i] = pow(in[i],n_pow);
06365         return buf_new;
06366 }
06367 
06368 EMData* EMData::conjg()
06369 {
06370         if(this->is_complex()) {
06371                 EMData* buf_new = this->copy_head();
06372                 float *in  = this->get_data();
06373                 float *out = buf_new->get_data();
06374                 for(size_t i=0; i<(size_t)nx*ny*nz; i+=2) {out[i] = in[i]; out[i+1] = -in[i+1];}
06375                 return buf_new;
06376         } else throw ImageFormatException("image has to be complex");
06377 }
06378 
06379 EMData* EMData::delete_disconnected_regions(int ix, int iy, int iz) {
06380         if (3 != get_ndim())
06381                 throw ImageDimensionException("delete_disconnected_regions needs a 3-D image.");
06382         if (is_complex())
06383                 throw ImageFormatException("delete_disconnected_regions requires a real image");
06384         if ((*this)(ix+nx/2,iy+ny/2,iz+nz/2) == 0)
06385                 throw ImageDimensionException("delete_disconnected_regions starting point is zero.");
06386 
06387         EMData* result = this->copy_head();
06388         result->to_zero();
06389         (*result)(ix+nx/2,iy+ny/2,iz+nz/2) = (*this)(ix+nx/2,iy+ny/2,iz+nz/2);
06390         bool kpt = true;
06391         //cout << "  delete   "<<(*result)(ix+nx/2,iy+ny/2,iz+nz/2)<<endl;
06392         while(kpt) {
06393                 kpt = false;
06394                 for (int cz = 1; cz < nz-1; cz++) {
06395                         for (int cy = 1; cy < ny-1; cy++) {
06396                                 for (int cx = 1; cx < nx-1; cx++) {
06397                                         if((*result)(cx,cy,cz) == 1) {
06398                                                 for (int lz = -1; lz <= 1; lz++) {
06399                                                         for (int ly = -1; ly <= 1; ly++) {
06400                                                                 for (int lx = -1; lx <= 1; lx++) {
06401                                                                         if(((*this)(cx+lx,cy+ly,cz+lz) == 1) && ((*result)(cx+lx,cy+ly,cz+lz) == 0))  {
06402                                                                                 (*result)(cx+lx,cy+ly,cz+lz) = 1;
06403                                                                                 kpt = true;
06404                                                                         }
06405                                                                 }
06406                                                         }
06407                                                 }
06408                                         }
06409                                 }
06410                         }
06411                 }
06412         }
06413         result->update();
06414         return result;
06415 }
06416 
06417 #define    QUADPI                   3.141592653589793238462643383279502884197
06418 #define    DGR_TO_RAD                   QUADPI/180
06419 
06420 EMData* EMData::helicise(float pixel_size, float dp, float dphi, float section_use, float radius, float minrad) {
06421         if(3 != get_ndim())               throw ImageDimensionException("helicise needs a 3-D image.");
06422         if(is_complex())                  throw ImageFormatException("helicise requires a real image");
06423         if(int(section_use*nz+0.5)>=nz-2) throw ImageFormatException("Reduce section used for helicise");
06424 
06425         EMData* result = this->copy_head();
06426         result->to_zero();
06427 
06428 
06429         int nxc = nx/2;
06430         int nyc = ny/2;
06431         int nzc = nz/2;
06432         //  calculations are done in Angstroms
06433         float volen = nz*pixel_size;
06434         float nzcp  = nzc*pixel_size;
06435         float sectl = nz*pixel_size*section_use;  //In Angstroms
06436         float nb = nzcp - sectl/2.0f;
06437         float ne = nzcp + sectl/2.0f;
06438         int numst = int( nz*pixel_size/dp );  // A
06439         int numri = int(sectl/dp);             // pix
06440         if(numri < 1)   throw ImageFormatException("Increase section used for helicise");
06441 
06442         float r2, ir;
06443         if(radius < 0.0f) r2 = (float)((nxc-1)*(nxc-1));
06444         else r2 = radius*radius;
06445         if(minrad < 0.0f) ir = 0.0f;
06446         else ir = minrad*minrad;
06447 
06448         for (int k = 0; k<nz; k++) {
06449                 int nq = 0;
06450                 for (int ist = 0; ist<numst; ist++) {
06451                         float z = k*pixel_size + ist*dp;
06452                         float phi = ist*dphi;
06453                         if( z >= volen ) {
06454                                 z = k*pixel_size + (ist-numst)*dp;
06455                                 phi = (ist-numst)*dphi;
06456                         }
06457                         float ca = cos(phi*(float)DGR_TO_RAD);
06458                         float sa = sin(phi*(float)DGR_TO_RAD);
06459                         if((z >= nb) && (z <= ne )) {
06460                                 nq++;
06461                                 if( nq > numri ) break;
06462                                 float zz = z/pixel_size;
06463                                 //cout <<" zz  "<<zz<<"  k  "<<k<<"  phi  "<<phi<<endl;
06464                                 for (int j=0; j<ny; j++) {
06465                                         int jy = j - nyc;
06466                                         int jj = jy*jy;
06467                                         for (int i=0; i<nx; i++) {
06468                                                 int ix = i - nxc;
06469                                                 float d2 = float((ix*ix + jj));
06470                                                 if(d2 <= r2 && d2>=ir) {
06471                                                         float xx =  ix*ca + jy*sa + nxc;
06472                                                         float yy = -ix*sa + jy*ca + nyc;
06473 
06474 
06475         //  Do tri-linear interpolation
06476         int IOX = int(xx);
06477         int IOY = int(yy);
06478         int IOZ = int(zz);
06479 
06480         #ifdef _WIN32
06481         int IOXp1 = _cpp_min( nx-1 ,IOX+1);
06482         #else
06483         int IOXp1 = std::min( nx-1 ,IOX+1);
06484         #endif  //_WIN32
06485 
06486         #ifdef _WIN32
06487         int IOYp1 = _cpp_min( ny-1 ,IOY+1);
06488         #else
06489         int IOYp1 = std::min( ny-1 ,IOY+1);
06490         #endif  //_WIN32
06491 
06492         #ifdef _WIN32
06493         int IOZp1 = _cpp_min( nz-1 ,IOZ+1);
06494         #else
06495         int IOZp1 = std::min( nz-1 ,IOZ+1);
06496         #endif  //_WIN32
06497 
06498         float dx = xx-IOX;
06499         float dy = yy-IOY;
06500         float dz = zz-IOZ;
06501 
06502         float a1 = (*this)(IOX,IOY,IOZ);
06503         float a2 = (*this)(IOXp1,IOY,IOZ) - (*this)(IOX,IOY,IOZ);
06504         float a3 = (*this)(IOX,IOYp1,IOZ) - (*this)(IOX,IOY,IOZ);
06505         float a4 = (*this)(IOX,IOY,IOZp1) - (*this)(IOX,IOY,IOZ);
06506         float a5 = (*this)(IOX,IOY,IOZ) - (*this)(IOXp1,IOY,IOZ) - (*this)(IOX,IOYp1,IOZ) + (*this)(IOXp1,IOYp1,IOZ);
06507         float a6 = (*this)(IOX,IOY,IOZ) - (*this)(IOXp1,IOY,IOZ) - (*this)(IOX,IOY,IOZp1) + (*this)(IOXp1,IOY,IOZp1);
06508         float a7 = (*this)(IOX,IOY,IOZ) - (*this)(IOX,IOYp1,IOZ) - (*this)(IOX,IOY,IOZp1) + (*this)(IOX,IOYp1,IOZp1);
06509         float a8 = (*this)(IOXp1,IOY,IOZ) + (*this)(IOX,IOYp1,IOZ)+ (*this)(IOX,IOY,IOZp1)
06510                         - (*this)(IOX,IOY,IOZ)- (*this)(IOXp1,IOYp1,IOZ) - (*this)(IOXp1,IOY,IOZp1)
06511                         - (*this)(IOX,IOYp1,IOZp1) + (*this)(IOXp1,IOYp1,IOZp1);
06512 
06513 
06514 
06515                                                         (*result)(i,j,k) += a1 + dz*(a4 + a6*dx + (a7 + a8*dx)*dy) + a3*dy + dx*(a2 + a5*dy);
06516                                                 }
06517                                         }
06518                                 }
06519                         }
06520                 }
06521                 if(nq < numri) throw InvalidValueException(nq, "Helicise: incorrect number of repeats encoutered.");
06522         }
06523         for (int k = 0; k<nz; k++) for (int j = 0; j<ny; j++) for (int i = 0; i<nx; i++) (*result)(i,j,k) /= numst ;
06524 
06525         result->update();
06526         return result;
06527 }
06528 
06529 
06530 
06531 EMData* EMData::helicise_grid(float pixel_size, float dp, float dphi, Util::KaiserBessel& kb, float section_use, float radius, float minrad) {
06532         std::cout<<"111111"<<std::endl;
06533         if (3 != get_ndim())
06534                 throw ImageDimensionException("helicise needs a 3-D image.");
06535         if (is_complex())
06536                 throw ImageFormatException("helicise requires a real image");
06537         //begin griding
06538         //if (scale_input == 0.0f) scale_input = 1.0f;
06539         float  scale = 0.5f;//*scale_input;
06540 
06541         
06542         int nxn = nx/2; int nyn = ny/2; int nzn = nz/2;
06543 
06544         vector<int> saved_offsets = get_array_offsets();
06545         set_array_offsets(0,0,0);
06546         EMData* ret = this->copy_head();
06547 #ifdef _WIN32
06548         ret->set_size(nxn, _cpp_max(nyn,1), _cpp_max(nzn,1));
06549 #else
06550         ret->set_size(nxn, std::max(nyn,1), std::max(nzn,1));
06551 #endif  //_WIN32
06552         ret->to_zero();  //we will leave margins zeroed.
06553 
06554         // center of big image,
06555         int xc = nxn;
06556         int ixs = nxn%2;  // extra shift on account of odd-sized images
06557         int yc = nyn;
06558         int iys = nyn%2;
06559         int zc = nzn;
06560         int izs = nzn%2;
06561         // center of small image
06562         int xcn = nxn/2;
06563         int ycn = nyn/2;
06564         int zcn = nzn/2;
06565         // shifted center for rotation
06566         float shiftxc = xcn; // + delx;
06567         float shiftyc = ycn; // + dely;
06568         float shiftzc = zcn; // + delz;
06569         // bounds if origin at center
06570         float zmin = -nz/2.0f;
06571         float ymin = -ny/2.0f;
06572         float xmin = -nx/2.0f;
06573         float zmax = -zmin;
06574         float ymax = -ymin;
06575         float xmax = -xmin;
06576         if (0 == nx%2) xmax--;
06577         if (0 == ny%2) ymax--;
06578         if (0 == nz%2) zmax--;
06579 
06580         float* data = this->get_data();
06581 
06582         
06583         // rotation matrix (the transpose is used in the loop to get (xold,yold,zold)):
06584          
06585         //float a13 = -0.0f;    float a23 =  0.0f;
06586         //float a31 =  0.0f;    float a32 =  0.0f;        float a33 =  1.0f;
06587                 
06588         //end gridding
06589 
06590         
06591         int nyc = nyn/2;
06592         int nxc = nxn/2;
06593         int nb = int(nzn*(1.0f - section_use)/2.);
06594         int ne = nzn - nb -1;
06595         int numst = int(nzn*section_use*pixel_size/dp);
06596         // how many steps needed total, fewer will be used, only those that fall between nb and ne
06597         int nst = int(nzn*pixel_size/dp);
06598         float r2, ir;
06599         if(radius < 0.0f) r2 = (float)((nxc-1)*(nxc-1));
06600         else r2 = radius*radius;
06601         if(minrad < 0.0f) ir = 0.0f;
06602         else ir = minrad*minrad;
06603         
06604         for (int k = 0; k<nzn; k++) {
06605                 for (int j = 0; j<nyn; j++) {
06606                         int jy = j - nyc;
06607                         int jj = jy*jy;
06608                         for (int i = 0; i<nxn; i++) {
06609                                 int ix = i - nxc;
06610                                 float d2 = (float)(ix*ix + jj);
06611                                 if(d2 <= r2 && d2>=ir) {
06612                                         int nq = 0;
06613                                         for ( int ist = -nst; ist <= nst; ist++) {
06614                                                 float zold = (k*pixel_size + ist*dp)/pixel_size;
06615                                                 int IOZ = int(zold);
06616                                                 if(IOZ >= nb && IOZ <= ne) {
06617                                                 
06618                                                         float cphi = ist*dphi*(float)DGR_TO_RAD;
06619                                                         float ca = cos(cphi);
06620                                                         float sa = sin(cphi);
06621                                                         
06622                                                         float xold = ix*ca - jy*sa + nxc;
06623                                                         float yold = ix*sa + jy*ca + nyc;
06624                                                         
06625                                                         float xold_big = (xold-shiftxc)/scale - ixs + xc;
06626                                                         float yold_big = (yold-shiftyc)/scale - iys + yc;
06627                                                         float zold_big = (zold-shiftzc)/scale - izs + zc;
06628                                                         
06629                                                         /*float a11 =  ca; float a12 =  sa;
06630                                                         float a21 = -sa; float a22 = ca;
06631                                                         
06632                                                         float z = (zold - shiftzc)/scale;
06633                                                         float zco1 = a31*z+xc;
06634                                                         float zco2 = a32*z+yc;
06635                                                         float zco3 = a33*z+zc;
06636                                                                                                                 
06637                                                         float y = (float(j) - shiftyc)/scale;
06638                                                         float yco1 = zco1+a21*y;
06639                                                         float yco2 = zco2+a22*y;
06640                                                         float yco3 = zco3+a23*y;
06641                                                         
06642                                                         float x = (float(i) - shiftxc)/scale;
06643                                                         float xold_big = yco1+a11*x-ixs; //have to add the fraction on account on odd-sized images for which Fourier zero-padding changes the center location
06644                                                         float yold_big = yco2+a12*x-iys;
06645                                                         float zold_big = yco3+a13*x-izs;*/
06646                                                         
06647                                                                                                 
06648                                                         nq++;
06649                                                         
06650                                                                 
06651                                                         (*ret)(i,j,k) += Util::get_pixel_conv_new(nx, ny, nz, xold_big, yold_big, zold_big, data, kb);
06652                                                         
06653                                                         
06654                                                         if(nq == numst) break;
06655                                                 }
06656                                         }
06657                                         if(nq != numst)
06658                                                 throw InvalidValueException(nq, "Helicise: incorrect number of repeats encoutered.");
06659                                 }
06660                         }
06661                 }
06662         }
06663         
06664         for (int k = 0; k<nzn; k++) for (int j = 0; j<nyn; j++) for (int i = 0; i<nxn; i++) (*ret)(i,j,k) /= numst ;
06665         set_array_offsets(saved_offsets);
06666         ret->update();
06667         return ret;
06668 }
06669 
06670 
06671 /*
06672 Purpose: Depad and remove FT extension from a real image.
06673 Method: Depad and remove FT extension from a real image.
06674 return new image.
06675 Input: f real n-dimensional image
06676 Output: depadded image
06677  */
06678 void EMData::depad() {
06679         if (is_complex())
06680                 throw ImageFormatException("Depadding of complex images not supported");
06681         vector<int> saved_offsets = get_array_offsets();
06682         set_array_offsets(0,0,0);
06683         int npad = attr_dict["npad"];
06684         if (0 == npad) npad = 1;
06685         int offset = is_fftodd() ? 1 : 2;
06686         int nxold = (nx - offset)/npad;
06687 #ifdef _WIN32
06688         int nyold = _cpp_max(ny/npad, 1);
06689         int nzold = _cpp_max(nz/npad, 1);
06690 #else
06691         int nyold = std::max<int>(ny/npad, 1);
06692         int nzold = std::max<int>(nz/npad, 1);
06693 #endif  //_WIN32
06694         int xstart = 0, ystart = 0, zstart = 0;
06695         if( npad > 1) {
06696                 xstart = (nx - offset - nxold)/2 + nxold%2;
06697                 if(ny > 1) {
06698                         ystart = (ny - nyold)/2 + nyold%2;
06699                         if(nz > 1) {
06700                                 zstart = (nz - nzold)/2 + nzold%2;
06701                         }
06702                 }
06703         }
06704         int bytes = nxold*sizeof(float);
06705         float* dest = get_data();
06706         for (int iz=0; iz < nzold; iz++) {
06707                 for (int iy = 0; iy < nyold; iy++) {
06708                         memmove(dest, &(*this)(xstart,iy+ystart,iz+zstart), bytes);
06709                         dest += nxold;
06710                 }
06711         }
06712         set_size(nxold, nyold, nzold);
06713         set_attr("npad", 1);
06714         set_fftpad(false);
06715         set_fftodd(false);
06716         set_complex(false);
06717         if(ny==1 && nz==1) set_complex_x(false);
06718         set_array_offsets(saved_offsets);
06719         update();
06720         EXITFUNC;
06721 }
06722 
06723 /*
06724 Purpose: Depad and remove FT extension from a real image.
06725 Method: Depad and remove FT extension from a real image.
06726 return new image.
06727 Input: f real n-dimensional image
06728 Output: depadded image
06729  */
06730 void EMData::depad_corner() {
06731         if(is_complex())
06732                 throw ImageFormatException("Depadding of complex images not allowed");
06733         vector<int> saved_offsets = get_array_offsets();
06734         set_array_offsets(0,0,0);
06735         int npad = attr_dict["npad"];
06736         if(0 == npad) npad = 1;
06737         int offset = is_fftodd() ? 1 : 2;
06738         int nxold = (nx - offset)/npad;
06739 #ifdef _WIN32
06740         int nyold = _cpp_max(ny/npad, 1);
06741         int nzold = _cpp_max(nz/npad, 1);
06742 #else
06743         int nyold = std::max<int>(ny/npad, 1);
06744         int nzold = std::max<int>(nz/npad, 1);
06745 #endif  //_WIN32
06746         size_t bytes = nxold*sizeof(float);
06747         float* dest = get_data();
06748         for (int iz=0; iz < nzold; iz++) {
06749                 for (int iy = 0; iy < nyold; iy++) {
06750                         memmove(dest, &(*this)(0,iy,iz), bytes);
06751                         dest += nxold;
06752                 }
06753         }
06754         set_size(nxold, nyold, nzold);
06755         set_attr("npad", 1);
06756         set_fftpad(false);
06757         set_fftodd(false);
06758         set_complex(false);
06759         if(ny==1 && nz==1) set_complex_x(false);
06760         set_array_offsets(saved_offsets);
06761         update();
06762         EXITFUNC;
06763 }
06764 
06765 
06766 // calculate circumference of the surrounding 1 pixel.
06767 float circumference( EMData* emdata, int npixel )
06768 {
06769         int nx = emdata->get_xsize();
06770         int ny = emdata->get_ysize();
06771         int nz = emdata->get_zsize();
06772 
06773         float* data = emdata->get_data();
06774         if( ny==1 && nz==1 ) {
06775                 // 1d case
06776                 float sumf=0.0;
06777                 int   sumn=0;
06778                 for( int i=0; i < npixel; ++i ) {
06779                         sumf += data[i];
06780                         sumf += data[nx-1-i];
06781                         sumn += 2;
06782                 }
06783                 return sumf/sumn;
06784         }
06785 
06786         if( nz==1 ) {
06787                 float sumf=0.0;
06788                 int   sumn=0;
06789                 int   id=0;
06790                 for( int iy=0; iy < ny; ++iy ) {
06791                         for( int ix=0; ix < nx; ++ix ) {
06792                                 if( iy<npixel || iy>ny-1-npixel || ix<npixel || ix>nx-1-npixel ) {
06793                                     sumf += data[id];
06794                                     sumn += 1;
06795                                 }
06796                                 id++;
06797                         }
06798                 }
06799 
06800                 Assert( id==nx*ny  );
06801                 Assert( sumn == nx*ny - (nx-2*npixel)*(ny-2*npixel) );
06802                 return sumf/sumn;
06803         }
06804 
06805         // 3d cases;
06806 
06807         float sumf = 0.0;
06808         size_t   sumn = 0;
06809         size_t   id = 0;
06810         for( int iz=0; iz < nz; ++iz) {
06811                 for( int iy=0; iy < ny; ++iy) {
06812                         for( int ix=0; ix < nx; ++ix ) {
06813                                 if( iz<npixel||iz>nz-1-npixel||iy<npixel||iy>ny-1-npixel||ix<npixel||ix>nx-1-npixel) {
06814                                         sumf += data[id];
06815                                         sumn += 1;
06816                                 }
06817                                 id++;
06818                         }
06819                 }
06820         }
06821 
06822 
06823         Assert( id==(size_t)nx*ny*nz);
06824         Assert( sumn==(size_t)nx*ny*nz-(size_t)(nx-2*npixel)*(ny-2*npixel)*(nz-2*npixel) );
06825         return sumf/sumn;
06826 }
06827 /*
06828 Purpose: Create a new [normalized] [zero-padded]  image.
06829 Method: Normalize, pad with zero or circumference, extend for fft,
06830 return new image.
06831 Input: f real n-dimensional image
06832 flag specify normalize, pad, and/or extend
06833 Output: zero-padded, ft-extended, normalized input image
06834  */
06835 EMData* EMData::norm_pad(bool donorm, int npad, int valtype) {
06836         if (this->is_complex())
06837                 throw ImageFormatException("Padding of complex images not supported");
06838         int nx = this->get_xsize();
06839         int ny = this->get_ysize();
06840         int nz = this->get_zsize();
06841         float mean = 0., stddev = 1.;
06842         if(donorm) { // Normalization requested
06843                 mean = this->get_attr("mean");
06844                 stddev = this->get_attr("sigma");
06845         }
06846         // sanity check
06847         if (npad < 1) npad = 1;
06848         int nxpad = npad*nx;
06849         int nypad = npad*ny;
06850         int nzpad = npad*nz;
06851         if (1 == ny) {
06852                 // 1-d image, don't want to pad along y or z
06853                 // Also, assuming that we can't have an image sized as nx=5, ny=1, nz=5.
06854                 nypad = ny;
06855                 nzpad = nz;
06856         } else if (nz == 1) {
06857                 // 2-d image, don't want to pad along z
06858                 nzpad = nz;
06859         }
06860         size_t bytes;
06861         size_t offset;
06862         // Not currently fft-extended, so we want to extend for ffts
06863         offset = 2 - nxpad%2;
06864         bytes = nx*sizeof(float);
06865         EMData* fpimage = copy_head();
06866         fpimage->set_size(nxpad+offset, nypad, nzpad);
06867         int xstart = 0, ystart = 0, zstart = 0;
06868         if( npad > 1) {
06869                 if( valtype==0 ) {
06870                         fpimage->to_zero();
06871                 } else {
06872                         float val = circumference(this, 1);
06873                         float* data = fpimage->get_data();
06874                         int nxyz = (nxpad+offset)*nypad*nzpad;
06875                         for( int i=0; i < nxyz; ++i )  data[i] = val;
06876                 }
06877 
06878                 xstart = (nxpad - nx)/2 + nx%2;
06879                 if(ny > 1) {
06880                         ystart = (nypad - ny)/2 + ny%2;
06881                         if(nz > 1) {
06882                                 zstart = (nzpad - nz)/2 + nz%2;
06883                         }
06884                 }
06885         }
06886 
06887 
06888         vector<int> saved_offsets = this->get_array_offsets();
06889         this->set_array_offsets( 0, 0, 0 );
06890         for (int iz = 0; iz < nz; iz++) {
06891                 for (int iy = 0; iy < ny; iy++) {
06892                         memcpy(&(*fpimage)(xstart,iy+ystart,iz+zstart), &(*this)(0,iy,iz), bytes);
06893                 }
06894         }
06895         this->set_array_offsets( saved_offsets );
06896 
06897 
06898         //  Perform the actual normalization (only on the
06899         //  non-zero section of the image)
06900         if (donorm) { // Normalization requested
06901                 for (int iz = zstart; iz < nz+zstart; iz++)
06902                         for (int iy = ystart; iy < ny+ystart; iy++)
06903                                 for (int ix = xstart; ix < nx+xstart; ix++)
06904                                         (*fpimage)(ix,iy,iz) = ((*fpimage)(ix,iy,iz)-mean)/stddev;
06905         }
06906 
06907         fpimage->set_fftpad(true);
06908         fpimage->set_attr("npad", npad);
06909         if (offset == 1) fpimage->set_fftodd(true);
06910         else             fpimage->set_fftodd(false);
06911         return fpimage;
06912 }
06913 
06914 void EMData::center_origin()
06915 {
06916         ENTERFUNC;
06917         if (is_complex()) {
06918                 LOGERR("Real image expected. Input image is complex.");
06919                 throw ImageFormatException("Real image expected. Input image is complex.");
06920         }
06921         for (int iz = 0; iz < nz; iz++) {
06922                 for (int iy = 0; iy < ny; iy++) {
06923                         for (int ix = 0; ix < nx; ix++) {
06924                                 // next line multiplies by +/- 1
06925                                 (*this)(ix,iy,iz) *= -2*((ix+iy+iz)%2) + 1;
06926                         }
06927                 }
06928         }
06929         update();
06930         EXITFUNC;
06931 }
06932 
06933 void EMData::center_origin_yz()
06934 {
06935         ENTERFUNC;
06936         if (is_complex()) {
06937                 LOGERR("Real image expected. Input image is complex.");
06938                 throw ImageFormatException("Real image expected. Input image is complex.");
06939         }
06940         for (int iz = 0; iz < nz; iz++) {
06941                 for (int iy = (iz+1)%2; iy < ny; iy+=2) {
06942                         for (int ix = 0; ix < nx; ix++) {
06943                                 (*this)(ix,iy,iz) *= -1;
06944                         }
06945                 }
06946         }
06947         update();
06948         EXITFUNC;
06949 }
06950 
06951 void EMData::center_origin_fft()
06952 {
06953         ENTERFUNC;
06954         if (!is_complex()) {
06955                 LOGERR("complex image expected. Input image is real image.");
06956                 throw ImageFormatException("complex image expected. Input image is real image.");
06957         }
06958 
06959         if (!is_ri()) {
06960                 LOGWARN("Only RI should be used. ");
06961         }
06962         vector<int> saved_offsets = get_array_offsets();
06963         // iz in [1,nz], iy in [1,ny], ix in [0,nx/2], but nx comes in as extended and is the same for odd
06964         //                                                 and even, so we can ignore the difference...
06965         //                         in short, as nx is extended, it should be  ix in [0,(nx-2)/2],  corrected PAP 05/20
06966         set_array_offsets(0,1,1);
06967         int nxc = nx/2;
06968 
06969         if (is_fftodd()) {
06970                 for (int iz = 1; iz <= nz; iz++) {
06971                         for (int iy = 1; iy <= ny; iy++) {
06972                                 for (int ix = 0; ix < nxc; ix++) {
06973                                         cmplx(ix,iy,iz) *= float(-2*((ix+iy+iz)%2) + 1);
06974                                         float temp = float(iz-1+iy-1+ix)/float(ny)*M_PI;
06975                                         complex<float> temp2 = complex<float>(cos(temp), -sin(temp));
06976                                         cmplx(ix,iy,iz) *= temp2;
06977                                 }
06978                         }
06979                 }
06980         } else {
06981                 for (int iz = 1; iz <= nz; iz++) {
06982                         for (int iy = 1; iy <= ny; iy++) {
06983                                 for (int ix = 0; ix < nxc; ix++) {
06984                                         // next line multiplies by +/- 1
06985                                         cmplx(ix,iy,iz) *= float(-2*((ix+iy+iz)%2) + 1);
06986                                 }
06987                         }
06988                 }
06989         }
06990         set_array_offsets(saved_offsets);
06991         update();
06992         EXITFUNC;
06993 }
06994 
06995 
06996 #define  fint(i,j,k)  fint[(i-1) + ((j-1) + (k-1)*ny)*(size_t)lsd]
06997 #define  fout(i,j,k)  fout[(i-1) + ((j-1) + (k-1)*nyn)*(size_t)lsdn]
06998 EMData *EMData::FourInterpol(int nxn, int nyni, int nzni, bool RetReal) {
06999 
07000         int nyn, nzn, lsd, lsdn, inx, iny, inz;
07001         int i, j, k;
07002         if (is_complex())
07003                 throw ImageFormatException("Input image has to be real");
07004 
07005         if(ny > 1) {
07006                 nyn = nyni;
07007                 if(nz > 1) {
07008                         nzn = nzni;
07009                 }  else {
07010                         nzn = 1;
07011                 }
07012         } else {
07013                 nyn = 1; nzn = 1;
07014         }
07015         if(nxn<nx || nyn<ny || nzn<nz)  throw ImageDimensionException("Cannot reduce the image size");
07016         lsd = nx + 2 - nx%2;
07017         lsdn = nxn + 2 - nxn%2;
07018 //  do out of place ft
07019         EMData *temp_ft = do_fft();
07020         EMData *ret = this->copy();
07021         ret->set_size(lsdn, nyn, nzn);
07022         ret->to_zero();
07023         float *fout = ret->get_data();
07024         float *fint = temp_ft->get_data();
07025 //  TO KEEP EXACT VALUES ON THE ORIGINAL GRID ONE SHOULD USE
07026 //  SQ2     = 2.0. HOWEVER, TOTAL ENERGY WILL NOT BE CONSERVED
07027         float  sq2 = 1.0f/std::sqrt(2.0f);
07028         float  anorm = (float) nxn* (float) nyn* (float) nzn/(float) nx/ (float) ny/ (float) nz;
07029         for (i = 0; i < lsd*ny*nz; i++)  fint[i] *= anorm;
07030         inx = nxn-nx; iny = nyn - ny; inz = nzn - nz;
07031         for (k=1; k<=nz/2+1; k++) for (j=1; j<=ny/2+1; j++) for (i=1; i<=lsd; i++) fout(i,j,k)=fint(i,j,k);
07032         if(nyn>1) {
07033         //cout << "  " <<nxn<<"  " <<nyn<<" A " <<nzn<<endl;
07034                 for (k=1; k<=nz/2+1; k++) for (j=ny/2+2+iny; j<=nyn; j++) for (i=1; i<=lsd; i++) fout(i,j,k)=fint(i,j-iny,k);
07035                 if(nzn>1) {
07036                         for (k=nz/2+2+inz; k<=nzn; k++) {
07037                                 for (j=1; j<=ny/2+1; j++) {
07038                                         for (i=1; i<=lsd; i++) {
07039                                                 fout(i,j,k)=fint(i,j,k-inz);
07040                                         }
07041                                 }
07042                                 for (j=ny/2+2+iny; j<=nyn; j++) {
07043                                         for (i=1; i<=lsd; i++) {
07044                                                 fout(i,j,k)=fint(i,j-iny,k-inz);
07045                                         }
07046                                 }
07047                         }
07048                 }
07049         }
07050 //       WEIGHTING FACTOR USED FOR EVEN NSAM. REQUIRED SINCE ADDING ZERO FOR
07051 //       INTERPOLATION WILL INTRODUCE A COMPLEX CONJUGATE FOR NSAM/2'TH
07052 //       ELEMENT.
07053         if(nx%2 == 0 && inx !=0) {
07054                 for (k=1; k<=nzn; k++) {
07055                         for (j=1; j<=nyn; j++) {
07056                                 fout(nx+1,j,k) *= sq2;
07057                                 fout(nx+2,j,k) *= sq2;
07058                         }
07059                 }
07060                 if(nyn>1) {
07061                         for (k=1; k<=nzn; k++) {
07062                           for (i=1; i<=lsd; i++) {
07063                             fout(i,ny/2+1+iny,k) = sq2*fout(i,ny/2+1,k);
07064                             fout(i,ny/2+1,k) *= sq2;
07065                           }
07066                         }
07067                         if(nzn>1) {
07068                                 for (j=1; j<=nyn; j++) {
07069                                         for (i=1; i<=lsd; i++) {
07070                                                 fout(i,j,nz/2+1+inz) = sq2*fout(i,j,nz/2+1);
07071                                                 fout(i,j,nz/2+1) *= sq2;
07072                                         }
07073                                 }
07074                         }
07075                 }
07076         }
07077         ret->set_complex(true);
07078 /*
07079 //  For padding from odd to even dimension additional shift by 1 pixel is necessary.
07080         float  xshift = 0.f, yshift = 0.f, zshift = 0.f;
07081         int nyn2, nzn2;
07082         if(nxn > nx && nx%2 == 1)  xshift = 1.0f;
07083         if(ny > 1) {
07084                 if(nyn > ny && ny%2 == 1)  yshift = 1.0f;
07085                 nyn2 = nyn/2;
07086                 if(nz > 1) {
07087                         if(nzn > nz && nz%2 == 1)  zshift = 1.0f;
07088                         nzn2 = nzn/2;
07089                 }  else {
07090                         nzn2 = 0;
07091                 }
07092         } else {
07093                 nyn2 = 0; nzn2 = 0;
07094         }
07095         if(xshift == 1.0 || yshift == 1.0 || zshift == 1.0)  {
07096                 ret->set_array_offsets(1,1,1);
07097                 int  lsdn2 = lsd/2;
07098                 for (int iz = 1; iz <= nzn; iz++) {
07099                         int jz=iz-1; if(jz>nzn2) jz=jz-nzn;
07100                         for (int iy = 1; iy <= nyn; iy++) {
07101                                 int jy=iy-1; if(jy>nyn2) jy=jy-nyn;
07102                                 for (int ix = 1; ix <= lsdn2; ix++) {
07103                                         int jx=ix-1;
07104                                         ret->cmplx(ix,iy,iz) *=
07105                                         exp(-float(twopi)*iimag*(xshift*jx/nxn + yshift*jy/nyn+ zshift*jz/nzn));
07106                                 }
07107                         }
07108                 }
07109                 ret->set_array_offsets(0,0,0);
07110         }*/
07111         ret->set_ri(1);
07112         ret->set_fftpad(true);
07113         ret->set_attr("npad", 1);
07114         if (nxn%2 == 1) {ret->set_fftodd(true);} else {ret->set_fftodd(false);}
07115         if(RetReal) {
07116                 ret->do_ift_inplace();
07117                 ret->depad();
07118         }
07119         ret->update();
07120 
07121         /*Dict d1 = temp_ft->get_attr_dict();
07122         Dict d2 = ret->get_attr_dict();
07123         printf("-----------------Attribute Dict for temp_ft--------------\n");
07124         EMUtil::dump_dict(d1);
07125         printf("-----------------Attribute Dict for ret--------------\n");
07126         EMUtil::dump_dict(d2);*/
07127         delete temp_ft;
07128         temp_ft = 0;
07129         return ret;
07130 }
07131 
07132 EMData *EMData::FourTruncate(int nxn, int nyni, int nzni, bool RetReal) {
07133 
07134         int nyn, nzn, lsd, lsdn, inx, iny, inz;
07135         int i, j, k;
07136         float  *fint;
07137         EMData *temp_ft = NULL;
07138         //if (is_complex())
07139         //      throw ImageFormatException("Input image has to be real");
07140 
07141         if(ny > 1) {
07142                 nyn = nyni;
07143                 if(nz > 1) {
07144                         nzn = nzni;
07145                 }  else {
07146                         nzn = 1;
07147                 }
07148         } else {
07149                 nyn = 1; nzn = 1;
07150         }
07151         if (is_complex()) {
07152                 nx = nx - 2 + nx%2;
07153                 fint = get_data();
07154         } else {
07155                 //  do out of place ft
07156                 temp_ft = do_fft();
07157                 fint = temp_ft->get_data();
07158         }
07159         if(nxn>nx || nyn>ny || nzn>nz)  throw ImageDimensionException("Cannot increase the image size");
07160         lsd = nx + 2 - nx%2;
07161         lsdn = nxn + 2 - nxn%2;
07162         EMData *ret = this->copy_head();
07163         ret->set_size(lsdn, nyn, nzn);
07164         float *fout = ret->get_data();
07165 //  TO KEEP EXACT VALUES ON THE ORIGINAL GRID ONE SHOULD USE
07166 //  SQ2     = 2.0. HOWEVER, TOTAL ENERGY WILL NOT BE CONSERVED
07167         //float  sq2 = std::sqrt(2.0f);
07168         float  anorm = (float) nxn* (float) nyn* (float) nzn/(float) nx/ (float) ny/ (float) nz;
07169         for (i = 0; i < lsd*ny*nz; i++)  fint[i] *= anorm;
07170         inx = nx - nxn;  iny = ny - nyn;  inz = nz - nzn;
07171         for (k=1; k<=nzn/2+1; k++) for (j=1; j<=nyn/2+1; j++) for (i=1; i<=lsdn; i++) fout(i,j,k)=fint(i,j,k);
07172         if(nyn>1) {
07173                 for (k=1; k<=nzn/2+1; k++) for (j=nyn/2+2; j<=nyn; j++) for (i=1; i<=lsdn; i++) fout(i,j,k)=fint(i,j+iny,k);
07174                 if(nzn>1) {
07175                         for (k=nzn/2+2; k<=nzn; k++) {
07176                                 for (j=1; j<=nyn/2+1; j++) {
07177                                         for (i=1; i<=lsdn; i++) {
07178                                                 fout(i,j,k)=fint(i,j,k+inz);
07179                                         }
07180                                 }
07181                                 for (j=nyn/2+2; j<=nyn; j++) {
07182                                         for (i=1; i<=lsdn; i++) {
07183                                                 fout(i,j,k)=fint(i,j+iny,k+inz);
07184                                         }
07185                                 }
07186                         }
07187                 }
07188         }
07189 //       WEIGHTING FACTOR USED FOR EVEN NSAM. REQUIRED SINCE ADDING ZERO FOR
07190 //       INTERPOLATION WILL INTRODUCE A COMPLEX CONJUGATE FOR NSAM/2'TH
07191 //       ELEMENT.
07192         /*
07193         if(nxn%2 == 0 && inx !=0) {
07194                 for (k=1; k<=nzn; k++) {
07195                         for (j=1; j<=nyn; j++) {
07196                                 fout(nxn+1,j,k) *= sq2;
07197                                 fout(nxn+2,j,k) *= sq2;
07198                         }
07199                 }
07200                 if(nyn>1) {
07201                         for (k=1; k<=nzn; k++) {
07202                           for (i=1; i<=lsdn; i++) {
07203                             fout(i,nyn/2+1+iny,k) = sq2*fout(i,nyn/2+1,k);
07204                             fout(i,nyn/2+1,k) *= sq2;
07205                           }
07206                         }
07207                         if(nzn>1) {
07208                                 for (j=1; j<=nyn; j++) {
07209                                         for (i=1; i<=lsdn; i++) {
07210                                                 fout(i,j,nzn/2+1+inz) = sq2*fout(i,j,nzn/2+1);
07211                                                 fout(i,j,nzn/2+1) *= sq2;
07212                                         }
07213                                 }
07214                         }
07215                 }
07216         }*/
07217         ret->set_complex(true);
07218         ret->set_ri(1);
07219         ret->set_fftpad(true);
07220         ret->set_attr("npad", 1);
07221         if (nxn%2 == 1) {ret->set_fftodd(true);} else {ret->set_fftodd(false);}
07222         if(RetReal) {
07223                 ret->do_ift_inplace();
07224                 ret->depad();
07225         }
07226         ret->update();
07227 
07228         /*Dict d1 = temp_ft->get_attr_dict();
07229         Dict d2 = ret->get_attr_dict();
07230         printf("-----------------Attribute Dict for temp_ft--------------\n");
07231         EMUtil::dump_dict(d1);
07232         printf("-----------------Attribute Dict for ret--------------\n");
07233         EMUtil::dump_dict(d2);*/
07234         if (!is_complex()) {
07235                 delete temp_ft;
07236                 temp_ft = 0;
07237         }
07238         return ret;
07239 }
07240 /*
07241 EMData *EMData::FourInterpol_i(int nxn, int nyni, int nzni, bool RetReal) {
07242 
07243         int nyn, nzn, lsd, lsdn, inx, iny, inz;
07244         int i, j, k;
07245 
07246         if(ny > 1) {
07247                 nyn = nyni;
07248                 if(nz > 1) {
07249                         nzn = nzni;
07250                 }  else {
07251                         nzn = 1;
07252                 }
07253         } else {
07254                 nyn = 1; nzn = 1;
07255         }
07256         if(nxn<nx || nyn<ny || nzn<nz)  throw ImageDimensionException("Cannot reduce the image size");
07257         lsd = nx-2 + 2 - nx%2;
07258         lsdn = nxn + 2 - nxn%2;
07259 //  do out of place ft
07260         EMData *temp_ft = this->copy();
07261         EMData *ret = this->copy();
07262         ret->set_size(lsdn, nyn, nzn);
07263         ret->to_zero();
07264         float *fout = ret->get_data();
07265         float *fint = temp_ft->get_data();
07266 //  TO KEEP EXACT VALUES ON THE ORIGINAL GRID ONE SHOULD USE
07267 //  SQ2     = 2.0. HOWEVER, TOTAL ENERGY WILL NOT BE CONSERVED
07268         float  sq2 = 1.0f/std::sqrt(2.0f);
07269         float  anorm = (float) nxn* (float) nyn* (float) nzn/(float) nx/ (float) ny/ (float) nz;
07270         for (i = 0; i < lsd*ny*nz; i++)  fint[i] *= anorm;
07271         inx = nxn-(nx-2); iny = nyn - ny; inz = nzn - nz;
07272         for (k=1; k<=nz/2+1; k++) for (j=1; j<=ny/2+1; j++) for (i=1; i<=lsd; i++) fout(i,j,k)=fint(i,j,k);
07273         if(nyn>1) {
07274         //cout << "  " <<nxn<<"  " <<nyn<<" A " <<nzn<<endl;
07275                 for (k=1; k<=nz/2+1; k++) for (j=ny/2+2+iny; j<=nyn; j++) for (i=1; i<=lsd; i++) fout(i,j,k)=fint(i,j-iny,k);
07276                 if(nzn>1) {
07277                         for (k=nz/2+2+inz; k<=nzn; k++) {
07278                                 for (j=1; j<=ny/2+1; j++) {
07279                                         for (i=1; i<=lsd; i++) {
07280                                                 fout(i,j,k)=fint(i,j,k-inz);
07281                                         }
07282                                 }
07283                                 for (j=ny/2+2+iny; j<=nyn; j++) {
07284                                         for (i=1; i<=lsd; i++) {
07285                                                 fout(i,j,k)=fint(i,j-iny,k-inz);
07286                                         }
07287                                 }
07288                         }
07289                 }
07290         }
07291 //       WEIGHTING FACTOR USED FOR EVEN NSAM. REQUIRED SINCE ADDING ZERO FOR
07292 //       INTERPOLATION WILL INTRODUCE A COMPLEX CONJUGATE FOR NSAM/2'TH
07293 //       ELEMENT.
07294         if(nx%2 == 0 && inx !=0) {
07295                 for (k=1; k<=nzn; k++) {
07296                         for (j=1; j<=nyn; j++) {
07297                                 fout(nx-2+1,j,k) *= sq2;
07298                                 fout(nx-2+2,j,k) *= sq2;
07299                         }
07300                 }
07301                 if(nyn>1) {
07302                         for (k=1; k<=nzn; k++) {
07303                           for (i=1; i<=lsd; i++) {
07304                             fout(i,ny/2+1+iny,k) = sq2*fout(i,ny/2+1,k);
07305                             fout(i,ny/2+1,k) *= sq2;
07306                           }
07307                         }
07308                         if(nzn>1) {
07309                                 for (j=1; j<=nyn; j++) {
07310                                         for (i=1; i<=lsd; i++) {
07311                                                 fout(i,j,nz/2+1+inz) = sq2*fout(i,j,nz/2+1);
07312                                                 fout(i,j,nz/2+1) *= sq2;
07313                                         }
07314                                 }
07315                         }
07316                 }
07317         }
07318         ret->set_complex(true);
07319         ret->set_ri(1);
07320         ret->set_fftpad(true);
07321         ret->set_attr("npad", 1);
07322         if (nxn%2 == 1) {ret->set_fftodd(true);} else {ret->set_fftodd(false);}
07323         if(RetReal) {
07324                 ret->do_ift_inplace();
07325                 ret->depad();
07326         }
07327         ret->update();
07328 
07329         delete temp_ft;
07330         temp_ft = 0;
07331         return ret;
07332 }
07333 */
07334 
07335 EMData *EMData::Four_ds(int nxn, int nyni, int nzni, bool RetReal) {
07336 
07337         int nyn, nzn, lsd, lsdn, inx, iny, inz;
07338         int i, j;
07339 
07340         if(ny > 1) {
07341                 nyn = nyni;
07342                 if(nz > 1) {
07343                         nzn = nzni;
07344                 }  else {
07345                         nzn = 1;
07346                 }
07347         } else {
07348                 nyn = 1; nzn = 1;
07349         }
07350         lsd = nx-2 + 2 - nx%2;
07351         lsdn = nxn + 2 - nxn%2;
07352 //  do out of place ft
07353         EMData *temp_ft = this->copy();
07354         EMData *ret = this->copy();
07355         ret->set_size(lsdn, nyn, nzn);
07356         ret->to_zero();
07357         float *fout = ret->get_data();
07358         float *fint = temp_ft->get_data();
07359 //  TO KEEP EXACT VALUES ON THE ORIGINAL GRID ONE SHOULD USE
07360 //  SQ2     = 2.0. HOWEVER, TOTAL ENERGY WILL NOT BE CONSERVED
07361 //      float  sq2 = 1.0f/std::sqrt(2.0f);
07362         float  anorm = (float) nxn* (float) nyn* (float) nzn/(float) nx/ (float) ny/ (float) nz;
07363         for (i = 0; i < lsd*ny*nz; i++)  fint[i] *= anorm;
07364         inx = nxn-(nx-2); iny = nyn - ny; inz = nzn - nz;
07365         for (j=1; j<=nyn; j++)
07366                 for (i=1; i<=lsdn; i++)
07367                         fout(i,j,1)=fint((i-1)/2*4+2-i%2,j*2-1,1);
07368         ret->set_complex(true);
07369         ret->set_ri(1);
07370         //ret->set_fftpad(true);
07371         //ret->set_attr("npad", 1);
07372         if (nxn%2 == 1) {ret->set_fftodd(true);} else {ret->set_fftodd(false);}
07373         if(RetReal) {
07374                 ret->do_ift_inplace();
07375                 ret->depad();
07376         }
07377         ret->update();
07378 
07379         delete temp_ft;
07380         temp_ft = 0;
07381         return ret;
07382 }
07383 
07384 EMData *EMData::Four_shuf_ds_cen_us(int nxn, int nyni, int, bool RetReal) {
07385 
07386         int nyn, nzn, lsd, lsdn, inx, iny, inz;
07387         int i, j;
07388 
07389         nyn = nyni;
07390         nzn = 1;
07391         lsd = nx;
07392         lsdn = nxn + 2 - nxn%2;
07393 
07394         EMData *temp_ft = this->copy();
07395         EMData *ret = this->copy();
07396         ret->set_size(lsdn, nyn, nzn);
07397         ret->to_zero();
07398         float *fout = ret->get_data();
07399         float *fint = temp_ft->get_data();
07400 //  TO KEEP EXACT VALUES ON THE ORIGINAL GRID ONE SHOULD USE
07401 //  SQ2     = 2.0. HOWEVER, TOTAL ENERGY WILL NOT BE CONSERVED
07402         float  sq2 = 1.0f/std::sqrt(2.0f);
07403 
07404         for (size_t i = 0; i < (size_t)lsd*ny*nz; i++)  fint[i] *= 4;
07405 
07406         inx = nxn-(nx-2); iny = nyn - ny; inz = nzn - nz;
07407         for (j=1; j<=ny/4; j++)
07408                 for (i=1; i<=(nx-2)/2+2; i++) {
07409                         int g = (i-1)/2+1;
07410                         if ((g+j)%2 == 0) {
07411                                 fout(i,j,1)=fint(g*4-2-i%2,j*2-1+ny/2,1);
07412                         } else {
07413                                 fout(i,j,1)=-fint(g*4-2-i%2,j*2-1+ny/2,1);
07414                         }
07415                 }
07416 
07417         for (j=ny/4+1; j<=ny/4+1; j++)
07418                 for (i=1; i<=(nx-2)/2+2; i++) {
07419                         int g = (i-1)/2+1;
07420                         if ((g+j)%2 == 0) {
07421                                 fout(i,j,1)=fint(g*4-2-i%2,j*2-1-ny/2,1);
07422                         } else {
07423                                 fout(i,j,1)=-fint(g*4-2-i%2,j*2-1-ny/2,1);
07424                         }
07425                 }
07426 
07427         for (j=ny/4+2; j<=ny/2; j++)
07428                 for (i=1; i<=(nx-2)/2+2; i++) {
07429                         int g = (i-1)/2+1;
07430                         if ((g+j)%2 == 0) {
07431                                 fout(i,j+ny/2,1)=fint(g*4-2-i%2,j*2-1-ny/2,1);
07432                         } else {
07433                                 fout(i,j+ny/2,1)=-fint(g*4-2-i%2,j*2-1-ny/2,1);
07434                         }
07435                 }
07436 
07437         if (nx%2 == 0) {
07438                 for (j=1; j<=nyn; j++) {
07439                         fout((nx-2)/2+1,j,1) *= sq2;
07440                         fout((nx-2)/2+2,j,1) *= sq2;
07441                 }
07442                 for (i=1; i<=lsd/2+1; i++) {
07443                         fout(i,ny/4+1+ny/2,1) = sq2*fout(i,ny/4+1,1);
07444                         fout(i,ny/4+1,1) *= sq2;
07445                 }
07446         }
07447 
07448         ret->set_complex(true);
07449         ret->set_ri(1);
07450 
07451         if (nxn%2 == 1) {ret->set_fftodd(true);} else {ret->set_fftodd(false);}
07452         if(RetReal) {
07453                 ret->do_ift_inplace();
07454                 ret->depad();
07455         }
07456         ret->update();
07457 
07458         delete temp_ft;
07459         temp_ft = 0;
07460         return ret;
07461 }
07462 
07463 #undef fint
07464 #undef fout
07465 
07466 #define  fint(jx,jy,jz)  fint[jx + (jy + jz*ny)*(size_t)nox]
07467 EMData *EMData::filter_by_image(EMData* image, bool RetReal) {
07468 
07469 
07470         bool   complex_input = this->is_complex();
07471         nx  = this->get_xsize();
07472         ny  = this->get_ysize();
07473         nz  = this->get_zsize();
07474         int nox;
07475         if (complex_input) nox = (nx - 2 + this->is_fftodd()); else nox = nx;
07476 
07477         int lsd2 = (nox + 2 - nox%2) / 2; // Extended x-dimension of the complex image
07478 
07479         EMData* fp = NULL; // output image
07480         if(complex_input) {
07481                 // fimage must remain pristine
07482                 fp = this->copy();
07483         } else {
07484                 fp = this->norm_pad( false, 1);
07485                 fp->do_fft_inplace();
07486         }
07487         fp->set_array_offsets(1,1,1);
07488         int nx2 = nox/2;
07489         int ny2 = ny/2;
07490         int nz2 = nz/2;
07491         float *fint = image->get_data();
07492         for ( int iz = 1; iz <= nz; iz++) {
07493                 int jz=nz2-iz+1; if(jz<0) jz += nz;
07494                 for ( int iy = 1; iy <= ny; iy++) {
07495                         int jy=ny2-iy+1; if(jy<0) jy += ny;
07496                         for ( int ix = 1; ix <= lsd2; ix++) {
07497                                 int jx = nx2-ix+1;
07498                                 fp->cmplx(ix,iy,iz) *= fint(jx,jy,jz);
07499                         }
07500                 }
07501         }
07502 
07503         fp->set_ri(1);
07504         fp->set_fftpad(true);
07505         fp->set_attr("npad", 1);
07506         if (nx%2 == 1) fp->set_fftodd(true);
07507         else fp->set_fftodd(false);
07508         if(RetReal) {
07509                 fp->do_ift_inplace();
07510                 fp->depad();
07511         }
07512         fp->set_array_offsets(0,0,0);
07513         fp->update();
07514 
07515         return fp;
07516 }
07517 #undef   fint
07518 #define  fint(jx,jy,jz)  fint[jx + (jy + jz*ny)*(size_t)nx]
07519 #define  fout(jx,jy,jz)  fout[jx + (jy + jz*ny)*(size_t)nx]
07520 EMData *EMData::replace_amplitudes(EMData* image, bool RetReal) {
07521 
07522 
07523         bool   complex_input = this->is_complex();
07524         nx  = this->