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

CmpNEW ()

Static Public Attributes

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 270 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 381 of file cmp.cpp.

References dm, 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::Dict::set_default(), sqrt(), and EMAN::Cmp::validate_input_args().

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

00382 {
00383         ENTERFUNC;
00384         validate_input_args(image, with);
00385 
00386         const float *const x_data = image->get_const_data();
00387         const float *const y_data = with->get_const_data();
00388 
00389         int normalize = params.set_default("normalize", 0);
00390         float negative = (float)params.set_default("negative", 1);
00391 
00392         if (negative) negative=-1.0; else negative=1.0;
00393         double result = 0.;
00394         long n = 0;
00395         if(image->is_complex() && with->is_complex()) {
00396         // Implemented by PAP  01/09/06 - please do not change.  If in doubts, write/call me.
00397                 int nx  = with->get_xsize();
00398                 int ny  = with->get_ysize();
00399                 int nz  = with->get_zsize();
00400                 nx = (nx - 2 + with->is_fftodd()); // nx is the real-space size of the input image
00401                 int lsd2 = (nx + 2 - nx%2) ; // Extended x-dimension of the complex image
00402 
00403                 int ixb = 2*((nx+1)%2);
00404                 int iyb = ny%2;
00405                 //
00406                 if(nz == 1) {
00407                 //  it looks like it could work in 3D, but does not
00408                 for ( int iz = 0; iz <= nz-1; ++iz) {
00409                         double part = 0.;
00410                         for ( int iy = 0; iy <= ny-1; ++iy) {
00411                                 for ( int ix = 2; ix <= lsd2 - 1 - ixb; ++ix) {
00412                                         size_t ii = ix + (iy  + iz * ny)* lsd2;
00413                                         part += x_data[ii] * double(y_data[ii]);
00414                                 }
00415                         }
00416                         for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00417                                 size_t ii = (iy  + iz * ny)* lsd2;
00418                                 part += x_data[ii] * double(y_data[ii]);
00419                                 part += x_data[ii+1] * double(y_data[ii+1]);
00420                         }
00421                         if(nx%2 == 0) {
00422                                 for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00423                                         size_t ii = lsd2 - 2 + (iy  + iz * ny)* lsd2;
00424                                         part += x_data[ii] * double(y_data[ii]);
00425                                         part += x_data[ii+1] * double(y_data[ii+1]);
00426                                 }
00427 
00428                         }
00429                         part *= 2;
00430                         part += x_data[0] * double(y_data[0]);
00431                         if(ny%2 == 0) {
00432                                 size_t ii = (ny/2  + iz * ny)* lsd2;
00433                                 part += x_data[ii] * double(y_data[ii]);
00434                         }
00435                         if(nx%2 == 0) {
00436                                 size_t ii = lsd2 - 2 + (0  + iz * ny)* lsd2;
00437                                 part += x_data[ii] * double(y_data[ii]);
00438                                 if(ny%2 == 0) {
00439                                         int ii = lsd2 - 2 +(ny/2  + iz * ny)* lsd2;
00440                                         part += x_data[ii] * double(y_data[ii]);
00441                                 }
00442                         }
00443                         result += part;
00444                 }
00445                 if( normalize ) {
00446                 //  it looks like it could work in 3D, but does not
00447                 double square_sum1 = 0., square_sum2 = 0.;
00448                 for ( int iz = 0; iz <= nz-1; ++iz) {
00449                         for ( int iy = 0; iy <= ny-1; ++iy) {
00450                                 for ( int ix = 2; ix <= lsd2 - 1 - ixb; ++ix) {
00451                                         size_t ii = ix + (iy  + iz * ny)* lsd2;
00452                                         square_sum1 += x_data[ii] * double(x_data[ii]);
00453                                         square_sum2 += y_data[ii] * double(y_data[ii]);
00454                                 }
00455                         }
00456                         for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00457                                 size_t ii = (iy  + iz * ny)* lsd2;
00458                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00459                                 square_sum1 += x_data[ii+1] * double(x_data[ii+1]);
00460                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00461                                 square_sum2 += y_data[ii+1] * double(y_data[ii+1]);
00462                         }
00463                         if(nx%2 == 0) {
00464                                 for ( int iy = 1; iy <= ny/2-1 + iyb; ++iy) {
00465                                         size_t ii = lsd2 - 2 + (iy  + iz * ny)* lsd2;
00466                                         square_sum1 += x_data[ii] * double(x_data[ii]);
00467                                         square_sum1 += x_data[ii+1] * double(x_data[ii+1]);
00468                                         square_sum2 += y_data[ii] * double(y_data[ii]);
00469                                         square_sum2 += y_data[ii+1] * double(y_data[ii+1]);
00470                                 }
00471 
00472                         }
00473                         square_sum1 *= 2;
00474                         square_sum1 += x_data[0] * double(x_data[0]);
00475                         square_sum2 *= 2;
00476                         square_sum2 += y_data[0] * double(y_data[0]);
00477                         if(ny%2 == 0) {
00478                                 int ii = (ny/2  + iz * ny)* lsd2;
00479                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00480                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00481                         }
00482                         if(nx%2 == 0) {
00483                                 int ii = lsd2 - 2 + (0  + iz * ny)* lsd2;
00484                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00485                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00486                                 if(ny%2 == 0) {
00487                                         int ii = lsd2 - 2 +(ny/2  + iz * ny)* lsd2;
00488                                         square_sum1 += x_data[ii] * double(x_data[ii]);
00489                                         square_sum2 += y_data[ii] * double(y_data[ii]);
00490                                 }
00491                         }
00492                 }
00493                 result /= sqrt(square_sum1*square_sum2);
00494                 } else  result /= ((float)nx*(float)ny*(float)nz*(float)nx*(float)ny*(float)nz);
00495 
00496                 } else { //This 3D code is incorrect, but it is the best I can do now 01/09/06 PAP
00497                 int ky, kz;
00498                 int ny2 = ny/2; int nz2 = nz/2;
00499                 for ( int iz = 0; iz <= nz-1; ++iz) {
00500                         if(iz>nz2) kz=iz-nz; else kz=iz;
00501                         for ( int iy = 0; iy <= ny-1; ++iy) {
00502                                 if(iy>ny2) ky=iy-ny; else ky=iy;
00503                                 for ( int ix = 0; ix <= lsd2-1; ++ix) {
00504                                         // Skip Friedel related values
00505                                         if(ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
00506                                                 size_t ii = ix + (iy  + iz * ny)* lsd2;
00507                                                 result += x_data[ii] * double(y_data[ii]);
00508                                         }
00509                                 }
00510                         }
00511                 }
00512                 if( normalize ) {
00513                 //  still incorrect
00514                 double square_sum1 = 0., square_sum2 = 0.;
00515                 int ky, kz;
00516                 int ny2 = ny/2; int nz2 = nz/2;
00517                 for ( int iz = 0; iz <= nz-1; ++iz) {
00518                         if(iz>nz2) kz=iz-nz; else kz=iz;
00519                         for ( int iy = 0; iy <= ny-1; ++iy) {
00520                                 if(iy>ny2) ky=iy-ny; else ky=iy;
00521                                 for ( int ix = 0; ix <= lsd2-1; ++ix) {
00522                                         // Skip Friedel related values
00523                                         if(ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
00524                                                 size_t ii = ix + (iy  + iz * ny)* lsd2;
00525                                                 square_sum1 += x_data[ii] * double(x_data[ii]);
00526                                                 square_sum2 += y_data[ii] * double(y_data[ii]);
00527                                         }
00528                                 }
00529                         }
00530                 }
00531                 result /= sqrt(square_sum1*square_sum2);
00532                 } else result /= ((float)nx*(float)ny*(float)nz*(float)nx*(float)ny*(float)nz/2);
00533                 }
00534         } else {
00535                 size_t totsize = image->get_xsize() * image->get_ysize() * image->get_zsize();
00536 
00537                 double square_sum1 = 0., square_sum2 = 0.;
00538 
00539                 if (params.has_key("mask")) {
00540                         EMData* mask;
00541                         mask = params["mask"];
00542                         const float *const dm = mask->get_const_data();
00543                         if (normalize) {
00544                                 for (size_t i = 0; i < totsize; i++) {
00545                                         if (dm[i] > 0.5) {
00546                                                 square_sum1 += x_data[i]*double(x_data[i]);
00547                                                 square_sum2 += y_data[i]*double(y_data[i]);
00548                                                 result += x_data[i]*double(y_data[i]);
00549                                         }
00550                                 }
00551                         } else {
00552                                 for (size_t i = 0; i < totsize; i++) {
00553                                         if (dm[i] > 0.5) {
00554                                                 result += x_data[i]*double(y_data[i]);
00555                                                 n++;
00556                                         }
00557                                 }
00558                         }
00559                 } else {
00560                         // this little bit of manual loop unrolling makes the dot product as fast as sqeuclidean with -O2
00561                         for (size_t i=0; i<totsize; i++) result+=x_data[i]*y_data[i];
00562 
00563                         if (normalize) {
00564                                 square_sum1 = image->get_attr("square_sum");
00565                                 square_sum2 = with->get_attr("square_sum");
00566                         } else n = totsize;
00567                 }
00568                 if (normalize) result /= (sqrt(square_sum1*square_sum2)); else result /= n;
00569         }
00570 
00571 
00572         EXITFUNC;
00573         return (float) (negative*result);
00574 }

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

Implements EMAN::Cmp.

Definition at line 280 of file cmp.h.

00281                 {
00282                         return "Dot product (default -1 * dot product)";
00283                 }

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 275 of file cmp.h.

00276                 {
00277                         return NAME;
00278                 }

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 290 of file cmp.h.

References EMAN::TypeDict::put().

00291                 {
00292                         TypeDict d;
00293                         d.put("negative", EMObject::INT, "If set, returns -1 * dot product. Set by default so smaller is better");
00294                         d.put("normalize", EMObject::INT, "If set, returns normalized dot product (cosine of the angle) -1.0 - 1.0.");
00295                         d.put("mask", EMObject::EMDATA, "image mask");
00296                         return d;
00297                 }

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

Definition at line 285 of file cmp.h.

00286                 {
00287                         return new DotCmp();
00288                 }


Member Data Documentation

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

Definition at line 46 of file cmp.cpp.


The documentation for this class was generated from the following files:
Generated on Thu Dec 9 13:47:18 2010 for EMAN2 by  doxygen 1.3.9.1