crosscorrelation.C

Go to the documentation of this file.
00001 /* Gnome gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  *
00005  * plugin_helper reports your answers as
00006  *
00007  * Gxsm Plugin Name: crosscorrelation.C
00008  * ========================================
00009  * 
00010  * Copyright (C) 1999 The Free Software Foundation
00011  *
00012  * Authors: Percy Zahl <zahl@fkp.uni-hannover.de>
00013  * additional features: Andreas Klust <klust@fkp.uni-hannover.de>
00014  *
00015  * This program is free software; you can redistribute it and/or modify
00016  * it under the terms of the GNU General Public License as published by
00017  * the Free Software Foundation; either version 2 of the License, or
00018  * (at your option) any later version.
00019  *
00020  * This program is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00028  */
00029 
00030 /* Please do not change the Begin/End lines of this comment section!
00031  * this is a LaTeX style section used for cross generation of the PlugIn Manual 
00032  * Chapter. Add a complete PlugIn documentation inbetween the Begin/End marks!
00033  * All "% PlugInXXX" commentary tags are mandatory
00034  * All "% OptPlugInXXX" tags are optional
00035  * --------------------------------------------------------------------------------
00036 % BeginPlugInDocuSection
00037 % PlugInDocuCaption: Crosscorrelation
00038 % PlugInName: crosscorrelation
00039 % PlugInAuthor: Erik Muller
00040 % PlugInAuthorEmail: emmuller@users.sourceforge.net
00041 % PlugInMenuPath: Math/Statistic/Cross Correlation
00042 
00043 % PlugInDescription
00044  Computes the crosscorrelation of two images using a masked area of first source (the active scan).
00045 
00046 -- WORK IN PROGRESS --
00047 
00048 %%% \[ Z' = |\text{IFT} (\text{FT} (Z_{\text{active}}) \times \text{FT} (Z_{\text{X}}) )| \]
00049 
00050 % PlugInUsage
00051  Call \GxsmMenu{Math/Statistic/Cross Correlation} to execute.
00052 
00053 % OptPlugInSources
00054  The active and X channel are used as data source, a rectangular
00055  selection mask is used for feature selection.
00056 
00057 % OptPlugInDest
00058  The computation result is placed into an existing math channel, else
00059  into a new created math channel.
00060 
00061 % OptPlugInNotes
00062  The quadrants of the resulting invers spectrum are aligned in a way,
00063  that the intensity of by it self correlated pixels (distance zero) is
00064  found at the image center and not at all four edges.
00065 
00066 
00067 % EndPlugInDocuSection
00068  * -------------------------------------------------------------------------------- 
00069  */
00070 
00071 #include <complex>
00072 #include <gtk/gtk.h>
00073 #include "config.h"
00074 #include "gxsm/plugin.h"
00075 #include "gxsm/xsmmath.h"
00076 
00077 //      *((__complex__ double*)(out1[0])) = *((__complex__ double*)(in1[0])) * *((__complex__ double*)(in1[0]));
00078 
00079 #define ComplexP (__complex__ double*)
00080 #define ComplexProd(A,B,C) *(ComplexP(C)) = *(ComplexP(A)) * *(ComplexP(B))
00081 
00082 
00083 
00084 // Plugin Prototypes
00085 static void crosscorrelation_init( void );
00086 static void crosscorrelation_about( void );
00087 static void crosscorrelation_configure( void );
00088 static void crosscorrelation_cleanup( void );
00089 
00090 // Define Type of math plugin here, only one line should be commented in!!
00091 //#define GXSM_ONE_SRC_PLUGIN__DEF
00092 #define GXSM_TWO_SRC_PLUGIN__DEF
00093 
00094 // Math-Run-Function, use only one of (crossmatically done :=)
00095 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00096 // "OneSrc" Prototype
00097 static gboolean crosscorrelation_run( Scan *Src, Scan *Dest );
00098 #else
00099 // "TwoSrc" Prototype
00100 static gboolean crosscorrelation_run( Scan *Src1, Scan *Src2, Scan *Dest );
00101 #endif
00102 
00103 // Fill in the GxsmPlugin Description here
00104 GxsmPlugin crosscorrelation_pi = {
00105         NULL,                   // filled in and used by Gxsm, don't touch !
00106         NULL,                   // filled in and used by Gxsm, don't touch !
00107         0,                      // filled in and used by Gxsm, don't touch !
00108         NULL,                   // The Gxsm-App Class Ref.pointer (called "gapp" in Gxsm) is 
00109         // filled in here by Gxsm on Plugin load, 
00110         // just after init() is called !!!
00111         // ----------------------------------------------------------------------
00112         // Plugins Name, CodeStly is like: Name-M1S|M2S-BG|F1D|F2D|ST|TR|Misc
00113         "crosscorrelation-"
00114 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00115         "M1S"
00116 #else
00117         "M2S"
00118 #endif
00119         "-ST",
00120         // Plugin's Category - used to crossdecide on Pluginloading or ignoring
00121         // NULL: load, else
00122         // example: "+noHARD +STM +AFM"
00123         // load only, if "+noHARD: no hardware" and Instrument is STM or AFM
00124         // +/-xxxHARD und (+/-INST or ...)
00125         NULL,
00126         // Description, is shown by PluginViewer (Plugin: listplugin, Tools->Plugin Details)
00127         "Computes the Cross-Correlation of a Scan.",
00128         // Author(s)
00129         "Percy Zahl",
00130         // Menupath to position where it is appendet to
00131         N_("_Math/_Statistics/"),
00132         // Menuentry
00133         N_("Cross Correlation"),
00134         // help text shown on menu
00135         N_("Do a Cross-Correlation of the scan"),
00136         // more info...
00137         "Calc. Cross Correlation of Scan",
00138         NULL,          // error msg, plugin may put error status msg here later
00139         NULL,          // Plugin Status, managed by Gxsm, plugin may manipulate it too
00140         // init-function pointer, can be "NULL", 
00141         // called if present at plugin load
00142         crosscorrelation_init,  
00143         // query-function pointer, can be "NULL", 
00144         // called if present after plugin init to let plugin manage it install itself
00145         NULL, // query should be "NULL" for Gxsm-Math-Plugin !!!
00146         // about-function, can be "NULL"
00147         // can be called by "Plugin Details"
00148         crosscorrelation_about,
00149         // configure-function, can be "NULL"
00150         // can be called by "Plugin Details"
00151         crosscorrelation_configure,
00152         // run-function, can be "NULL", if non-Zero and no query defined, 
00153         // it is called on menupath->"plugin"
00154         NULL, // run should be "NULL" for Gxsm-Math-Plugin !!!
00155         // cleanup-function, can be "NULL"
00156         // called if present at plugin removeal
00157         crosscorrelation_cleanup
00158 };
00159 
00160 // special math Plugin-Strucure, use
00161 // GxsmMathOneSrcPlugin crosscorrelation_m1s_pi -> "OneSrcMath"
00162 // GxsmMathTwoSrcPlugin crosscorrelation_m2s_pi -> "TwoSrcMath"
00163 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00164 GxsmMathOneSrcPlugin crosscorrelation_m1s_pi
00165 #else
00166 GxsmMathTwoSrcPlugin crosscorrelation_m2s_pi
00167 #endif
00168 = {
00169         // math-function to run, see prototype(s) above!!
00170         crosscorrelation_run
00171 };
00172 
00173 // Text used in Aboutbox, please update!!
00174 static const char *about_text = N_("Gxsm crosscorrelation Plugin\n\n"
00175                                    "Computes the Cross-Correlation of a scan:\n"
00176                                    "The Cross-Correlation of a scan is computed\n"
00177                                    "by FT the source Scan, setting the phase\n"
00178                                    "to zero and doing the IFT.");
00179 
00180 // Symbol "get_gxsm_plugin_info" is resolved by dlsym from Gxsm, used to get Plugin's info!! 
00181 // Essential Plugin Function!!
00182 GxsmPlugin *get_gxsm_plugin_info ( void ){ 
00183         crosscorrelation_pi.description = g_strdup_printf(N_("Gxsm MathOneArg crosscorrelation plugin %s"), VERSION);
00184         return &crosscorrelation_pi; 
00185 }
00186 
00187 // Symbol "get_gxsm_math_one|two_src_plugin_info" is resolved by dlsym from Gxsm, 
00188 // used to find out which Math Type the Plugin is!! 
00189 // Essential Plugin Function!!
00190 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00191 GxsmMathOneSrcPlugin *get_gxsm_math_one_src_plugin_info( void ) {
00192         return &crosscorrelation_m1s_pi; 
00193 }
00194 #else
00195 GxsmMathTwoSrcPlugin *get_gxsm_math_two_src_plugin_info( void ) { 
00196         return &crosscorrelation_m2s_pi; 
00197 }
00198 #endif
00199 
00200 /* Here we go... */
00201 // init-Function
00202 static void crosscorrelation_init(void)
00203 {
00204         PI_DEBUG (DBG_L2, "crosscorrelation Plugin Init");
00205 }
00206 
00207 // about-Function
00208 static void crosscorrelation_about(void)
00209 {
00210         const gchar *authors[] = { crosscorrelation_pi.authors, NULL};
00211         gtk_widget_show(gnome_about_new ( crosscorrelation_pi.name,
00212                                           VERSION,
00213                                           N_("(C) 2000 the Free Software Foundation"),
00214                                           about_text,
00215                                           authors,
00216                                           NULL, NULL, NULL
00217                                 ));
00218 }
00219 
00220 double WindowDefault=0;
00221 double WindowLast=0;
00222 
00223 // configure-Function
00224 static void crosscorrelation_configure(void)
00225 {
00226 
00227 //      if(crosscorrelation_pi.app)
00228 //              crosscorrelation_pi.app->message("crosscorrelation Plugin Configuration");
00229         crosscorrelation_pi.app->ValueRequest("Enter Value", "Window", 
00230                                               "Please enter the window type\n"
00231                                               "0: Uniform\n"
00232                                               "1: Hanning\n"
00233                                               "2: Hamming\n"
00234                                               "3: Bartlett\n"
00235                                               "4: Blackman\n"
00236                                               "5: Connes",
00237                                               crosscorrelation_pi.app->xsm->Unity, 
00238                                               0, 5, ".0f", &WindowDefault);
00239 
00240 
00241 }
00242 
00243 // cleanup-Function
00244 static void crosscorrelation_cleanup(void)
00245 {
00246         PI_DEBUG (DBG_L2, "crosscorrelation Plugin Cleanup");
00247 }
00248 
00249 
00250 
00251 // run-Function
00252 static gboolean crosscorrelation_run(Scan *Src1, Scan *Src2, Scan *Dest)
00253 { 
00254         double window=WindowLast;
00255         if(fabs(WindowDefault) > 1e-10)
00256                 window = WindowDefault;
00257         else
00258                 crosscorrelation_pi.app->ValueRequest("Enter Value", "Window", 
00259                                                       "Please enter the window type\n"
00260                                                       "0: Uniform\n"
00261                                                       "1: Hanning\n"
00262                                                       "2: Hamming\n"
00263                                                       "3: Bartlett\n"
00264                                                       "4: Blackman\n"
00265                                                       "5: Connes",
00266                                                       crosscorrelation_pi.app->xsm->Unity, 
00267                                                       0, 5, ".0f", &window);
00268 
00269 
00270         // Set Dest to Float, Range: +/-100% =^= One Pixel
00271         Dest->mem2d->Resize(Dest->data.s.nx, Dest->data.s.ny, ZD_FLOAT);
00272 
00273         // Get the size of the two images.
00274         int Nx1,Ny1,Nx2,Ny2;
00275         Nx1=Src1->mem2d->GetNx();
00276         Ny1=Src1->mem2d->GetNy();
00277         Nx2=Src2->mem2d->GetNx();
00278         Ny2=Src2->mem2d->GetNy();
00279 
00280 
00281         // allocate memory for the complex data and one line buffer
00282         fftw_complex *in1  = new fftw_complex [Nx1*Ny1];
00283         fftw_complex *in2  = new fftw_complex [Nx2*Ny2];
00284         fftw_complex *in3  = new fftw_complex [Nx1*Ny1];    
00285         fftw_complex *out1 = new fftw_complex [Nx1*Ny1];
00286         fftw_complex *out2 = new fftw_complex [Nx2*Ny2];
00287         fftw_complex *out3 = new fftw_complex [Nx1*Ny1];    
00288 
00289 
00290 
00291 
00292 
00293         double xfactor=1,yfactor=1;
00294 
00295         // Fill array with data and apply window function to the first image
00296         for (int pos=0, line=0; line < Ny1; ++line)
00297                 for (int col=0; col < Nx1; ++col, ++pos){                 
00298                        
00299                         if(window == 0.){
00300                                 xfactor=1.0;
00301                                 yfactor=1.0;
00302                         }
00303                         else if(window == 1.){
00304                                 xfactor = 0.5*(1.0+cos(2.0*M_PI*(line-Ny1/2.0)/Ny1));
00305                                 yfactor = 0.5*(1.0+cos(2.0*M_PI*(col-Nx1/2.0)/Nx1));
00306                         }
00307                         else if(window == 2.){
00308                                 xfactor = 0.54+0.46*cos(2.0*M_PI*(line-Ny1/2.0)/Ny1);
00309                                 yfactor = 0.54+0.46*cos(2.0*M_PI*(col-Nx1/2.0)/Nx1);
00310                         }
00311                         else if(window == 3.){
00312                                 xfactor=(1.0-2.0*sqrt((line-Ny1/2.0)*(line-Ny1/2.0))/Ny1);
00313                                 yfactor=(1.0-2.0*sqrt((col-Nx1/2.0)*(col-Nx1/2.0))/Nx1);
00314                         }
00315                         else if(window == 4.){
00316                                 xfactor = 0.42+0.5*cos(2.0*M_PI*(line-Ny1/2.0)/Ny1)+0.08*cos(4.0*M_PI*(line-Ny1/2.0)/Ny1);
00317                                 yfactor = 0.42+0.5*cos(2.0*M_PI*(col-Nx1/2.0)/Nx1)+0.08*cos(4.0*M_PI*(col-Nx1/2.0)/Nx1);
00318                         }
00319                         else if(window == 5.){
00320                                 xfactor = (1.0-4.0*(line-Ny1/2.0)*(line-Ny1/2.0)/Ny1/Ny1)*(1.-4.0*(line-Ny1/2.0)*(line-Ny1/2.0)/Ny1/Ny1);
00321                                 yfactor = (1.0-4.0*(col-Nx1/2.0)*(col-Nx1/2.0)/Nx1/Nx1)*(1.-4.0*(col-Nx1/2.0)*(col-Nx1/2.0)/Nx1/Nx1);
00322                         }
00323                         
00324                         c_re(in1[pos]) = Src1->mem2d->GetDataPkt(col, line)*xfactor*yfactor;
00325                         c_im(in1[pos]) = 0.;                    
00326                 }
00327         
00328 
00329         
00330 
00331         // Fill array with data and apply window function to the second image
00332         for (int pos=0, line=0; line < Ny2; ++line)
00333                 for (int col=0; col < Nx2; ++col, ++pos){
00334 
00335                         if(window == 0.){
00336                                 xfactor=1.0;
00337                                 yfactor=1.0;
00338                         }
00339                         else if(window == 1.){
00340                                 xfactor = 0.5*(1.0+cos(2.0*M_PI*(line-Ny2/2.0)/Ny2));
00341                                 yfactor = 0.5*(1.0+cos(2.0*M_PI*(col-Nx2/2.0)/Nx2));
00342                         }
00343                         else if(window == 2.){
00344                                 xfactor = 0.54+0.46*cos(2.0*M_PI*(line-Ny2/2.0)/Ny2);
00345                                 yfactor = 0.54+0.46*cos(2.0*M_PI*(col-Nx2/2.0)/Nx2);
00346                         }
00347                         else if(window == 3.){
00348                                 xfactor=(1.0-2.0*sqrt((line-Ny2/2.0)*(line-Ny2/2.0))/Ny2);
00349                                 yfactor=(1.0-2.0*sqrt((col-Nx2/2.0)*(col-Nx2/2.0))/Nx2);
00350                         }
00351                         else if(window == 4.){
00352                                 xfactor = 0.42+0.5*cos(2.0*M_PI*(line-Ny2/2.0)/Ny2)+0.08*cos(4.0*M_PI*(line-Ny2/2.0)/Ny2);
00353                                 yfactor = 0.42+0.5*cos(2.0*M_PI*(col-Nx2/2.0)/Nx2)+0.08*cos(4.0*M_PI*(col-Nx2/2.0)/Nx2);
00354                         }
00355                         else if(window == 5.){
00356                                 xfactor = (1.0-4.0*(line-Ny2/2.0)*(line-Ny2/2.0)/Ny2/Ny2)*(1.0-4.0*(line-Ny2/2.0)*(line-Ny2/2.0)/Ny2/Ny2);
00357                                 yfactor = (1.0-4.0*(col-Nx2/2.0)*(col-Nx2/2.0)/Nx2/Nx2)*(1.0-4.0*(col-Nx2/2.0)*(col-Nx2/2.0)/Nx2/Nx2);
00358                         }
00359 
00360                         c_re(in2[pos]) = Src2->mem2d->GetDataPkt(col, line)*xfactor*yfactor;
00361                         c_im(in2[pos]) = 0.;                    
00362                 }
00363 
00364 
00365 
00366         // do the fourier transform
00367         // create plan for fft
00368         fftw_plan plan1 = fftw_plan_dft_2d (Ny1, Nx1, in1, out1, FFTW_FORWARD, FFTW_ESTIMATE);
00369         
00370         // compute fft
00371         fftw_execute (plan1);
00372 
00373 
00374         
00375         fftw_plan plan2 = fftw_plan_dft_2d (Ny2, Nx2, in2, out2, FFTW_FORWARD, FFTW_ESTIMATE);
00376         
00377         // compute fft
00378         fftw_execute (plan2);
00379         
00380 
00381         //Matrix Multiply -- this is not the right way!
00382 //      for(int i=0; i < Ny1; ++i)
00383 //              for(int j=0; j < Nx2; ++j){
00384 //                      c_re(in3[j+Nx1*i])=0;
00385 //                      c_im(in3[j+Nx1*i])=0;                         
00386 //                              for(int k=0; k < Ny2; ++k){
00387 //                                      c_re(in3[j+Nx1*i])+=c_re(out1[k+Nx1*i])*c_re(out2[j+Nx2*k])+c_im(out1[k+Nx1*i])*c_im(out2[j+Nx2*k]);
00388 //                                      c_im(in3[j+Nx1*i])+=c_im(out1[k+Nx1*i])*c_re(out2[j+Nx2*k])-c_re(out1[k+Nx1*i])*c_im(out2[j+Nx2*k]);
00389 //                              }
00390 //              }
00391         //Element-by-Element Multiply -- this is the right way!
00392         for(int i=0; i < Ny1; ++i)
00393                 for(int j=0; j < Nx2; ++j){
00394                         c_re(in3[j+Nx1*i])=0;
00395                         c_im(in3[j+Nx1*i])=0;                         
00396                         c_re(in3[j+Nx1*i])=c_re(out1[j+Nx1*i])*c_re(out2[j+Nx2*i])+c_im(out1[j+Nx1*i])*c_im(out2[j+Nx2*i]);
00397                         c_im(in3[j+Nx1*i])=c_im(out1[j+Nx1*i])*c_re(out2[j+Nx2*i])-c_re(out1[j+Nx1*i])*c_im(out2[j+Nx2*i]);
00398                 }
00399 
00400 
00401         fftw_plan plan3 = fftw_plan_dft_2d (Ny1, Nx1, in3, out3, FFTW_BACKWARD, FFTW_ESTIMATE);
00402         // compute fft
00403         fftw_execute (plan3);
00404 
00405 
00406 
00407         //Find Normalization factor
00408         double SumNorm=0.0;
00409         for(int i=0; i < Nx1*Ny1; i++){
00410                 SumNorm += c_re(in1[i])*c_re(in2[i]);
00411             }
00412 
00413 
00414         //WRITE DATA TO DEST
00415         for (int pos=0, i=0; i < Ny1; ++i)
00416                 for (int j=0; j < Nx1; ++j, ++pos){
00417                         Dest->mem2d->PutDataPkt(c_re(out3[pos])/SumNorm/Nx1/Ny1,//j, i) ;
00418                                      QSWP (j,Nx1), 
00419                                      QSWP (i, Ny1));
00420                 }
00421 
00422                                              
00423         // destroy plan
00424         fftw_destroy_plan (plan1);
00425         fftw_destroy_plan (plan2);
00426         fftw_destroy_plan (plan3);
00427         
00428         // free memory
00429         delete in1;
00430         delete in2;
00431         delete in3;                                  
00432         delete out1;
00433         delete out2;
00434         delete out3;
00435 
00436         Dest->mem2d->data->MkXLookup(0., Src1->data.s.rx);
00437         Dest->mem2d->data->MkYLookup(0., Src1->data.s.ry);
00438         UnitObj *u;
00439 //      Dest->data.SetZUnit(u=new LinUnit(" "," ",0.02328,0));
00440         Dest->data.SetZUnit(u=new LinUnit(" "," ",1.,0));
00441         Dest->data.s.dz=1.0;
00442 //      Dest->data.s.dx=1.0;
00443 //      Dest->data.s.dy=1.0;
00444         delete u;
00445 
00446         return MATH_OK;
00447 }

Generated on Sat Apr 1 09:04:22 2006 for GXSM by  doxygen 1.4.6