Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

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

Generated on Thu Dec 9 13:45:45 2010 for EMAN2 by  doxygen 1.3.9.1