00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "cmp.h"
00037 #include "emdata.h"
00038 #include "ctf.h"
00039 #include "plugins/cmp_template.h"
00040
00041 using namespace EMAN;
00042
00043 const string CccCmp::NAME = "ccc";
00044 const string LodCmp::NAME = "lod";
00045 const string SqEuclideanCmp::NAME = "sqeuclidean";
00046 const string DotCmp::NAME = "dot";
00047 const string TomoCccCmp::NAME = "ccc.tomo";
00048 const string QuadMinDotCmp::NAME = "quadmindot";
00049 const string OptVarianceCmp::NAME = "optvariance";
00050 const string PhaseCmp::NAME = "phase";
00051 const string FRCCmp::NAME = "frc";
00052
00053 template <> Factory < Cmp >::Factory()
00054 {
00055 force_add<CccCmp>();
00056 force_add<LodCmp>();
00057 force_add<SqEuclideanCmp>();
00058 force_add<DotCmp>();
00059 force_add<TomoCccCmp>();
00060 force_add<QuadMinDotCmp>();
00061 force_add<OptVarianceCmp>();
00062 force_add<PhaseCmp>();
00063 force_add<FRCCmp>();
00064
00065 }
00066
00067 void Cmp::validate_input_args(const EMData * image, const EMData *with) const
00068 {
00069 if (!image) {
00070 throw NullPointerException("compared image");
00071 }
00072 if (!with) {
00073 throw NullPointerException("compare-with image");
00074 }
00075
00076 if (!EMUtil::is_same_size(image, with)) {
00077 throw ImageFormatException( "images not same size");
00078 }
00079
00080 float *d1 = image->get_data();
00081 if (!d1) {
00082 throw NullPointerException("image contains no data");
00083 }
00084
00085 float *d2 = with->get_data();
00086 if (!d2) {
00087 throw NullPointerException("compare-with image data");
00088 }
00089 }
00090
00091
00092 float CccCmp::cmp(EMData * image, EMData *with) const
00093 {
00094 ENTERFUNC;
00095 if (image->is_complex() || with->is_complex())
00096 throw ImageFormatException( "Complex images not supported by CMP::CccCmp");
00097 validate_input_args(image, with);
00098
00099 const float *const d1 = image->get_const_data();
00100 const float *const d2 = with->get_const_data();
00101
00102 float negative = (float)params.set_default("negative", 1);
00103 if (negative) negative=-1.0; else negative=1.0;
00104
00105 double avg1 = 0.0, var1 = 0.0, avg2 = 0.0, var2 = 0.0, ccc = 0.0;
00106 long n = 0;
00107 size_t totsize = image->get_xsize()*image->get_ysize()*image->get_zsize();
00108
00109 bool has_mask = false;
00110 EMData* mask = 0;
00111 if (params.has_key("mask")) {
00112 mask = params["mask"];
00113 if(mask!=0) {has_mask=true;}
00114 }
00115
00116 if (has_mask) {
00117 const float *const dm = mask->get_const_data();
00118 for (size_t i = 0; i < totsize; ++i) {
00119 if (dm[i] > 0.5) {
00120 avg1 += double(d1[i]);
00121 var1 += d1[i]*double(d1[i]);
00122 avg2 += double(d2[i]);
00123 var2 += d2[i]*double(d2[i]);
00124 ccc += d1[i]*double(d2[i]);
00125 n++;
00126 }
00127 }
00128 } else {
00129 for (size_t i = 0; i < totsize; ++i) {
00130 avg1 += double(d1[i]);
00131 var1 += d1[i]*double(d1[i]);
00132 avg2 += double(d2[i]);
00133 var2 += d2[i]*double(d2[i]);
00134 ccc += d1[i]*double(d2[i]);
00135 }
00136 n = totsize;
00137 }
00138
00139 avg1 /= double(n);
00140 var1 = var1/double(n) - avg1*avg1;
00141 avg2 /= double(n);
00142 var2 = var2/double(n) - avg2*avg2;
00143 ccc = ccc/double(n) - avg1*avg2;
00144 ccc /= sqrt(var1*var2);
00145 ccc *= negative;
00146 return static_cast<float>(ccc);
00147 EXITFUNC;
00148 }
00149
00150
00151
00152
00153 float LodCmp::cmp(EMData * image, EMData *with) const
00154 {
00155 ENTERFUNC;
00156 if (image->is_complex() || with->is_complex())
00157 throw ImageFormatException( "Complex images not yet supported by CMP::LodCmp");
00158 validate_input_args(image, with);
00159
00160 const float *const d1 = image->get_const_data();
00161 const float *const d2 = with->get_const_data();
00162
00163 float negative = (float)params.set_default("negative", 1);
00164 if (negative) negative=-1.0; else negative=1.0;
00165
00166 double avg1 = 0.0, sig1 = 0.0, avg2 = 0.0, sig2 = 0.0, lod = 0.0;
00167 long n = 0;
00168 size_t totsize = image->get_xsize()*image->get_ysize()*image->get_zsize();
00169 size_t i;
00170
00171 bool has_mask = false;
00172 EMData* mask = 0;
00173 if (params.has_key("mask")) {
00174 mask = params["mask"];
00175 if(mask!=0) {has_mask=true;}
00176 }
00177
00178 int normalize = 0;
00179 if (params.has_key("normalize")) {
00180 normalize = params["normalize"];
00181 }
00182
00183 if (normalize) {
00184 if (has_mask) {
00185 const float *const dm = mask->get_const_data();
00186 for (i = 0; i < totsize; ++i) {
00187 if (dm[i] > 0.5) {
00188 avg1 += double(d1[i]);
00189 avg2 += double(d2[i]);
00190 n++;
00191 }
00192 }
00193 } else {
00194 for (i = 0; i < totsize; ++i) {
00195 avg1 += double(d1[i]);
00196 avg2 += double(d2[i]);
00197 }
00198 n = totsize;
00199 }
00200
00201 avg1 /= double(n);
00202 avg2 /= double(n);
00203
00204 if (has_mask) {
00205 const float *const dm = mask->get_const_data();
00206 for (i = 0; i < totsize; ++i) {
00207 if (dm[i] > 0.5) {
00208 sig1 += fabs(double(d1[i])-avg1);
00209 sig2 += fabs(double(d2[i])-avg2);
00210 }
00211 }
00212 } else {
00213 for (i = 0; i < totsize; ++i) {
00214 sig1 += fabs(double(d1[i])-avg1);
00215 sig2 += fabs(double(d2[i])-avg2);
00216 }
00217 }
00218 } else {
00219 avg1 = 0.0; avg2 = 0.0;
00220 sig1 = 1.0; sig2 = 1.0;
00221 }
00222
00223 if (has_mask) {
00224 const float *const dm = mask->get_const_data();
00225 for (i = 0; i < totsize; ++i) {
00226 if (dm[i] > 0.5) {
00227 lod += fabs((double(d1[i])-avg1)/sig1 - (double(d2[i])-avg2)/sig2);
00228 }
00229 }
00230 } else {
00231 for (i = 0; i < totsize; ++i) {
00232 lod += fabs((double(d1[i])-avg1)/sig1 - (double(d2[i])-avg2)/sig2);
00233 }
00234 }
00235
00236 lod *= (-0.5);
00237 lod *= negative;
00238 return static_cast<float>(lod);
00239 EXITFUNC;
00240 }
00241
00242
00243
00244 float SqEuclideanCmp::cmp(EMData *image,EMData * withorig ) const
00245 {
00246 ENTERFUNC;
00247 EMData *with = withorig;
00248 validate_input_args(image, with);
00249
00250 int zeromask = params.set_default("zeromask",0);
00251 int normto = params.set_default("normto",0);
00252
00253 if (normto) {
00254 if (zeromask) with = withorig->process("normalize.toimage",Dict("to",image));
00255 else with = withorig->process("normalize.toimage",Dict("to",image,"ignore_zero",0));
00256 with->set_attr("deleteme",1);
00257 if ((float)(with->get_attr("norm_mult"))<=0) {
00258 delete with;
00259 with=withorig;
00260 }
00261 }
00262
00263 const float *const y_data = with->get_const_data();
00264 const float *const x_data = image->get_const_data();
00265 double result = 0.;
00266 float n = 0.0f;
00267 if(image->is_complex() && with->is_complex()) {
00268
00269 int nx = with->get_xsize();
00270 int ny = with->get_ysize();
00271 int nz = with->get_zsize();
00272 nx = (nx - 2 + with->is_fftodd());
00273 int lsd2 = (nx + 2 - nx%2) ;
00274
00275 int ixb = 2*((nx+1)%2);
00276 int iyb = ny%2;
00277
00278 if(nz == 1) {
00279
00280 for ( int iz = 0; iz <= nz-1; iz++) {
00281 double part = 0.;
00282 for ( int iy = 0; iy <= ny-1; iy++) {
00283 for ( int ix = 2; ix <= lsd2 - 1 - ixb; ix++) {
00284 size_t ii = ix + (iy + iz * ny)* lsd2;
00285 part += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00286 }
00287 }
00288 for ( int iy = 1; iy <= ny/2-1 + iyb; iy++) {
00289 size_t ii = (iy + iz * ny)* lsd2;
00290 part += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00291 part += (x_data[ii+1] - y_data[ii+1])*double(x_data[ii+1] - y_data[ii+1]);
00292 }
00293 if(nx%2 == 0) {
00294 for ( int iy = 1; iy <= ny/2-1 + iyb; iy++) {
00295 size_t ii = lsd2 - 2 + (iy + iz * ny)* lsd2;
00296 part += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00297 part += (x_data[ii+1] - y_data[ii+1])*double(x_data[ii+1] - y_data[ii+1]);
00298 }
00299
00300 }
00301 part *= 2;
00302 part += (x_data[0] - y_data[0])*double(x_data[0] - y_data[0]);
00303 if(ny%2 == 0) {
00304 int ii = (ny/2 + iz * ny)* lsd2;
00305 part += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00306 }
00307 if(nx%2 == 0) {
00308 int ii = lsd2 - 2 + (0 + iz * ny)* lsd2;
00309 part += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00310 if(ny%2 == 0) {
00311 int ii = lsd2 - 2 +(ny/2 + iz * ny)* lsd2;
00312 part += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00313 }
00314 }
00315 result += part;
00316 }
00317 n = (float)nx*(float)ny*(float)nz*(float)nx*(float)ny*(float)nz;
00318
00319 }else{
00320 int ky, kz;
00321 int ny2 = ny/2; int nz2 = nz/2;
00322 for ( int iz = 0; iz <= nz-1; iz++) {
00323 if(iz>nz2) kz=iz-nz; else kz=iz;
00324 for ( int iy = 0; iy <= ny-1; iy++) {
00325 if(iy>ny2) ky=iy-ny; else ky=iy;
00326 for ( int ix = 0; ix <= lsd2-1; ix++) {
00327
00328 if(ix>0 || (kz>=0 && (ky>=0 || kz!=0))) {
00329 size_t ii = ix + (iy + iz * ny)* lsd2;
00330 result += (x_data[ii] - y_data[ii])*double(x_data[ii] - y_data[ii]);
00331 }
00332 }
00333 }
00334 }
00335 n = ((float)nx*(float)ny*(float)nz*(float)nx*(float)ny*(float)nz)/2.0f;
00336 }
00337 } else {
00338 size_t totsize = image->get_xsize()*image->get_ysize()*image->get_zsize();
00339 if (params.has_key("mask")) {
00340 EMData* mask;
00341 mask = params["mask"];
00342 const float *const dm = mask->get_const_data();
00343 for (size_t i = 0; i < totsize; i++) {
00344 if (dm[i] > 0.5) {
00345 double temp = x_data[i]- y_data[i];
00346 result += temp*temp;
00347 n++;
00348 }
00349 }
00350 }
00351 else if (zeromask) {
00352 n=0;
00353 for (size_t i = 0; i < totsize; i++) {
00354 if (x_data[i]==0 || y_data[i]==0) continue;
00355 double temp = x_data[i]- y_data[i];
00356 result += temp*temp;
00357 n++;
00358 }
00359
00360 }
00361 else {
00362 for (size_t i = 0; i < totsize; i++) {
00363 double temp = x_data[i]- y_data[i];
00364 result += temp*temp;
00365 }
00366 n = (float)totsize;
00367 }
00368 }
00369 result/=n;
00370
00371 EXITFUNC;
00372 if (with->has_attr("deleteme")) delete with;
00373 float ret = (float)result;
00374 if (!Util::goodf(&ret)) return FLT_MAX;
00375 return ret;
00376 }
00377
00378
00379
00380
00381 float DotCmp::cmp(EMData* image, EMData* with) const
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
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());
00401 int lsd2 = (nx + 2 - nx%2) ;
00402
00403 int ixb = 2*((nx+1)%2);
00404 int iyb = ny%2;
00405
00406 if(nz == 1) {
00407
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
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 {
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
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
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
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
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 }
00575
00576
00577
00578
00579
00580
00581
00582 float TomoCccCmp::cmp(EMData * image, EMData *with) const
00583 {
00584 ENTERFUNC;
00585 EMData* ccf = params.set_default("ccf",(EMData*) NULL);
00586 bool ccf_ownership = false;
00587 if (!ccf) {
00588 ccf = image->calc_ccf(with);
00589 ccf_ownership = true;
00590 }
00591 bool norm = params.set_default("norm",true);
00592 bool zeroori = params.set_default("zeroori",false);
00593
00594 if (norm) ccf->process_inplace("normalize");
00595
00596 IntPoint point;
00597 if (zeroori) {
00598 point[0] = 0; point[1] = 0; point[2] = 0;
00599 } else {
00600 int searchx = params.set_default("searchx",-1);
00601 int searchy = params.set_default("searchy",-1);
00602 int searchz = params.set_default("searchz",-1);
00603 point = ccf->calc_max_location_wrap(searchx,searchy,searchz);
00604 }
00605
00606
00607 float tx = (float)point[0]; float ty = (float)point[1]; float tz = (float)point[2];
00608 image->set_attr("tx", tx);
00609 image->set_attr("ty", ty);
00610 image->set_attr("tz", tz);
00611
00612 float best_score = ccf->get_value_at_wrap(tx,ty,tz);
00613 if (ccf_ownership) delete ccf; ccf = 0;
00614
00615 return -best_score;
00616
00617 }
00618
00619
00620
00621 float QuadMinDotCmp::cmp(EMData * image, EMData *with) const
00622 {
00623 ENTERFUNC;
00624 validate_input_args(image, with);
00625
00626 if (image->get_zsize()!=1) throw InvalidValueException(0, "QuadMinDotCmp supports 2D only");
00627
00628 int nx=image->get_xsize();
00629 int ny=image->get_ysize();
00630
00631 int normalize = params.set_default("normalize", 0);
00632 float negative = (float)params.set_default("negative", 1);
00633
00634 if (negative) negative=-1.0; else negative=1.0;
00635
00636 double result[4] = { 0,0,0,0 }, sq1[4] = { 0,0,0,0 }, sq2[4] = { 0,0,0,0 } ;
00637
00638 vector<int> image_saved_offsets = image->get_array_offsets();
00639 vector<int> with_saved_offsets = with->get_array_offsets();
00640 image->set_array_offsets(-nx/2,-ny/2);
00641 with->set_array_offsets(-nx/2,-ny/2);
00642 int i,x,y;
00643 for (y=-ny/2; y<ny/2; y++) {
00644 for (x=-nx/2; x<nx/2; x++) {
00645 int quad=(x<0?0:1) + (y<0?0:2);
00646 result[quad]+=(*image)(x,y)*(*with)(x,y);
00647 if (normalize) {
00648 sq1[quad]+=(*image)(x,y)*(*image)(x,y);
00649 sq2[quad]+=(*with)(x,y)*(*with)(x,y);
00650 }
00651 }
00652 }
00653 image->set_array_offsets(image_saved_offsets);
00654 with->set_array_offsets(with_saved_offsets);
00655
00656 if (normalize) {
00657 for (i=0; i<4; i++) result[i]/=sqrt(sq1[i]*sq2[i]);
00658 } else {
00659 for (i=0; i<4; i++) result[i]/=nx*ny/4;
00660 }
00661
00662 float worst=static_cast<float>(result[0]);
00663 for (i=1; i<4; i++) if (static_cast<float>(result[i])<worst) worst=static_cast<float>(result[i]);
00664
00665 EXITFUNC;
00666 return (float) (negative*worst);
00667 }
00668
00669 float OptVarianceCmp::cmp(EMData * image, EMData *with) const
00670 {
00671 ENTERFUNC;
00672 validate_input_args(image, with);
00673
00674 int keepzero = params.set_default("keepzero", 1);
00675 int invert = params.set_default("invert",0);
00676 int matchfilt = params.set_default("matchfilt",1);
00677 int matchamp = params.set_default("matchamp",0);
00678 int radweight = params.set_default("radweight",0);
00679 int dbug = params.set_default("debug",0);
00680
00681 size_t size = image->get_xsize() * image->get_ysize() * image->get_zsize();
00682
00683
00684 EMData *with2=NULL;
00685 if (matchfilt) {
00686 EMData *a = image->do_fft();
00687 EMData *b = with->do_fft();
00688
00689 vector <float> rfa=a->calc_radial_dist(a->get_ysize()/2,0.0f,1.0f,1);
00690 vector <float> rfb=b->calc_radial_dist(b->get_ysize()/2,0.0f,1.0f,1);
00691
00692 float avg=0;
00693 for (size_t i=0; i<a->get_ysize()/2.0f; i++) {
00694 rfa[i]=(rfb[i]==0?0.0f:(rfa[i]/rfb[i]));
00695 avg+=rfa[i];
00696 }
00697
00698 avg/=a->get_ysize()/2.0f;
00699 for (size_t i=0; i<a->get_ysize()/2.0f; i++) {
00700 if (rfa[i]>avg*10.0) rfa[i]=10.0;
00701 }
00702 rfa[0]=0.0;
00703
00704 if (dbug) b->write_image("a.hdf",-1);
00705
00706 b->apply_radial_func(0.0f,1.0f/a->get_ysize(),rfa);
00707 with2=b->do_ift();
00708
00709 if (dbug) b->write_image("a.hdf",-1);
00710 if (dbug) a->write_image("a.hdf",-1);
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 delete a;
00724 delete b;
00725
00726 if (dbug) {
00727 with2->write_image("a.hdf",-1);
00728 image->write_image("a.hdf",-1);
00729 }
00730
00731
00732
00733 }
00734
00735
00736
00737 if (matchamp) {
00738 EMData *a = image->do_fft();
00739 EMData *b = with->do_fft();
00740 size_t size2 = a->get_xsize() * a->get_ysize() * a->get_zsize();
00741
00742 a->ri2ap();
00743 b->ri2ap();
00744
00745 const float *const ad=a->get_const_data();
00746 float * bd=b->get_data();
00747
00748 for (size_t i=0; i<size2; i+=2) bd[i]=ad[i];
00749 b->update();
00750
00751 b->ap2ri();
00752 with2=b->do_ift();
00753
00754 delete a;
00755 delete b;
00756 }
00757
00758 const float * x_data;
00759 if (with2) x_data=with2->get_const_data();
00760 else x_data = with->get_const_data();
00761 const float *const y_data = image->get_const_data();
00762
00763 size_t nx = image->get_xsize();
00764 float m = 0;
00765 float b = 0;
00766
00767
00768
00769 if (dbug) {
00770 FILE *out=fopen("dbug.optvar.txt","w");
00771 if (out) {
00772 for (size_t i=0; i<size; i++) {
00773 if ( !keepzero || (x_data[i] && y_data[i])) fprintf(out,"%g\t%g\n",x_data[i],y_data[i]);
00774 }
00775 fclose(out);
00776 }
00777 }
00778
00779
00780 Util::calc_least_square_fit(size, x_data, y_data, &m, &b, keepzero);
00781 if (m == 0) {
00782 m = FLT_MIN;
00783 }
00784 b = -b / m;
00785 m = 1.0f / m;
00786
00787
00788
00789
00790
00791
00792
00793
00794 double result = 0;
00795 int count = 0;
00796
00797 if (radweight) {
00798 if (image->get_zsize()!=1) throw ImageDimensionException("radweight option is 2D only");
00799 if (keepzero) {
00800 for (size_t i = 0,y=0; i < size; y++) {
00801 for (size_t x=0; x<nx; i++,x++) {
00802 if (y_data[i] && x_data[i]) {
00803 #ifdef _WIN32
00804 if (invert) result += Util::square(x_data[i] - (y_data[i]-b)/m)*(_hypot((float)x,(float)y)+nx/4.0);
00805 else result += Util::square((x_data[i] * m) + b - y_data[i])*(_hypot((float)x,(float)y)+nx/4.0);
00806 #else
00807 if (invert) result += Util::square(x_data[i] - (y_data[i]-b)/m)*(hypot((float)x,(float)y)+nx/4.0);
00808 else result += Util::square((x_data[i] * m) + b - y_data[i])*(hypot((float)x,(float)y)+nx/4.0);
00809 #endif
00810 count++;
00811 }
00812 }
00813 }
00814 result/=count;
00815 }
00816 else {
00817 for (size_t i = 0,y=0; i < size; y++) {
00818 for (size_t x=0; x<nx; i++,x++) {
00819 #ifdef _WIN32
00820 if (invert) result += Util::square(x_data[i] - (y_data[i]-b)/m)*(_hypot((float)x,(float)y)+nx/4.0);
00821 else result += Util::square((x_data[i] * m) + b - y_data[i])*(_hypot((float)x,(float)y)+nx/4.0);
00822 #else
00823 if (invert) result += Util::square(x_data[i] - (y_data[i]-b)/m)*(hypot((float)x,(float)y)+nx/4.0);
00824 else result += Util::square((x_data[i] * m) + b - y_data[i])*(hypot((float)x,(float)y)+nx/4.0);
00825 #endif
00826 }
00827 }
00828 result = result / size;
00829 }
00830 }
00831 else {
00832 if (keepzero) {
00833 for (size_t i = 0; i < size; i++) {
00834 if (y_data[i] && x_data[i]) {
00835 if (invert) result += Util::square(x_data[i] - (y_data[i]-b)/m);
00836 else result += Util::square((x_data[i] * m) + b - y_data[i]);
00837 count++;
00838 }
00839 }
00840 result/=count;
00841 }
00842 else {
00843 for (size_t i = 0; i < size; i++) {
00844 if (invert) result += Util::square(x_data[i] - (y_data[i]-b)/m);
00845 else result += Util::square((x_data[i] * m) + b - y_data[i]);
00846 }
00847 result = result / size;
00848 }
00849 }
00850 scale = m;
00851 shift = b;
00852
00853 image->set_attr("ovcmp_m",m);
00854 image->set_attr("ovcmp_b",b);
00855 if (with2) delete with2;
00856 EXITFUNC;
00857
00858 #if 0
00859 return (1 - result);
00860 #endif
00861
00862 return static_cast<float>(result);
00863 }
00864
00865 float PhaseCmp::cmp(EMData * image, EMData *with) const
00866 {
00867 ENTERFUNC;
00868
00869 int snrweight = params.set_default("snrweight", 0);
00870 int snrfn = params.set_default("snrfn",0);
00871 int ampweight = params.set_default("ampweight",0);
00872 int zeromask = params.set_default("zeromask",0);
00873 float minres = params.set_default("minres",500.0f);
00874 float maxres = params.set_default("maxres",2.0f);
00875
00876 if (snrweight && snrfn) throw InvalidCallException("SNR weight and SNRfn cannot both be set in the phase comparator");
00877
00878 #ifdef EMAN2_USING_CUDA
00879 if (image->gpu_operation_preferred()) {
00880
00881 EXITFUNC;
00882 return cuda_cmp(image,with);
00883 }
00884 #endif
00885
00886 EMData *image_fft = NULL;
00887 EMData *with_fft = NULL;
00888
00889 int ny = image->get_ysize();
00890
00891 int np = 0;
00892 vector<float> snr;
00893
00894
00895 if (snrweight) {
00896 Ctf *ctf = NULL;
00897 if (!image->has_attr("ctf")) {
00898 if (!with->has_attr("ctf")) throw InvalidCallException("SNR weight with no CTF parameters");
00899 ctf=with->get_attr("ctf");
00900 }
00901 else ctf=image->get_attr("ctf");
00902
00903 float ds=1.0f/(ctf->apix*ny);
00904 snr=ctf->compute_1d(ny,ds,Ctf::CTF_SNR);
00905 if(ctf) {delete ctf; ctf=0;}
00906 np=snr.size();
00907 }
00908
00909 else if (snrfn==1) {
00910 np=ny/2;
00911 snr.resize(np);
00912
00913 for (int i = 0; i < np; i++) {
00914 float x2 = 10.0f*i/np;
00915 snr[i] = x2 * exp(-x2);
00916 }
00917 }
00918
00919 else {
00920 np=ny/2;
00921 snr.resize(np);
00922
00923 for (int i = 0; i < np; i++) snr[i]=1.0;
00924 }
00925
00926
00927 float pmin,pmax;
00928 if (minres>0) pmin=((float)image->get_attr("apix_x")*image->get_ysize())/minres;
00929 else pmin=0;
00930 if (maxres>0) pmax=((float)image->get_attr("apix_x")*image->get_ysize())/maxres;
00931 else pmax=0;
00932
00933
00934
00935
00936 for (int i = 0; i < np; i++) {
00937 if (pmin>0) snr[i]*=(tanh(5.0f*(i-pmin)/pmin)+1.0f)/2.0f;
00938 if (pmax>0) snr[i]*=(1.0f-tanh(i-pmax))/2.0f;
00939
00940 }
00941
00942 if (zeromask) {
00943 image_fft=image->copy();
00944 with_fft=with->copy();
00945
00946 if (image_fft->is_complex()) image_fft->do_ift_inplace();
00947 if (with_fft->is_complex()) with_fft->do_ift_inplace();
00948
00949 int sz=image_fft->get_xsize()*image_fft->get_ysize()*image_fft->get_zsize();
00950 float *d1=image_fft->get_data();
00951 float *d2=with_fft->get_data();
00952
00953 for (int i=0; i<sz; i++) {
00954 if (d1[i]==0.0 || d2[i]==0.0) { d1[i]=0.0; d2[i]=0.0; }
00955 }
00956
00957 image_fft->update();
00958 with_fft->update();
00959 image_fft->do_fft_inplace();
00960 with_fft->do_fft_inplace();
00961 image_fft->set_attr("free_me",1);
00962 with_fft->set_attr("free_me",1);
00963 }
00964 else {
00965 if (image->is_complex()) image_fft=image;
00966 else {
00967 image_fft=image->do_fft();
00968 image_fft->set_attr("free_me",1);
00969 }
00970
00971 if (with->is_complex()) with_fft=with;
00972 else {
00973 with_fft=with->do_fft();
00974 with_fft->set_attr("free_me",1);
00975 }
00976 }
00977
00978
00979
00980 const float *const image_fft_data = image_fft->get_const_data();
00981 const float *const with_fft_data = with_fft->get_const_data();
00982 double sum = 0;
00983 double norm = FLT_MIN;
00984 size_t i = 0;
00985
00986 ny=image_fft->get_ysize();
00987 int nz=image_fft->get_zsize();
00988 int nx2=image_fft->get_xsize()/2;
00989 int ny2=image_fft->get_ysize()/2;
00990
00991
00992
00993 if (np==0) {
00994 for (int z = 0; z < nz; z++){
00995 for (int y = 0; y < ny; y++) {
00996 for (int x = 0; x < nx2; x ++) {
00997 float a;
00998 if (ampweight) a= (float)hypot(with_fft_data[i],with_fft_data[i+1]);
00999 else a=1.0f;
01000 sum += Util::angle_err_ri(image_fft_data[i],image_fft_data[i+1],with_fft_data[i],with_fft_data[i+1]) * a;
01001 norm += a;
01002 i += 2;
01003 }
01004 }
01005 }
01006
01007 }
01008 else if (nz==1) {
01009 for (int y = 0; y < ny; y++) {
01010 for (int x = 0; x < nx2; x ++) {
01011 int r=Util::hypot_fast_int(x,y>ny/2?ny-y:y);
01012 if (r>=ny2) { i+=2; continue; }
01013
01014 float a;
01015 if (ampweight) a= (float)hypot(with_fft_data[i],with_fft_data[i+1]);
01016 else a=1.0f;
01017 a*=snr[r];
01018 sum += Util::angle_err_ri(image_fft_data[i],image_fft_data[i+1],with_fft_data[i],with_fft_data[i+1]) * a;
01019 norm += a;
01020 i += 2;
01021 }
01022 }
01023 }
01024 else {
01025 for (int z = 0; z < nz; z++){
01026 for (int y = 0; y < ny; y++) {
01027 for (int x = 0; x < nx2; x ++) {
01028 int r=(int)Util::hypot3(x,y>ny/2?ny-y:y,z>nz/2?nz-z:z);
01029 if (r>=ny2) { i+=2; continue; }
01030
01031 float a;
01032 if (ampweight) a= (float)hypot(with_fft_data[i],with_fft_data[i+1]);
01033 else a=1.0f;
01034 a*=snr[r];
01035 sum += Util::angle_err_ri(image_fft_data[i],image_fft_data[i+1],with_fft_data[i],with_fft_data[i+1]) * a;
01036 norm += a;
01037 i += 2;
01038 }
01039 }
01040 }
01041
01042 }
01043
01044 EXITFUNC;
01045
01046 if( image_fft->has_attr("free_me") )
01047 {
01048 delete image_fft;
01049 image_fft = 0;
01050 }
01051 if( with_fft->has_attr("free_me") )
01052 {
01053 delete with_fft;
01054 with_fft = 0;
01055 }
01056 #if 0
01057 return (1.0f - sum / norm);
01058 #endif
01059 return (float)(sum / norm);
01060 }
01061
01062 #ifdef EMAN2_USING_CUDA
01063 #include "cuda/cuda_cmp.h"
01064 float PhaseCmp::cuda_cmp(EMData * image, EMData *with) const
01065 {
01066 ENTERFUNC;
01067 validate_input_args(image, with);
01068
01069 typedef vector<EMData*> EMDatas;
01070 static EMDatas hist_pyramid;
01071 static EMDatas norm_pyramid;
01072 static EMData weighting;
01073 static int image_size = 0;
01074
01075 int size;
01076 EMData::CudaDataLock imagelock(image);
01077 EMData::CudaDataLock withlock(with);
01078
01079 if (image->is_complex()) {
01080 size = image->get_xsize();
01081 } else {
01082 int nx = image->get_xsize()+2;
01083 nx -= nx%2;
01084 size = nx*image->get_ysize()*image->get_zsize();
01085 }
01086 if (size != image_size) {
01087 for(unsigned int i =0; i < hist_pyramid.size(); ++i) {
01088 delete hist_pyramid[i];
01089 delete norm_pyramid[i];
01090 }
01091 hist_pyramid.clear();
01092 norm_pyramid.clear();
01093 int s = size;
01094 if (s < 1) throw UnexpectedBehaviorException("The image is 0 size");
01095 int p2 = 1;
01096 while ( s != 1 ) {
01097 s /= 2;
01098 p2 *= 2;
01099 }
01100 if ( p2 != size ) {
01101 p2 *= 2;
01102 s = p2;
01103 }
01104 if (s != 1) s /= 2;
01105 while (true) {
01106 EMData* h = new EMData();
01107 h->set_size_cuda(s); h->to_value(0.0);
01108 hist_pyramid.push_back(h);
01109 EMData* n = new EMData();
01110 n->set_size_cuda(s); n->to_value(0.0);
01111 norm_pyramid.push_back(n);
01112 if ( s == 1) break;
01113 s /= 2;
01114 }
01115 int nx = image->get_xsize()+2;
01116 nx -= nx%2;
01117 int ny = image->get_ysize();
01118 int nz = image->get_zsize();
01119 weighting.set_size_cuda(nx,ny,nz);
01120
01121 weighting.set_size_cuda(nx/2,ny,nz);
01122 float np = (int) ceil(Ctf::CTFOS * sqrt(2.0f) * ny / 2) + 2;
01123 EMDataForCuda tmp = weighting.get_data_struct_for_cuda();
01124 calc_phase_weights_cuda(&tmp,np);
01125
01126 image_size = size;
01127 }
01128
01129 EMDataForCuda hist[hist_pyramid.size()];
01130 EMDataForCuda norm[hist_pyramid.size()];
01131
01132 EMDataForCuda wt = weighting.get_data_struct_for_cuda();
01133 EMData::CudaDataLock lock1(&weighting);
01134 for(unsigned int i = 0; i < hist_pyramid.size(); ++i ) {
01135 hist[i] = hist_pyramid[i]->get_data_struct_for_cuda();
01136 hist_pyramid[i]->cuda_lock();
01137 norm[i] = norm_pyramid[i]->get_data_struct_for_cuda();
01138 norm_pyramid[i]->cuda_lock();
01139 }
01140
01141 EMData *image_fft = image->do_fft_cuda();
01142 EMDataForCuda left = image_fft->get_data_struct_for_cuda();
01143 EMData::CudaDataLock lock2(image_fft);
01144 EMData *with_fft = with->do_fft_cuda();
01145 EMDataForCuda right = with_fft->get_data_struct_for_cuda();
01146 EMData::CudaDataLock lock3(image_fft);
01147
01148 mean_phase_error_cuda(&left,&right,&wt,hist,norm,hist_pyramid.size());
01149 float result;
01150 float* gpu_result = hist_pyramid[hist_pyramid.size()-1]->get_cuda_data();
01151 cudaError_t error = cudaMemcpy(&result,gpu_result,sizeof(float),cudaMemcpyDeviceToHost);
01152 if ( error != cudaSuccess) throw UnexpectedBehaviorException( "CudaMemcpy (host to device) in the phase comparator failed:" + string(cudaGetErrorString(error)));
01153
01154 delete image_fft; image_fft=0;
01155 delete with_fft; with_fft=0;
01156
01157 for(unsigned int i = 0; i < hist_pyramid.size(); ++i ) {
01158
01159
01160 hist_pyramid[i]->cuda_unlock();
01161 norm_pyramid[i]->cuda_unlock();
01162 }
01163
01164 EXITFUNC;
01165 return result;
01166
01167 }
01168
01169 #endif // EMAN2_USING_CUDA
01170
01171
01172 float FRCCmp::cmp(EMData * image, EMData * with) const
01173 {
01174 ENTERFUNC;
01175 validate_input_args(image, with);
01176
01177 int snrweight = params.set_default("snrweight", 0);
01178 int ampweight = params.set_default("ampweight", 0);
01179 int sweight = params.set_default("sweight", 1);
01180 int nweight = params.set_default("nweight", 0);
01181 int zeromask = params.set_default("zeromask",0);
01182 float minres = params.set_default("minres",500.0f);
01183 float maxres = params.set_default("maxres",2.0f);
01184
01185 if (zeromask) {
01186 image=image->copy();
01187 with=with->copy();
01188
01189 int sz=image->get_xsize()*image->get_ysize()*image->get_zsize();
01190 float *d1=image->get_data();
01191 float *d2=with->get_data();
01192
01193 for (int i=0; i<sz; i++) {
01194 if (d1[i]==0.0 || d2[i]==0.0) { d1[i]=0.0; d2[i]=0.0; }
01195 }
01196
01197 image->update();
01198 with->update();
01199 image->do_fft_inplace();
01200 with->do_fft_inplace();
01201 image->set_attr("free_me",1);
01202 with->set_attr("free_me",1);
01203 }
01204
01205
01206 if (!image->is_complex()) {
01207 image=image->do_fft();
01208 image->set_attr("free_me",1);
01209 }
01210 if (!with->is_complex()) {
01211 with=with->do_fft();
01212 with->set_attr("free_me",1);
01213 }
01214
01215 static vector < float >default_snr;
01216
01217
01218
01219
01220
01221
01222 int ny = image->get_ysize();
01223 int ny2=ny/2+1;
01224
01225 vector < float >fsc;
01226
01227
01228
01229 fsc = image->calc_fourier_shell_correlation(with,1);
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 vector<float> snr;
01265 if (snrweight) {
01266 Ctf *ctf = NULL;
01267 if (!image->has_attr("ctf")) {
01268 if (!with->has_attr("ctf")) throw InvalidCallException("SNR weight with no CTF parameters");
01269 ctf=with->get_attr("ctf");
01270 }
01271 else ctf=image->get_attr("ctf");
01272
01273 float ds=1.0f/(ctf->apix*ny);
01274 snr=ctf->compute_1d(ny,ds,Ctf::CTF_SNR);
01275 if(ctf) {delete ctf; ctf=0;}
01276 }
01277
01278 vector<float> amp;
01279 if (ampweight) amp=image->calc_radial_dist(ny/2,0,1,0);
01280
01281
01282 float pmin,pmax;
01283 if (minres>0) pmin=((float)image->get_attr("apix_x")*image->get_ysize())/minres;
01284 else pmin=0;
01285 if (maxres>0) pmax=((float)image->get_attr("apix_x")*image->get_ysize())/maxres;
01286 else pmax=0;
01287
01288 double sum=0.0, norm=0.0;
01289
01290 for (int i=0; i<ny/2; i++) {
01291 double weight=1.0;
01292 if (sweight) weight*=fsc[(ny2)*2+i];
01293 if (ampweight) weight*=amp[i];
01294 if (snrweight) weight*=snr[i];
01295
01296
01297
01298
01299
01300 if (pmin>0) weight*=(tanh(5.0*(i-pmin)/pmin)+1.0)/2.0;
01301 if (pmax>0) weight*=(1.0-tanh(i-pmax))/2.0;
01302
01303 sum+=weight*fsc[ny2+i];
01304 norm+=weight;
01305
01306 }
01307
01308
01309 sum/=norm;
01310 if (nweight && with->get_attr_default("ptcl_repr",0) && sum>=0 && sum<1.0) {
01311 sum=sum/(1.0-sum);
01312 sum/=(float)with->get_attr_default("ptcl_repr",0);
01313 sum=sum/(1.0+sum);
01314 }
01315
01316 if (image->has_attr("free_me")) delete image;
01317 if (with->has_attr("free_me")) delete with;
01318
01319 EXITFUNC;
01320
01321
01322 if (!Util::goodf(&sum)) sum=-3.0e38;
01323
01324
01325
01326 return (float)-sum;
01327 }
01328
01329 void EMAN::dump_cmps()
01330 {
01331 dump_factory < Cmp > ();
01332 }
01333
01334 map<string, vector<string> > EMAN::dump_cmps_list()
01335 {
01336 return dump_factory_list < Cmp > ();
01337 }
01338
01339