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

EMAN::DotCmp Class Reference

Use dot product of 2 same-size images to do the comparison. More...

#include <cmp.h>

Inheritance diagram for EMAN::DotCmp:

Inheritance graph
[legend]
Collaboration diagram for EMAN::DotCmp:

Collaboration graph
[legend]
List of all members.

Public Member Functions

float cmp (EMData *image, EMData *with) const
 To compare 'image' with another image passed in through its parameters.
string get_name () const
 Get the Cmp's name.
string get_desc () const
TypeDict get_param_types () const
 Get Cmp parameter information in a dictionary.

Static Public Member Functions

static CmpNEW ()

Static Public Attributes

static const string NAME = "dot"

Detailed Description

Use dot product of 2 same-size images to do the comparison.

// Added mask option PAP 04/23/06 For complex images, it does not check r/i vs a/p.

Author:
Steve Ludtke (sludtke@bcm.tmc.edu)
Date:
2005-07-13
Parameters:
negative Returns -1 * dot product, default true
normalize Returns normalized dot product -1.0 - 1.0

Definition at line 234 of file cmp.h.


Member Function Documentation

float DotCmp::cmp EMData image,
EMData with
const [virtual]
 

To compare 'image' with another image passed in through its parameters.

An optional transformation may be used to transform the 2 images.

Parameters:
image The first image to be compared.
with The second image to be comppared.
Returns:
The comparison result. Smaller better by default

Implements EMAN::Cmp.

Definition at line 288 of file cmp.cpp.

References dm, ENTERFUNC, EXITFUNC, EMAN::EMData::get_attr(), EMAN::EMData::get_const_data(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Dict::has_key(), EMAN::EMData::is_complex(), EMAN::EMData::is_fftodd(), nx, ny, EMAN::Cmp::params, EMAN::Dict::set_default(), sqrt(), and EMAN::Cmp::validate_input_args().

Referenced by EMAN::EMData::dot().

00289 {
00290         ENTERFUNC;
00291         validate_input_args(image, with);
00292 
00293         const float *const x_data = image->get_const_data();
00294         const float *const y_data = with->get_const_data();
00295 
00296         int normalize = params.set_default("normalize", 0);
00297         float negative = (float)params.set_default("negative", 1);
00298 
00299         if (negative) negative=-1.0; else negative=1.0;
00300         double result = 0.;
00301         long n = 0;
00302         if(image->is_complex() && with->is_complex()) {
00303         // Implemented by PAP  01/09/06 - please do not change.  If in doubts, write/call me.
00304                 int nx  = with->get_xsize();
00305                 int ny  = with->get_ysize();
00306                 int nz  = with->get_zsize();
00307                 nx = (nx - 2 + with->is_fftodd()); // nx is the real-space size of the input image
00308                 int lsd2 = (nx + 2 - nx%2) ; // Extended x-dimension of the complex image
00309 
00310                 int ixb = 2*((nx+1)%2);
00311                 int iyb = ny%2;
00312                 //
00313                 if(nz == 1) {
00314                 //  it looks like it could work in 3D, but does not
00315                 for ( int iz = 0; iz <= nz-1; ++iz) {
00316                         double part = 0.;
00317                         for ( int iy = 0; iy <= ny-1; ++iy) {
00318                                 for ( int ix = 2; ix <= lsd2 - 1 - ixb; ++ix) {
00319                                         size_t ii = ix + (iy  + iz * ny)* lsd2;
00320                                         part += x_data[ii] * double(y_data[ii]);
00321                                 }
00322                         }
00323                         for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00324                                 size_t ii = (iy  + iz * ny)* lsd2;
00325                                 part += x_data[ii] * double(y_data[ii]);
00326                                 part += x_data[ii+1] * double(y_data[ii+1]);
00327                         }
00328                         if(nx%2 == 0) {
00329                                 for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00330                                         size_t ii = lsd2 - 2 + (iy  + iz * ny)* lsd2;
00331                                         part += x_data[ii] * double(y_data[ii]);
00332                                         part += x_data[ii+1] * double(y_data[ii+1]);
00333                                 }
00334 
00335                         }
00336                         part *= 2;
00337                         part += x_data[0] * double(y_data[0]);
00338                         if(ny%2 == 0) {
00339                                 size_t ii = (ny/2  + iz * ny)* lsd2;
00340                                 part += x_data[ii] * double(y_data[ii]);
00341                         }
00342                         if(nx%2 == 0) {
00343                                 size_t ii = lsd2 - 2 + (0  + iz * ny)* lsd2;
00344                                 part += x_data[ii] * double(y_data[ii]);
00345                                 if(ny%2 == 0) {
00346                                         int ii = lsd2 - 2 +(ny/2  + iz * ny)* lsd2;
00347                                         part += x_data[ii] * double(y_data[ii]);
00348                                 }
00349                         }
00350                         result += part;
00351                 }
00352                 if( normalize ) {
00353                 //  it looks like it could work in 3D, but does not
00354                 double square_sum1 = 0., square_sum2 = 0.;
00355                 for ( int iz = 0; iz <= nz-1; ++iz) {
00356                         for ( int iy = 0; iy <= ny-1; ++iy) {
00357                                 for ( int ix = 2; ix <= lsd2 - 1 - ixb; ++ix) {
00358                                         size_t ii = ix + (iy  + iz * ny)* lsd2;
00359                                         square_sum1 += x_data[ii] * double(x_data[ii]);
00360                                         square_sum2 += y_data[ii] * double(y_data[ii]);
00361                                 }
00362                         }
00363                         for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00364                                 size_t ii = (iy  + iz * ny)* lsd2;
00365                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00366                                 square_sum1 += x_data[ii+1] * double(x_data[ii+1]);
00367                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00368                                 square_sum2 += y_data[ii+1] * double(y_data[ii+1]);
00369                         }
00370                         if(nx%2 == 0) {
00371                                 for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00372                                         size_t ii = lsd2 - 2 + (iy  + iz * ny)* lsd2;
00373                                         square_sum1 += x_data[ii] * double(x_data[ii]);
00374                                         square_sum1 += x_data[ii+1] * double(x_data[ii+1]);
00375                                         square_sum2 += y_data[ii] * double(y_data[ii]);
00376                                         square_sum2 += y_data[ii+1] * double(y_data[ii+1]);
00377                                 }
00378 
00379                         }
00380                         square_sum1 *= 2;
00381                         square_sum1 += x_data[0] * double(x_data[0]);
00382                         square_sum2 *= 2;
00383                         square_sum2 += y_data[0] * double(y_data[0]);
00384                         if(ny%2 == 0) {
00385                                 int ii = (ny/2  + iz * ny)* lsd2;
00386                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00387                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00388                         }
00389                         if(nx%2 == 0) {
00390                                 int ii = lsd2 - 2 + (0  + iz * ny)* lsd2;
00391                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00392                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00393                                 if(ny%2 == 0) {
00394                                         int ii = lsd2 - 2 +(ny/2  + iz * ny)* lsd2;
00395                                         square_sum1 += x_data[ii] * double(x_data[ii]);
00396                                         square_sum2 += y_data[ii] * double(y_data[ii]);
00397                                 }
00398                         }
00399                 }
00400                 result /= sqrt(square_sum1*square_sum2);
00401                 } else  result /= ((float)nx*(float)ny*(float)nz*(float)nx*(float)ny*(float)nz);
00402 
00403                 } else { //This 3D code is incorrect, but it is the best I can do now 01/09/06 PAP
00404                 int ky, kz;
00405                 int ny2 = ny/2; int nz2 = nz/2;
00406                 for ( int iz = 0; iz <= nz-1; ++iz) {
00407                         if(iz>nz2) kz=iz-nz; else kz=iz;
00408                         for ( int iy = 0; iy <= ny-1; ++iy) {
00409                                 if(iy>ny2) ky=iy-ny; else ky=iy;
00410                                 for ( int ix = 0; ix <= lsd2-1; ++ix) {
00411                                         // Skip Friedel related values
00412                                         if(ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
00413                                                 size_t ii = ix + (iy  + iz * ny)* lsd2;
00414                                                 result += x_data[ii] * double(y_data[ii]);
00415                                         }
00416                                 }
00417                         }
00418                 }
00419                 if( normalize ) {
00420                 //  still incorrect
00421                 double square_sum1 = 0., square_sum2 = 0.;
00422                 int ky, kz;
00423                 int ny2 = ny/2; int nz2 = nz/2;
00424                 for ( int iz = 0; iz <= nz-1; ++iz) {
00425                         if(iz>nz2) kz=iz-nz; else kz=iz;
00426                         for ( int iy = 0; iy <= ny-1; ++iy) {
00427                                 if(iy>ny2) ky=iy-ny; else ky=iy;
00428                                 for ( int ix = 0; ix <= lsd2-1; ++ix) {
00429                                         // Skip Friedel related values
00430                                         if(ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
00431                                                 size_t ii = ix + (iy  + iz * ny)* lsd2;
00432                                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00433                                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00434                                         }
00435                                 }
00436                         }
00437                 }
00438                 result /= sqrt(square_sum1*square_sum2);
00439                 } else result /= ((float)nx*(float)ny*(float)nz*(float)nx*(float)ny*(float)nz/2);
00440                 }
00441         } else {
00442                 size_t totsize = image->get_xsize() * image->get_ysize() * image->get_zsize();
00443 
00444                 double square_sum1 = 0., square_sum2 = 0.;
00445 
00446                 if (params.has_key("mask")) {
00447                         EMData* mask;
00448                         mask = params["mask"];
00449                         const float *const dm = mask->get_const_data();
00450                         if (normalize) {
00451                                 for (size_t i = 0; i < totsize; i++) {
00452                                         if (dm[i] > 0.5) {
00453                                                 square_sum1 += x_data[i]*double(x_data[i]);
00454                                                 square_sum2 += y_data[i]*double(y_data[i]);
00455                                                 result += x_data[i]*double(y_data[i]);
00456                                         }
00457                                 }
00458                         } else {
00459                                 for (size_t i = 0; i < totsize; i++) {
00460                                         if (dm[i] > 0.5) {
00461                                                 result += x_data[i]*double(y_data[i]);
00462                                                 n++;
00463                                         }
00464                                 }
00465                         }
00466                 } else {
00467                         // this little bit of manual loop unrolling makes the dot product as fast as sqeuclidean with -O2
00468                         for (size_t i=0; i<totsize; i++) result+=x_data[i]*y_data[i];
00469 
00470                         if (normalize) {
00471                                 square_sum1 = image->get_attr("square_sum");
00472                                 square_sum2 = with->get_attr("square_sum");
00473                         } else n = totsize;
00474                 }
00475                 if (normalize) result /= (sqrt(square_sum1*square_sum2)); else result /= n;
00476         }
00477 
00478 
00479         EXITFUNC;
00480         return (float) (negative*result);
00481 }

string EMAN::DotCmp::get_desc  )  const [inline, virtual]
 

Implements EMAN::Cmp.

Definition at line 244 of file cmp.h.

00245                 {
00246                         return "Dot product (default -1 * dot product)";
00247                 }

string EMAN::DotCmp::get_name  )  const [inline, virtual]
 

Get the Cmp's name.

Each Cmp is identified by a unique name.

Returns:
The Cmp's name.

Implements EMAN::Cmp.

Definition at line 239 of file cmp.h.

References NAME.

00240                 {
00241                         return NAME;
00242                 }

TypeDict EMAN::DotCmp::get_param_types  )  const [inline, virtual]
 

Get Cmp parameter information in a dictionary.

Each parameter has one record in the dictionary. Each record contains its name, data-type, and description.

Returns:
A dictionary containing the parameter info.

Implements EMAN::Cmp.

Definition at line 254 of file cmp.h.

References EMAN::EMObject::EMDATA, EMAN::EMObject::INT, and EMAN::TypeDict::put().

00255                 {
00256                         TypeDict d;
00257                         d.put("negative", EMObject::INT, "If set, returns -1 * dot product. Set by default so smaller is better");
00258                         d.put("normalize", EMObject::INT, "If set, returns normalized dot product (cosine of the angle) -1.0 - 1.0.");
00259                         d.put("mask", EMObject::EMDATA, "image mask");
00260                         return d;
00261                 }

static Cmp* EMAN::DotCmp::NEW  )  [inline, static]
 

Definition at line 249 of file cmp.h.

00250                 {
00251                         return new DotCmp();
00252                 }


Member Data Documentation

const string DotCmp::NAME = "dot" [static]
 

Definition at line 263 of file cmp.h.

Referenced by get_name().


The documentation for this class was generated from the following files:
Generated on Mon Jul 19 13:05:56 2010 for EMAN2 by  doxygen 1.4.4