| Bsoft 2.0.5 Bernard's software package

Bimage_align.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10
11 // Declaration of global variables
12 extern int verbose; // Level of output to the screen
13
29 Bimage* Bimage::align_progressive(long nref, Bimage* pmask,
30 double hi_res, double lo_res, double shift_limit,
31 fft_plan planf, fft_plan planb)
32 {
33 if ( nref < 0 || nref >= n ) nref = 0;
34
35 long i, nn;
36 double cc(0), shift_avg(0), cc_avg(0);
37 Vector3<double> shift, shift_prev;
38 Bimage* pref = extract(nref);
39 Bimage* p1;
40
41 if ( verbose ) {
42 cout << "Progressive alignment:" << endl;
43 cout << "Image\tShift\t\t\tCC" << endl;
44 }
45
46 for ( nn=nref+1, i=1; i<n; nn++, i++ ) {
47 if ( nn >= n ) nn = 0;
48 p1 = extract(nn);
49 shift = p1->find_shift(pref, pmask, hi_res, lo_res, shift_limit, 0, 1, planf, planb, cc);
50 image[nn].origin(pref->image->origin()+shift);
51 image[nn].FOM(cc);
52 shift = -shift;
53 p1->shift_wrap(shift);
54 pref->add(p1);
55 delete p1;
56 // shift_avg += shift.length();
57 cc_avg += cc;
58 shift_prev = shift;
59 if ( verbose )
60 cout << nn+1 << tab << shift << tab << cc << endl;
61 }
62
63 for ( nn=1; nn<n; nn++ ) {
64 shift = image[nn].origin() - image[nn-1].origin();
65 shift_avg += shift.length();
66 }
67
68 shift_avg /= n-1;
69 cc_avg /= n-1;
70 pref->show_scale(shift_avg);
71 pref->image->FOM(cc_avg);
72
73 if ( verbose ) {
74 cout << "Shift average: " << shift_avg << endl;
75 cout << "CC average: " << cc_avg << endl;
76 }
77
78 return pref;
79 }
80
81 Vector3<double> Bimage::find_shift_in_transform(long nn, Bimage* pref, double shift_limit)
82 {
83 Bimage* p1 = extract(nn);
84 cout << "origin = " << p1->image->origin() << endl;
85
86 // long h, k;
87 // double cc(0), ccmax(0);
88 // Vector3<double> shift, bestshift;
89
90 p1->complex_conjugate_product(pref);
91 /*
92 for ( k=-1; k<2; ++k ) {
93 shift[1] = k;
94 for ( h=-1; h<2; ++h ) {
95 shift[0] = h;
96 cc = p1->correlation_coefficient(shift);
97 if ( ccmax < cc ) {
98 ccmax = cc;
99 bestshift = shift;
100 }
101 }
102 }
103 */
104 p1->fft(FFTW_BACKWARD, 0);
105
106 p1->complex_to_real();
107
108 p1->find_peak(shift_limit, 0);
109 cout << "origin = " << p1->image->origin() << endl;
110
111 p1->refine_peak();
112
113 Vector3<double> shift = p1->image->origin();
114
115 image[nn].FOM(p1->image->FOM());
116
117 image[nn].origin(pref->image->origin()-shift);
118 // image[nn].FOM(cc);
119
120 cout << "shift = " << shift << endl;
121 cout << "fom = " << p1->image->FOM() << endl;
122
123 delete p1;
124
125 return shift;
126 }
127
138 Bimage* Bimage::align_progressive_fast(long nref, double shift_limit)
139 {
140 if ( nref < 0 || nref >= n ) nref = 0;
141
142 long i, nn;
143 double shift_avg(0), cc_avg(0);
144 Vector3<double> shift, shift_prev;
145 Bimage* pref = extract(nref);
146 Bimage* p1;
147
148 if ( verbose ) {
149 cout << "Progressive alignment:" << endl;
150 cout << "Image\tShift\t\t\tCC" << endl;
151 }
152
153 for ( nn=nref+1, i=1; i<n; nn++, i++ ) {
154 if ( nn >= n ) nn = 0;
155 shift = find_shift_in_transform(nn, pref, shift_limit);
156 p1 = extract(nn);
157 p1->phase_shift(shift);
158 pref->add(p1);
159 delete p1;
160 pref->fspace_normalize();
161 cc_avg += image[nn].FOM();
162 shift_prev = shift;
163 if ( verbose )
164 cout << nn+1 << tab << shift << tab << image[nn].FOM() << endl;
165 }
166
167 for ( nn=1; nn<n; nn++ ) {
168 shift = image[nn].origin() - image[nn-1].origin();
169 shift_avg += shift.length();
170 }
171
172 shift_avg /= n-1;
173 cc_avg /= n-1;
174 pref->show_scale(shift_avg);
175 pref->image->FOM(cc_avg);
176
177 if ( verbose ) {
178 cout << "Shift average: " << shift_avg << endl;
179 cout << "CC average: " << cc_avg << endl;
180 }
181
182 return pref;
183 }
184
203 JSvalue Bimage::align(long ref_num, Bimage* pmask,
204 double hi_res, double lo_res, double shift_limit,
205 double edge_width, double gauss_width, Vector3<long> bin)
206 {
207 if ( ref_num < 0 || ref_num >= n ) ref_num = 0;
208
209 change_type(Float);
210
211 origin(size()/2);
212
213 calculate_background();
214
215 Vector3<long> obin(bin[0], bin[1], bin[2]);
216
217 Bimage* pt = bin_copy(bin);
218
219 Vector3<double> edge_origin(edge_width, edge_width, 0);
220 Vector3<long> edge_size = pt->size() - (long) (2*edge_width);
221 edge_size = edge_size.max(1);
222
223 // cout << edge_size << tab << pt->image->background() << endl;
224
225 if ( edge_width > 0 )
226 pt->edge(0, edge_size, edge_origin, gauss_width, FILL_BACKGROUND);
227
228
229 // write_img("t.pif", this);
230 // exit(-1);
231
232 fft_plan planf = pt->fft_setup(FFTW_FORWARD, 0);
233 fft_plan planb = pt->fft_setup(FFTW_BACKWARD, 0);
234
235 Bimage* pref = pt->align_progressive(ref_num,
236 pmask, hi_res, lo_res, shift_limit, planf, planb);
237 double cc_avg(0), cc_avg_old(0), shift_avg, shift_avg_old(0);
238 shift_avg = pref->show_scale() * bin[0];
239 cc_avg = pref->image->FOM();
240 pref->origin(pref->size()/2);
241
242 // write_img("progaln.pif", pref);
243
244 long i, nn;
245 Bimage* p1;
246 Vector3<double>* sh = new Vector3<double>[pt->images()];
247
248 if ( verbose )
249 cout << "Iterative refinement:" << endl;
250 for ( i=1; i<=10 && fabs(shift_avg - shift_avg_old) > 0.01
251 && cc_avg > cc_avg_old; i++ ) {
252 pt->origin(pref->size()/2);
253
254 if ( verbose )
255 cout << "Iteration " << i << endl;
256 #ifdef HAVE_GCD
257 dispatch_apply(n, dispatch_get_global_queue(0, 0), ^(size_t nn){
258 sh[nn] = pt->find_shift(nn, pref, pmask, hi_res, lo_res, shift_limit, planf, planb);
259 });
260 #else
261 #pragma omp parallel for
262 for ( nn=0; nn<n; nn++ ) {
263 sh[nn] = pt->find_shift(nn, pref, pmask, hi_res, lo_res, shift_limit, planf, planb);
264 }
265 #endif
266
267 pref->clear();
268 pref->origin(pref->size()/2);
269
270 shift_avg_old = shift_avg;
271 cc_avg_old = cc_avg;
272
273 for ( nn=0; nn<n; nn++ ) sh[nn] = sh[ref_num] - sh[nn];
274
275 if ( verbose )
276 cout << "Image\tShift\t\t\tCC" << endl;
277 for ( cc_avg=0, shift_avg=0, nn=0; nn<n; nn++ ) {
278 p1 = pt->extract(nn);
279 p1->shift_wrap(sh[nn]);
280 pref->add(p1);
281 delete p1;
282 cc_avg += pt->image[nn].FOM();
283 sh[nn] *= obin;
284 if ( nn ) shift_avg += sh[nn].distance(sh[nn-1]);
285 if ( verbose )
286 cout << nn+1 << tab << sh[nn] << tab << pt->image[nn].FOM() << endl;
287 }
288
289 shift_avg /= n-1;
290 cc_avg /= n;
291
292 if ( verbose ) {
293 cout << "Shift average per frame: " << shift_avg << endl;
294 cout << "CC average: " << cc_avg << endl;
295 }
296 }
297
298 fft_destroy_plan(planf);
299 fft_destroy_plan(planb);
300
301 delete pref;
302
303 vector<double> vsh(3);
304 JSvalue job(JSobject);
305 JSvalue jsh(JSarray);
306
307 for ( nn=0; nn<n; nn++ ) {
308 vsh = {sh[nn][0], sh[nn][1], pt->image[nn].FOM()};
309 jsh.push_back(vsh);
310 }
311
312 job["shifts"] = jsh;
313 job["shift_average"] = shift_avg;
314 job["FOM"] = cc_avg;
315
316 if ( verbose )
317 cout << "Shifting original frames" << endl << endl;
318
319 fft();
320
321 #ifdef HAVE_GCD
322 dispatch_apply(n, dispatch_get_global_queue(0, 0), ^(size_t nn){
323 fspace_translate(nn, sh[nn]);
324 image[nn].FOM(pt->image[nn].FOM());
325 });
326 #else
327 #pragma omp parallel for
328 for ( nn=0; nn<n; nn++ ) {
329 fspace_translate(nn, sh[nn]);
330 image[nn].FOM(pt->image[nn].FOM());
331 }
332 #endif
333
334 fft_back();
335
336 delete pt;
337 delete[] sh;
338
339 return job;
340 }
341
342 #include "rwimg.h"
343
361 JSvalue Bimage::align_fast(long ref_num, Bimage* pmask,
362 double hi_res, double lo_res, double shift_limit,
363 double edge_width, double gauss_width)
364 {
365 if ( ref_num < 0 || ref_num >= n ) ref_num = 0;
366 if ( hi_res < 2*sampling()[0] ) hi_res = 2*sampling()[0];
367
368 change_type(Float);
369
370 origin(size()/2);
371
372 calculate_background();
373
374 Bimage* pt = copy();
375
376 Vector3<double> edge_origin(edge_width, edge_width, 0);
377 Vector3<long> edge_size = pt->size() - (long) (2*edge_width);
378 edge_size = edge_size.max(1);
379
380 // cout << edge_size << tab << pt->image->background() << endl;
381
382 if ( edge_width > 0 )
383 pt->edge(0, edge_size, edge_origin, gauss_width, FILL_BACKGROUND);
384
385 double scale(hi_res/(2*sampling()[0]));
386 Vector3<long> nusize(size()/scale);
387 nusize = nusize.max(1);
388 if ( nusize[0]%2 ) nusize[0]++;
389 if ( nusize[1]%2 ) nusize[1]++;
390 if ( z > 1 && nusize[2]%2 ) nusize[2]++;
391 scale = x/nusize[0];
392
393 pt->fft();
394
395 pt->zero_origin();
396
397 // pt->change_transform_size(nusize);
398 scale = 1;
399
400 cout << "new size = " << nusize << endl;
401 cout << "new sampling = " << pt->sampling() << endl;
402 cout << "new origin = " << pt->image->origin() << endl;
403
404 pt->fspace_bandpass(hi_res, lo_res, 0);
405
406 pt->fspace_normalize();
407
408 Bimage* pref = pt->align_progressive_fast(ref_num, shift_limit);
409
410 double cc_avg(0), cc_avg_old(0), shift_avg, shift_avg_old(0);
411 shift_avg = pref->show_scale() * scale;
412 cc_avg = pref->image->FOM();
413 pref->origin(pref->size()/2);
414
415 write_img("progaln.pif", pref, 0);
416
417 long i, nn;
418 Bimage* p1;
419 Vector3<double>* sh = new Vector3<double>[pt->images()];
420
421 if ( verbose )
422 cout << "Iterative refinement:" << endl;
423 for ( i=1; i<=10 && fabs(shift_avg - shift_avg_old) > 0.01
424 && cc_avg > cc_avg_old; i++ ) {
425 pt->origin(pref->size()/2);
426
427 if ( verbose )
428 cout << "Iteration " << i << endl;
429 #ifdef HAVE_GCD
430 dispatch_apply(n, dispatch_get_global_queue(0, 0), ^(size_t nn){
431 sh[nn] = pt->find_shift_in_transform(nn, pref, shift_limit);
432 });
433 #else
434 #pragma omp parallel for
435 for ( nn=0; nn<n; nn++ ) {
436 sh[nn] = p1->find_shift_in_transform(nn, pref, shift_limit);
437 }
438 #endif
439
440 pref->clear();
441 pref->origin(pref->size()/2);
442
443 shift_avg_old = shift_avg;
444 cc_avg_old = cc_avg;
445
446 for ( nn=0; nn<n; nn++ ) sh[nn] = sh[ref_num] - sh[nn];
447
448 if ( verbose )
449 cout << "Image\tShift\t\t\tCC" << endl;
450 for ( cc_avg=0, shift_avg=0, nn=0; nn<n; nn++ ) {
451 p1 = pt->extract(nn);
452 p1->phase_shift(sh[nn]);
453 pref->add(p1);
454 delete p1;
455 cc_avg += pt->image[nn].FOM();
456 sh[nn] *= scale;
457 if ( nn ) shift_avg += sh[nn].distance(sh[nn-1]);
458 if ( verbose )
459 cout << nn+1 << tab << sh[nn] << tab << pt->image[nn].FOM() << endl;
460 }
461
462 pref->fspace_normalize();
463
464 shift_avg /= n-1;
465 cc_avg /= n;
466
467 if ( verbose ) {
468 cout << "Shift average per frame: " << shift_avg << endl;
469 cout << "CC average: " << cc_avg << endl;
470 }
471 }
472
473 delete pref;
474
475 vector<double> vsh(3);
476 JSvalue job(JSobject);
477 JSvalue jsh(JSarray);
478
479 for ( nn=0; nn<n; nn++ ) {
480 vsh = {sh[nn][0], sh[nn][1], pt->image[nn].FOM()};
481 jsh.push_back(vsh);
482 }
483
484 job["shifts"] = jsh;
485 job["shift_average"] = shift_avg;
486 job["FOM"] = cc_avg;
487
488 if ( verbose )
489 cout << "Shifting original frames" << endl << endl;
490
491 fft();
492
493 #ifdef HAVE_GCD
494 dispatch_apply(n, dispatch_get_global_queue(0, 0), ^(size_t nn){
495 fspace_translate(nn, sh[nn]);
496 image[nn].FOM(pt->image[nn].FOM());
497 });
498 #else
499 #pragma omp parallel for
500 for ( nn=0; nn<n; nn++ ) {
501 fspace_translate(nn, sh[nn]);
502 image[nn].FOM(pt->image[nn].FOM());
503 }
504 #endif
505
506 fft_back();
507
508 delete pt;
509 delete[] sh;
510
511 return job;
512 }
513
514
515
516 /*
517 @brief Real space cross-correlation of two power spectrum annuli in two directions.
518 @param n number of values in the annulus.
519 @param *x first annulus.
520 @param *y second annulus.
521 @return double* array of correlation coefficients.
522
523 The first halves of the annuli is cross-correlated forward and the second
524 halves backward, representing the correlations of the original annulus and
525 its inverse.
526 **/
527 double* cc_two_way(long nn, double* x, double* y)
528 {
529 long i, j, k, n2(nn/2);
530 double sx(0), sx2(0), sy(0), sy2(0), sxy, d;
531
532 double* cc = new double[nn];
533 for ( i=0; i<nn; i++ ) cc[i] = 0;
534
535 for ( i=0; i<n2; i++ ) {
536 sx += x[i];
537 sx2 += x[i]*x[i];
538 sy += y[i];
539 sy2 += y[i]*y[i];
540 }
541
542 d = (n2*sx2 - sx*sx)*(n2*sy2 - sy*sy);
543 if ( d > 0 ) d = sqrt(d);
544 else {
545 cerr << "Error in cc_two_way: denominator is negative!" << endl;
546 return cc;
547 }
548
549 for ( i=0; i<n2; i++ ) {
550 sxy = 0;
551 for ( j=0, k=i; j<n2; j++, k++ ) {
552 if ( k >= nn ) k = 0;
553 sxy += x[j]*y[k];
554 }
555 cc[i] = (n2*sxy - sx*sy)/d;
556 }
557
558 for ( i=n2; i<nn; i++ ) {
559 sxy = 0;
560 for ( j=n2, k=i; j<nn; j++, k-- ) {
561 if ( k < 0 ) k = nn - 1;
562 sxy += x[j]*y[k];
563 }
564 cc[i] = (n2*sxy - sx*sy)/d;
565 }
566
567 return cc;
568 }
569
592 double Bimage::correlate_annuli(Bimage* polref,
593 int ann_min, int ann_max, double ang_min, double ang_max,
594 fft_plan planf, fft_plan planb, double& cc_max)
595 {
596 if ( ann_min > ann_max ) swap(ann_min, ann_max);
597 if ( ann_min < 0 ) ann_min = 0;
598 if ( ann_max >= y ) ann_max = y - 1;
599
600 while ( ang_min < -TWOPI ) ang_min += TWOPI;
601 while ( ang_max > TWOPI ) ang_max -= TWOPI;
602
603 if ( fabs(ang_min - ang_max) < 1e-10 ) {
604 ang_min = 0;
605 ang_max = TWOPI;
606 }
607
608 Bimage* pcc = polref->pack_two_in_complex(this);
609
610 if ( verbose & VERB_PROCESS )
611 cout << "Doing row cross-correlations from annulus " << ann_min << " to annulus " << ann_max << endl;
612
613 // Do FFT's in place
614 long i, j, ij, icc;
615 long offset, linesize(pcc->channels()*pcc->sizeX());
616 double scale, sum1, sum2;
617 Complex<float> d1, d2;
618
619 float* cc = new float[2*pcc->sizeX()];
620 for ( i=0; i<2*pcc->sizeX(); i++ ) cc[i] = 0;
621
622 // Specify FFTW arrays
623 Complex<float>* data;
624 Complex<float>* temp1 = new Complex<float>[pcc->sizeX()];
625 Complex<float>* temp2 = new Complex<float>[pcc->sizeX()];
626
627 // Correlate polar images line by line
628 for ( i=ann_min, offset=i*linesize; i<=ann_max; i++, offset+=linesize ) {
629 data = (Complex<float> *) (pcc->data_pointer(offset));
630 fftw(planf, data);
631 sum1 = sum2 = 0;
632 for ( j=0; j<pcc->sizeX(); j++ ) temp1[j] = 0;
633 for ( j=0; j<pcc->sizeX()/2; j++ ) {
634 ij = -j;
635 if ( ij < 0 ) ij += pcc->sizeX();
636 d1 = data[j].unpack_first(data[ij]);
637 d2 = data[j].unpack_second(data[ij]);
638 temp1[ij] = d1 * d2.conj();
639 temp1[i] = temp1[ij].conj();
640 sum1 += d1.power();
641 sum2 += d2.power();
642 }
643 if ( sum1 && sum2 ) {
644 scale = 0.5/sqrt(sum1*sum2);
645 for ( j=0; j<pcc->sizeX(); j++ ) temp1[j] *= scale;
646 }
647 fftw(planb, temp1);
648 for ( j=0; j<pcc->sizeX(); j++ ) cc[j] += temp1[j].real();
649 }
650
651 delete[] temp1;
652 delete[] temp2;
653
654 icc = 0;
655 cc_max = cc[0];
656
657 long imin((ang_min/TWOPI)*pcc->sizeX());
658 long imax((ang_max/TWOPI)*pcc->sizeX());
659 if ( imin < 0 && imax < 0 ) {
660 imin += pcc->sizeX();
661 imax += pcc->sizeX();
662 }
663 if ( imax > pcc->sizeX() ) imax = pcc->sizeX();
664
665 if ( imin < 0 && imax > 0 ) {
666 imin += pcc->sizeX();
667 for ( j=0; j<imin; j++ ) {
668 if ( cc_max < cc[j] ) {
669 cc_max = cc[j];
670 icc = j;
671 }
672 }
673 for ( j=imax; j<pcc->sizeX(); j++ ) {
674 if ( cc_max < cc[j] ) {
675 cc_max = cc[j];
676 icc = j;
677 }
678 }
679 } else {
680 if ( imin < 0 ) imin = 0;
681 for ( j=imin; j<imax; j++ ) {
682 if ( cc_max < cc[j] ) {
683 cc_max = cc[j];
684 icc = j;
685 }
686 }
687 }
688 double angle = icc*M_PI*(2.0/pcc->sizeX());
689 // if ( icc >= pcc->sizeX() ) angle = ((long)pcc->sizeX() - icc)*M_PI*(2.0/pcc->sizeX());
690 // if ( icc >= pcc->sizeX() ) angle = (icc - 2.0*pcc->sizeX())*M_PI*(2.0/pcc->sizeX());
691
692 if ( fabs(angle) < 1e-10 ) angle = 0;
693
694 if ( verbose & VERB_DEBUG )
695 cout << "DEBUG Bimage::correlate_annuli: " << icc << tab << angle << tab << angle*180.0/M_PI << tab << cc[icc] << endl;
696
697 delete[] cc;
698
699 delete pcc;
700
701 if ( verbose & VERB_PROCESS )
702 cout << "Best in-plane rotation angle: " << angle*180.0/M_PI << endl;
703
704 return angle;
705 }
706
707 /*
708 @brief Calculates the sums of the cross-correlation arrays for annuli of the power spectra.
709 @param *pref reference 2D image.
710 @param res_hi high resolution limit.
711 @param res_lo low resolution limit.
712 @param nang number of angles.
713 @param planf FFT forward plan.
714 @return double* array of summed correlation coefficients.
715
716 The images are packed into a complex form, Fourier transformed and unpacked.
717 The two polar power spectra are calculated and the annuli cross-correlated.
718 The input images must be equal-sized square 2D images.
719 **/
720 double* Bimage::pps_angular_correlation(Bimage* pref,
721 double res_hi, double res_lo, long nang, fft_plan planf)
722 {
723 Bimage* pc = pack_two_in_complex(pref);
724 if ( !pc ) return NULL;
725
726 pc->fft(planf, 1);
727
728 pc->origin(0.0,0.0,0.0);
729
730 Bimage* pc2 = pc->unpack_combined_transform();
731
732 pc->complex_to_amplitudes();
733 pc2->complex_to_amplitudes();
734
735 Bimage* ppsref = pc2->polar_power_spectrum(res_hi, nang);
736 Bimage* pps = pc->polar_power_spectrum(res_hi, nang);
737
738 delete pc;
739 delete pc2;
740
741 long min_rad(1);
742 if ( res_lo ) min_rad = (long) (real_size()[0]/res_lo);
743 if ( min_rad < 1 ) min_rad = 1;
744
745 long i, j, na, r, m, offset;
746 double f;
747 double* cc;
748 double* ccs = new double[pps->sizeX()];
749 for ( i=0; i<pps->sizeX(); i++ ) ccs[i] = 0;
750
751 for ( r=min_rad, m=0, offset=r*pps->sizeX(); r<pps->sizeY(); r++, m++, offset+=pps->sizeX() ) {
752 na = nang*r;
753 cc = cc_two_way(na, (double*) (ppsref->data_pointer(offset)), (double*) (pps->data_pointer(offset)));
754 f = na*1.0L/pps->sizeX();
755 for ( i=0; i<pps->sizeX(); i++ ) {
756 j = (long) (i*f + 0.5);
757 if ( j >= na ) j -= na;
758 ccs[i] += cc[j];
759 }
760 delete[] cc;
761 }
762
763 for ( i=0; i<pps->sizeX(); i++ ) ccs[i] /= m;
764
765 delete pps;
766 delete ppsref;
767
768 return ccs;
769 }
770
796 double Bimage::align2D_pps(Bimage* pref, double res_hi, double res_lo,
797 double shift_limit, double angle_limit,
798 fft_plan planf, fft_plan planb)
799 {
800 if ( verbose & VERB_DEBUG )
801 cout << "DEBUG Bimage::align2D_pps: res_hi=" << res_hi << " res_lo=" << res_lo << endl;
802
803 long nang(16);
804 long max_rad = (long) (real_size()[0]/res_hi);
805 if ( max_rad > x/2 ) max_rad = x/2;
806 long max_ang(nang*max_rad);
807 long hang(max_ang/2);
808
809 double angle(image->view_angle() - atan2(image->view()[1], image->view()[0]));
810 // double angle(image->view_angle());
811 long imin(0), imax(hang);
812 if ( angle_limit ) {
813 imin = max_ang*(angle - angle_limit)/TWOPI;
814 imax = max_ang*(angle + angle_limit)/TWOPI;
815 if ( imax < 0 ) {
816 imin += hang;
817 imax += hang;
818 }
819 }
820
821 long i, j, shift(0);
822 double cc1, cc2, cc3, cc, f;
823 double* ccs;
824
825 // Forward cross-correlation
826 ccs = pps_angular_correlation(pref, res_hi, res_lo, nang, planf);
827 if ( imin >= 0 ) {
828 for ( i=imin, cc2 = 0; i<imax; i++ ) if ( cc2 < ccs[i] ) {
829 shift = i;
830 cc2 = ccs[i];
831 }
832 } else {
833 for ( i=0, cc2 = 0; i<imax; i++ ) if ( cc2 < ccs[i] ) {
834 shift = i;
835 cc2 = ccs[i];
836 }
837 for ( i=imin; i<hang; i++ ) if ( cc2 < ccs[i] ) {
838 shift = i;
839 cc2 = ccs[i];
840 }
841 }
842 j = shift - 1;
843 if ( j < 0 ) j += hang;
844 cc1 = ccs[j];
845 j = shift + 1;
846 if ( j >= hang ) j -= hang;
847 cc3 = ccs[j];
848 f = (cc1 - cc3)/(2*(cc1 - 2*cc2 + cc3));
849 angle = (shift + f)*M_PI*2.0L/max_ang;
850
851 delete[] ccs;
852
853 // Determine origins and CC's for both angles and select the best
854 cc = cc1 = rotate_cross_correlate_two_way(pref, angle, res_hi, res_lo, shift_limit, planf, planb);
855
856 return cc;
857 }
858
859
886 double Bimage::align2D(Bimage* pref, double res_polar,
887 int ann_min, int ann_max, Bimage* prs_mask, double shift_limit, double angle_limit,
888 fft_plan planf_1D, fft_plan planb_1D, fft_plan planf_2D, fft_plan planb_2D)
889 {
890 if ( verbose & VERB_DEBUG )
891 cout << "DEBUG Bimage::align2D: ann_min=" << ann_min << " ann_max=" << ann_max << endl;
892
893 double angle(image->view_angle() - atan2(image->view()[1], image->view()[0]));
894 // double angle(image->view_angle());
895 double ang_min(0), ang_max(TWOPI);
896 if ( angle_limit ) {
897 ang_min = angle - angle_limit;
898 ang_max = angle + angle_limit;
899 }
900
901 long nannuli(pref->sizeX()/2); // Sampling same as image
902 long nangles(NPOLANG); // 0.5 degree step size
903 double pimgcc(0); // Polar image correlation coefficient
904
905 Bimage* ppart = copy();
906 Bimage* pproj = pref->copy();
907
908 if ( res_polar ) {
909 ppart->fspace_bandpass(0, res_polar, 0, planf_2D, planb_2D);
910 pproj->fspace_bandpass(0, res_polar, 0, planf_2D, planb_2D);
911 }
912
913 // cout << ppart->image->origin() << tab << pproj->image->origin() << endl;
914
915 Bimage* pol = NULL;
916 Bimage* polref = pproj->cartesian_to_cylindrical(nannuli, nangles, 1);
917 delete pproj;
918
919 long i, done(0);
920 double best_angle(0);
921 double da, dx, dy, ap(1e37);
922 double cc, best_cc(-1e37);
923 Vector3<double> translate, prev_translate(1e37, 1e37, 0), best_shift;
924 Bimage* prot;
925
926 for ( i=0; i<5 && !done; i++ ) {
927 pol = ppart->cartesian_to_cylindrical(nannuli, nangles, 1);
928 angle = pol->correlate_annuli(polref, ann_min, ann_max,
929 ang_min, ang_max, planf_1D, planb_1D, pimgcc);
930 delete pol;
931 prot = pref->rotate(pref->size(), fabs(angle));
932 translate = find_shift(prot, prs_mask, 0, 0, shift_limit, 0, 1, planf_2D, planb_2D, cc);
933 delete prot;
934 if ( best_cc < cc ) {
935 best_cc = cc;
936 best_shift = translate;
937 best_angle = angle;
938 }
939 da = fabs(angle - ap);
940 dx = fabs(translate[0] - prev_translate[0]);
941 dy = fabs(translate[1] - prev_translate[1]);
942 prev_translate = translate;
943 ap = angle;
944 if ( i > 0 && da < 0.005 && dx < 0.1 && dy < 0.1 ) done = 1;
945 }
946
947 delete polref;
948 delete ppart;
949
950 image->origin(pref->image->origin() + best_shift);
951 image->view_angle(best_angle);
952 image->FOM(best_cc);
953 // image->view_angle(pref->image->view_angle() + best_angle);
954
955 return best_cc;
956 }
957
973 int Bimage::align2D(Bimage* pref, int ann_min, int ann_max,
974 double res_lo, double res_hi, double shift_limit, double angle_limit)
975 {
976 // Generate the masks for cross-correlation and cross-validation
977 Bimage* prs_mask = new Bimage(Float, TSimple, size(), 1);
978 prs_mask->sampling(sampling());
979
980 vector<double> band = fspace_default_bands(res_lo, res_hi);
981 prs_mask->mask_fspace_banded(band);
982
983 // Specify FFTW arrays
984 fft_plan planf_1D = fft_setup_plan(NPOLANG, 1, 1, FFTW_FORWARD, 1);
985 fft_plan planb_1D = fft_setup_plan(NPOLANG, 1, 1, FFTW_BACKWARD, 1);
986 fft_plan planf_2D = fft_setup_plan(size(), FFTW_FORWARD, 1);
987 fft_plan planb_2D = fft_setup_plan(size(), FFTW_BACKWARD, 1);
988
989
990 double cc = align2D(pref, 0, ann_min, ann_max, prs_mask, shift_limit,
991 angle_limit, planf_1D, planb_1D, planf_2D, planb_2D);
992
993 if ( verbose )
994 cout << "Alignment correlation: " << cc << endl << endl;
995
996 fft_destroy_plan(planf_1D);
997 fft_destroy_plan(planb_1D);
998 fft_destroy_plan(planf_2D);
999 fft_destroy_plan(planb_2D);
1000
1001 delete prs_mask;
1002
1003 rotate();
1004
1005 return 0;
1006 }
1007
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bimage::phase_shift
int phase_shift(Vector3< double > shift)
Phase shifts a complex image.
Definition: Bimage_complex.cpp:256
Bimage::refine_peak
int refine_peak()
Refines the position of a peak to sub-voxel resolution.
Definition: Bimage_correlate.cpp:1556
Complex::unpack_second
Complex unpack_second(Complex c)
Definition: Complex.h:116
NPOLANG
#define NPOLANG
Definition: Bimage.h:29
Bimage::unpack_combined_transform
Bimage * unpack_combined_transform()
Unpacks a complex transform obtained from two real images.
Definition: Bimage_complex.cpp:749
FILL_BACKGROUND
#define FILL_BACKGROUND
Definition: utilities.h:174
Bsub_image::view
void view(double x, double y, double z, double a)
Definition: Bimage.h:143
Bimage.h
Header file for image class.
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
planb
fft_plan planb
Definition: bico.cpp:24
Bimage::add
void add(long j, double v)
Definition: Bimage.h:308
Bimage::align_progressive
Bimage * align_progressive(long nref, Bimage *pmask, double hi_res, double lo_res, double shift_limit, fft_plan planf, fft_plan planb)
Aligns and sums a set of sub-images using a progressive algorithm.
Definition: Bimage_align.cpp:29
Bimage::fspace_bandpass
int fspace_bandpass(double res_hi, double res_lo=0, double width=0)
Applies a bandpass filter to an image.
Definition: Bimage_fspace.cpp:499
Bimage::fspace_translate
int fspace_translate(Vector3< double > shift)
Translates an image in frequency space to avoid interpolation.
Definition: Bimage_fspace.cpp:150
Bimage::fft
int fft()
Definition: Bimage.h:822
Bimage::fft_back
int fft_back()
Definition: Bimage.h:823
Bimage::bin_copy
Bimage * bin_copy(long b)
Definition: Bimage.h:1284
Bimage::shift_wrap
int shift_wrap(Vector3< double > vec)
Shifts an image.
Definition: Bimage_transform.cpp:643
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
planf
fft_plan planf
Definition: bico.cpp:24
Bimage::edge
int edge(int type, Vector3< long > rect, Vector3< double > start, double width, int fill_type=0, double fill=0)
Smooths the image edge with a soft rectangular function.
Definition: Bimage_edit.cpp:319
Bimage::align2D
double align2D(Bimage *pref, double res_polar, int ann_min, int ann_max, Bimage *prs_mask, double shift_limit, double angle_limit, fft_plan planf_1D, fft_plan planb_1D, fft_plan planf_2D, fft_plan planb_2D)
Finds the best in-plane alignment for two 2D images using polar power spectra.
Definition: Bimage_align.cpp:886
Bimage::pps_angular_correlation
double * pps_angular_correlation(Bimage *pref, double res_hi, double res_lo, long nang, fft_plan planf)
Definition: Bimage_align.cpp:720
Complex::conj
Complex conj()
Definition: Complex.h:106
Bimage::mask_fspace_banded
int mask_fspace_banded(vector< double > &band)
Generate reciprocal space mask based on a specification of bands.
Definition: Bimage_mask.cpp:814
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bimage::show_scale
double show_scale()
Definition: Bimage.h:556
Bimage::correlate_annuli
double correlate_annuli(Bimage *polref, int ann_min, int ann_max, double ang_min, double ang_max, fft_plan planf, fft_plan planb, double &cc_max)
Correlate annuli of a polar image.
Definition: Bimage_align.cpp:592
Vector3::distance
double distance(const Vector3 &v)
Definition: Vector3.h:227
Bimage::Bimage
Bimage()
Initializes an image.
Definition: Bimage.cpp:44
TSimple
Definition: Bimage.h:58
Bimage::complex_to_amplitudes
void complex_to_amplitudes()
The amplitudes from a complex image is written to a simple image.
Definition: Bimage_complex.cpp:114
Float
Definition: utilities.h:157
Vector3::max
Type max()
Definition: Vector3.h:175
Bimage
General image parameter class.
Definition: Bimage.h:163
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:487
Bimage::align
JSvalue align(long ref_num, Bimage *pmask, double hi_res, double lo_res, double shift_limit, double edge_width, double gauss_width, Vector3< long > bin)
Aligns and sums a set of sub-images, first progressively and then iteratively.
Definition: Bimage_align.cpp:203
Bimage::complex_conjugate_product
int complex_conjugate_product(Bimage *p)
Calculates the product of a complex image with the conjugate of a second.
Definition: Bimage_complex.cpp:460
M_PI
#define M_PI
Definition: utilities.h:59
Bimage::extract
Bimage * extract(long nn)
Extracts one sub-image into new image structure.
Definition: Bimage_extract.cpp:21
Bimage::zero_origin
int zero_origin()
Shifts the origins to zero with wrapping.
Definition: Bimage_transform.cpp:727
Bimage::shift
int shift(Vector3< double > vec, int fill_type=0, double fill=0)
Shifts an image.
Definition: Bimage_transform.cpp:587
cc_two_way
double * cc_two_way(long nn, double *x, double *y)
Definition: Bimage_align.cpp:527
fft_plan
fftwf_plan fft_plan
Definition: fft.h:16
Bsub_image::FOM
double FOM()
Definition: Bimage.h:151
Bimage::polar_power_spectrum
Bimage * polar_power_spectrum(double resolution, long num_angle)
Calculates the polar power spectrum of a 2D transform amplitude or intensity image.
Definition: Bimage_polar.cpp:701
Bimage::find_peak
int find_peak(double radius=1e30, double sigma=0)
Finds the peak in an image to the nearest voxel.
Definition: Bimage_correlate.cpp:1338
write_img
int write_img(const char *filename, Bimage *p, int compression)
General driver function to write multiple image formats.
Definition: rwimg.cpp:280
Bimage::size
Vector3< long > size() const
Definition: Bimage.h:373
Bimage::calculate_background
int calculate_background(long nn, int flag)
Calculates the background for one sub-image.
Definition: Bimage_background.cpp:27
JSobject
Definition: json.h:26
Bimage::rotate_cross_correlate_two_way
double rotate_cross_correlate_two_way(Bimage *pref, double angle, double res_hi, double res_lo, double shift_limit, fft_plan planf, fft_plan planb)
Definition: Bimage_correlate.cpp:862
JSvalue
Definition: json.h:53
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:127
Bimage::channels
long channels()
Definition: Bimage.h:371
Bimage::align_fast
JSvalue align_fast(long ref_num, Bimage *pmask, double hi_res, double lo_res, double shift_limit, double edge_width, double gauss_width)
Aligns and sums a set of sub-images, first progressively and then iteratively.
Definition: Bimage_align.cpp:361
Bimage::complex_to_real
void complex_to_real()
The real part of a complex image is written to a simple image.
Definition: Bimage_complex.cpp:50
Complex
Definition: Complex.h:23
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:261
Bimage::copy
Bimage * copy()
Copies the header information and data of an image into a new image structure.
Definition: Bimage.cpp:2695
Bimage::sizeX
void sizeX(long nx)
Definition: Bimage.h:377
Bimage::fft_setup
fft_plan fft_setup(fft_direction dir, int opt=0)
Sets up a plan for fast Fourier transforms.
Definition: Bimage_fft.cpp:29
Bimage::clear
void clear()
Definition: Bimage.h:697
Bimage::find_shift_in_transform
Vector3< double > find_shift_in_transform(double shift_limit)
Finds the shift by brute force backtransformation for selected shifts.
Definition: Bimage_correlate.cpp:505
Bimage::fspace_default_bands
vector< double > fspace_default_bands(double res_lo, double res_hi)
Sets up default frequency space bands to generate a mask.
Definition: Bimage_mask.cpp:772
Bimage::align_progressive_fast
Bimage * align_progressive_fast(long nref, double shift_limit)
Aligns and sums a set of sub-images using a progressive algorithm.
Definition: Bimage_align.cpp:138
verbose
int verbose
Vector3< double >
fft_destroy_plan
int fft_destroy_plan(fft_plan plan)
Deallocates a plan for fast Fourier transforms.
Definition: fft.cpp:87
Bimage::rotate
int rotate()
Rotates an image using parameters defined in the image in place.
Definition: Bimage_transform.cpp:253
Bimage::find_shift
int find_shift(Bimage *pref, Bimage *pmask, double hires, double lores, double radius, double sigma, int refine_flag)
Calculates a cross-correlation map to find the shift for the pair of images.
Definition: Bimage_correlate.cpp:932
fft_setup_plan
fft_plan fft_setup_plan(long x, long y, long z, fft_direction dir, int opt)
Sets up a plan for fast Fourier transforms.
Definition: fft.cpp:31
JSarray
Definition: json.h:27
fftw
int fftw(fft_plan plan, Complex< float > *a)
Fast Fourier transforms a data array.
Definition: fft.cpp:106
Bimage::cartesian_to_cylindrical
Bimage * cartesian_to_cylindrical(long nannuli, long nphi, int flag=0)
Calculates an image with cylindrical coordinates.
Definition: Bimage_polar.cpp:519
Complex::unpack_first
Complex unpack_first(Complex c)
Definition: Complex.h:113
rwimg.h
Header file for 2D and 3D image I/O.
Bimage::fspace_normalize
int fspace_normalize()
Normalizes an image's amplitudes.
Definition: Bimage_fspace.cpp:1539
Complex::power
double power()
Definition: Complex.h:103
Bimage::images
long images()
Definition: Bimage.h:491
Bimage::pack_two_in_complex
Bimage * pack_two_in_complex(Bimage *p)
Packs two real images into one complex image.
Definition: Bimage_complex.cpp:679
JSvalue::push_back
void push_back(const JSvalue &val)
Definition: json.h:191
Bimage::sizeY
void sizeY(long ny)
Definition: Bimage.h:378
Bsub_image::view_angle
void view_angle(double d)
Definition: Bimage.h:147
Bimage::align2D_pps
double align2D_pps(Bimage *pref, double res_hi, double res_lo, double shift_limit, double angle_limit, fft_plan planf, fft_plan planb)
Finds the best in-plane alignment for two 2D images using polar power spectra.
Definition: Bimage_align.cpp:796
TWOPI
#define TWOPI
Definition: utilities.h:68
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:563