| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
img_polar.cpp
Go to the documentation of this file.
1
9 #include "img_fourier.h"
10 #include "img_polar.h"
11 #include "moving_average.h"
12 #include "trigonometry.h"
13 #include "utilities.h"
14 #include "Matrix.h"
15
16 // Declaration of global variables
17 extern int verbose; // Level of output to the screen
18
50 int img_cartesian_to_spherical(Bimage* p, int nannuli, int nphi, int ntheta)
51 {
52 p->change_type(Float);
53
54 unsigned long i, j, n;
55 long ann, phi, theta;
56 double maxrad, scale, x, y, z;
57
58 maxrad = p->sizeX()/2; // Maximum radius taken from largest dimension
59 if ( maxrad < p->sizeY()/2 ) maxrad = p->sizeY()/2;
60 if ( maxrad < p->sizeZ()/2 ) maxrad = p->sizeZ()/2;
61
62 if ( nannuli < 0 ) return -1;
63 if ( nannuli < 1 ) nannuli = (long) maxrad;
64 if ( nphi < 1 ) nphi = 90;
65 if ( p->sizeY() < 2 ) nphi = 1;
66 if ( ntheta < 1 ) ntheta = 50;
67 if ( p->sizeZ() < 2 ) ntheta = 1;
68
69 double dannulus = maxrad*1.0/nannuli; // Step size in each dimension
70 double dphi = TWOPI/nphi;
71 double dtheta = M_PI/ntheta;
72 double cos_phi, sin_phi, cos_theta, sin_theta;
73
74 unsigned long datasize = nannuli*nphi*ntheta;
75
76 float* sphdata = new float[datasize];
77
78 if ( verbose & VERB_PROCESS ) {
79 cout << "Spherical image size: " <<
80 nannuli << " " << nphi << " " << ntheta << endl;
81 cout << "Step sizes: " << dannulus*p->sampling().x() << " A "
82 << dphi*180.0/M_PI << " degree " << dtheta*180.0/M_PI << " degree" << endl;
83 } else if ( verbose & VERB_LABEL )
84 cout << "Converting to spherical coordinates" << endl << endl;
85
86 // Interpolate cartesian points to get spherical voxel values
87 if ( verbose & VERB_FULL )
88 cout << "Image\tOrigin" << endl;
89 for ( n=0; n<p->images(); n++ ) {
90 if ( verbose & VERB_FULL )
91 cout << n+1 << tab << p->image[n].origin().x() << tab <<
92 p->image[n].origin().y() << tab << p->image[n].origin().z() << endl;
93 for ( theta=0; theta<ntheta; theta++ ) {
94 cos_theta = dannulus*bcos(dtheta*theta);
95 sin_theta = dannulus*bsin(dtheta*theta);
96 for ( phi=0; phi<nphi; phi++ ) {
97 cos_phi = bcos(dphi*phi);
98 sin_phi = -bsin(dphi*phi);
99 for ( ann=0; ann<nannuli; ann++ ) {
100 j = ((n*ntheta + theta)*nphi + phi)*nannuli + ann;
101 scale = ann*sin_theta;
102 x = scale*cos_phi + p->image[n].origin().x();
103 y = scale*sin_phi + p->image[n].origin().y();
104 z = ann*cos_theta + p->image[n].origin().z();
105 sphdata[j] = p->interpolate(0, x, y, z, n, 0);
106 }
107 }
108 }
109 p->image[n].origin(0, nphi/2, ntheta/2);
110 }
111
112 if ( verbose & VERB_PROCESS ) cout << endl;
113
114 p->size(nannuli, nphi, ntheta);
115 p->page_size(nannuli, nphi, ntheta);
116
117 p->data_assign((unsigned char *) sphdata);
118
119 if ( verbose & VERB_DEBUG )
120 cout << "DEBUG img_cartesian_to_spherical: Calculating statistics" << endl;
121
122 p->statistics();
123
124 return 0;
125 }
126
154 int img_cartesian_to_cylindrical(Bimage* p, int nannuli, int nphi)
155 {
156 unsigned long i, j, n, x, y, z;
157 long ann, phi, xx, yy;
158 double maxrad, xpoint, ypoint;
159 double wx, wy, w;
160
161 maxrad = p->sizeX()/2; // Maximum radius taken from largest x and y dimension
162 if ( maxrad < p->sizeY()/2 ) maxrad = p->sizeY()/2;
163
164 if ( nannuli < 0 ) return -1;
165 if ( nannuli < 1 ) nannuli = (long) maxrad;
166 if ( nphi < 1 ) nphi = 90;
167 if ( p->sizeY() < 2 ) nphi = 1;
168
169 double dannulus = maxrad*1.0/nannuli; // Step size in each dimension
170 double dphi = TWOPI/nphi;
171 double cos_phi, sin_phi;
172
173 unsigned long datasize = nannuli*nphi*p->sizeZ();
174
175 float* cyldata = new float[datasize];
176
177 for ( i=0; i<datasize; i++ ) cyldata[i] = 0;
178
179 if ( verbose & VERB_PROCESS ) {
180 cout << "Cylindrical image size: " <<
181 nannuli << " " << nphi << " " << p->sizeZ() << endl;
182 cout << "Step sizes: " << dannulus*p->sampling().x() << " A "
183 << dphi*180.0/M_PI << " degree" << endl;
184 } else if ( verbose & VERB_LABEL )
185 cout << "Converting to cylindrical coordinates" << endl << endl;
186
187 // Interpolate cartesian points to get spherical voxel values
188 if ( verbose & VERB_FULL )
189 cout << "Image\tOrigin" << endl;
190 for ( n=0; n<p->images(); n++ ) {
191 if ( verbose & VERB_FULL )
192 cout << n+1 << tab << p->image[n].origin().x() << tab <<
193 p->image[n].origin().y() << tab << p->image[n].origin().z() << endl;
194 for ( z=0; z<p->sizeZ(); z++ ) {
195 for ( phi=0; phi<nphi; phi++ ) {
196 cos_phi = bcos(dphi*phi);
197 sin_phi = -bsin(dphi*phi);
198 for ( ann=0; ann<nannuli; ann++ ) {
199 j = ((n*p->sizeZ() + z)*nphi + phi)*nannuli + ann;
200 xpoint = ann*cos_phi + p->image[n].origin().x();
201 ypoint = ann*sin_phi + p->image[n].origin().y();
202 x = (long) xpoint;
203 y = (long) ypoint;
204 wy = ypoint - y;
205 for ( yy=y; yy<y+2 && yy<p->sizeY(); yy++ ) {
206 wy = 1 - wy;
207 wx = xpoint - x;
208 if ( yy >= 0 ) for ( xx=x; xx<x+2 && xx<p->sizeX(); xx++ ) {
209 wx = 1 - wx;
210 if ( xx >= 0 ) {
211 // i = ((n*p->z + z)*p->y + yy)*p->x + xx;
212 i = p->index(0,xx,yy,z,n);
213 w = wx*wy;
214 cyldata[j] += w*(*p)[i];
215 }
216 }
217 }
218 }
219 }
220 }
221 p->image[n].origin(0, nphi/2, p->image[n].origin().z());
222 }
223
224 if ( verbose & VERB_PROCESS ) cout << endl;
225
226 p->size(nannuli, nphi, p->size().z());
227
228 p->data_assign((unsigned char *) cyldata);
229
230 if ( verbose & VERB_DEBUG )
231 cout << "DEBUG img_cartesian_to_cylindrical: Calculating statistics" << endl;
232
233 p->statistics();
234
235 return 0;
236 }
237
252 int img_radial_shells(Bimage* p)
253 {
254 p->change_type(Float);
255
256 unsigned long i, j, n, x, y, z;
257 long zz;
258 double dx2, dy2, dz, dz2, d2, oldz, fraction;
259
260 unsigned long datasize = p->data_size();
261 float* shell = new float[datasize];
262
263 if ( verbose & ( VERB_PROCESS | VERB_LABEL ) )
264 cout << "Converting to radial shells" << endl << endl;
265
266 // Interpolate cartesian points to get spherical voxel values
267 if ( verbose & VERB_FULL )
268 cout << "Image\tOrigin" << endl;
269 for ( j=n=0; n<p->images(); n++ ) {
270 if ( verbose & VERB_FULL )
271 cout << n+1 << tab << p->image[n].origin().x() << tab <<
272 p->image[n].origin().y() << tab << p->image[n].origin().z() << endl;
273 for ( z=0; z<p->sizeZ(); z++ ) {
274 dz = z - p->image[n].origin().z();
275 dz2 = dz*dz;
276 for ( y=0; y<p->sizeY(); y++ ) {
277 dy2 = y - p->image[n].origin().y();
278 dy2 *= dy2;
279 for ( x=0; x<p->sizeX(); x++, j++ ) {
280 dx2 = x - p->image[n].origin().x();
281 dx2 *= dx2;
282 d2 = dz2 - dy2 - dx2;
283 if ( d2 >= 0 ) {
284 if ( dz < 0 ) oldz = p->image[n].origin().z() - sqrt(d2);
285 else oldz = p->image[n].origin().z() + sqrt(d2);
286 zz = (long) oldz;
287 if ( zz >= 0 && zz < p->sizeZ() ) {
288 fraction = 1 + zz - oldz;
289 i = p->index(0,x,y,zz,n);
290 shell[j] = fraction*(*p)[i];
291 zz++;
292 if ( zz < p->sizeZ() ) {
293 fraction = 1 - fraction;
294 i += p->sizeY()*p->sizeX();
295 shell[j] += fraction*(*p)[i];
296 }
297 }
298 }
299 }
300 }
301 }
302 }
303
304 if ( verbose & VERB_FULL ) cout << "" << endl;
305
306 p->data_assign((unsigned char *) shell);
307
308 p->statistics();
309
310 return 0;
311 }
312
327 int img_cylindrical_shells(Bimage* p)
328 {
329 p->change_type(Float);
330
331 unsigned long i, j, n, x, y, z;
332 long yy;
333 double dx, dy, dx2, dy2, d2, oldy, fraction;
334
335 unsigned long datasize = p->data_size();
336 float* shell = new float[datasize];
337
338 if ( verbose & ( VERB_PROCESS | VERB_LABEL ) )
339 cout << "Converting to cylindrical shells" << endl << endl;
340
341 // Interpolate cartesian points to get cylindrical voxel values
342 if ( verbose & VERB_FULL )
343 cout << "Image\tOrigin" << endl;
344 for ( j=n=0; n<p->images(); n++ ) {
345 if ( verbose & VERB_FULL )
346 cout << n+1 << tab << p->image[n].origin().x() << tab <<
347 p->image[n].origin().y() << tab << p->image[n].origin().z() << endl;
348 for ( z=0; z<p->sizeZ(); z++ ) {
349 // dz = z - p->image[n].origin().z();
350 // dz2 = dz*dz;
351 for ( y=0; y<p->sizeY(); y++ ) {
352 dy = y - p->image[n].origin().y();
353 dy2 = dy*dy;
354 for ( x=0; x<p->sizeX(); x++, j++ ) {
355 dx = x - p->image[n].origin().x();
356 dx2 = dx*dx;
357 d2 = dy2 + dx2;
358 if ( dy2 >= dx2 ) {
359 if ( dy < 0 ) oldy = p->image[n].origin().y() - sqrt(d2);
360 else oldy = p->image[n].origin().y() + sqrt(d2);
361 yy = (long) oldy;
362 if ( yy >= 0 && yy < p->sizeY() ) {
363 fraction = 1 + yy - oldy;
364 // i = ((n*p->z + z)*p->y + yy)*p->x + x;
365 i = p->index(0,x,yy,z,n);
366 shell[j] = fraction*(*p)[i];
367 yy++;
368 if ( yy < p->sizeY() ) {
369 fraction = 1 - fraction;
370 i += p->sizeX();
371 shell[j] += fraction*(*p)[i];
372 }
373 }
374 }
375 }
376 }
377 }
378 }
379
380 if ( verbose & VERB_FULL ) cout << endl;
381
382 p->data_assign((unsigned char *) shell);
383
384 p->statistics();
385
386 return 0;
387 }
388
389 double radius_wrt_sym_axes(Vector3<float> c, int ns, Vector3<float>* vs)
390 {
391 int i;
392 double r, rmax = 0;
393 Vector3<float> v = c;
394 v.normalize();
395
396 for ( i=0; i<ns; i++ ) {
397 r = v.scalar(vs[i]);
398 if ( rmax < r ) rmax = r;
399 }
400
401 return rmax;
402 }
403
404 int img_set_radial_distances(Bimage* p, double spherical_fraction, Bstring& symmetry_string)
405 {
406 p->change_type(Float);
407
408 unsigned long i, x, y, z, n;
409 double r, rf;
410 Vector3<float> c;
411
412 int ns = 0;
413 Bsymmetry* sym = init_point_group_symmetry(symmetry_string);
414 Vector3<float>* vs = symmetry_get_axes(sym, &ns);
415 if ( !vs ) return -1;
416
417 if ( ns < 2 ) spherical_fraction = 1;
418
419 if ( verbose ) {
420 cout << "Calculating radial distances:" << endl;
421 cout << "Symmetry: " << sym->label << " (" << ns << ")" << endl;
422 cout << "Spherical fraction: " << spherical_fraction << endl;
423 }
424
425 kill_symmetry(sym);
426
427 float* fom = p->FOM_initialize();
428
429 for ( i=n=0; n<p->images(); n++ ) {
430 for ( z=0; z<p->sizeZ(); z++ ) {
431 c[2] = z - p->image[n].origin().z();
432 for ( y=0; y<p->sizeY(); y++ ) {
433 c[1] = y - p->image[n].origin().y();
434 for ( x=0; x<p->sizeX(); x++, i++ ) {
435 c[0] = x - p->image[n].origin().x();
436 r = c.length();
437 rf = 1;
438 if ( ns > 1 ) {
439 rf = radius_wrt_sym_axes(c, ns, vs);
440 rf = rf + spherical_fraction*(1 - rf);
441 r = r*rf;
442 }
443 fom[i] = r;
444 }
445 }
446 }
447 }
448
449 delete[] vs;
450
451 // Bstring filename("fom.pif");
452 // write_fom_as_image(filename, p);
453
454 return 0;
455 }
456
457 int img_radial_section(Bimage* p, Bimage* prad, unsigned long n,
458 long zr, double rad_start, double rad_step)
459 {
460 unsigned long j, j1, x, y, z, zj;
461 unsigned long slice_size = p->sizeX()*p->sizeY();
462 unsigned long image_size = slice_size*p->sizeZ();
463 unsigned long i = (unsigned long) (n*prad->size().volume() + zr*slice_size);
464 double r = rad_step*zr + rad_start;
465 double dr, drp;
466 float* fom = (float *) p->FOM();
467
468 for ( y=0; y<prad->sizeY(); y++ ) {
469 for ( x=0; x<prad->sizeX(); x++, i++ ) {
470 j = n*image_size + y*p->sizeX() + x;
471 for ( z=0, zj=p->sizeZ()+1, drp=1; z<p->sizeZ() && zj>=p->sizeZ(); z++, j+=slice_size ) {
472 dr = fom[j] - r;
473 if ( dr > 0 && drp <= 0 ) zj = z;
474 drp = dr;
475 }
476 if ( zj < p->sizeZ() ) {
477 j1 = n*image_size + zj*slice_size + y*p->sizeX() + x;
478 j = j1 - slice_size;
479 dr = (fom[j1] - r)/(fom[j1] - fom[j]);
480 prad->set(i, dr*(*p)[j]);
481 dr = 1 - dr;
482 prad->set(i, (*prad)[i] + dr*(*p)[j1]);
483 }
484 }
485 }
486
487 return 0;
488 }
489
509 Bimage* img_radial_sections(Bimage* p, double rad_start, double rad_end, double rad_step,
510 double spherical_fraction, Bstring& symmetry_string)
511 {
512 if ( rad_start < 0 ) rad_start = 0;
513 if ( rad_start >= p->sizeZ()/2 ) rad_start = p->sizeZ()/2;
514 if ( rad_end <= 0 ) rad_end = p->sizeZ()/2;
515 if ( rad_end >= p->sizeZ()/2 ) rad_end = p->sizeZ()/2 - 1;
516 if ( rad_end < rad_start ) rad_end = rad_start;
517 if ( rad_step <= 0 ) rad_step = 1;
518
519 if ( img_set_radial_distances(p, spherical_fraction, symmetry_string) < 0 )
520 return NULL;
521
522 unsigned long n;
523 unsigned long nz = (unsigned long) ((rad_end - rad_start)/rad_step + 1);
524
525 if ( verbose ) {
526 cout << "Calculating radial shells:" << endl;
527 cout << "Radial range: " << rad_start << " - " << rad_end << endl;
528 cout << "Radial step size: " << rad_step << endl;
529 cout << "New image size: " << p->sizeX() << " x " << p->sizeY() << " x " << nz << " x " << p->images() << endl << endl;
530 }
531
532 Bimage* prad = new Bimage(Float, TSimple, p->sizeX(), p->sizeY(), nz, p->images());
533 prad->sampling(p->sampling().x(), p->sampling().y(), p->sampling().z() * rad_step);
534
535 for ( n=0; n<p->images(); n++ ) {
536 prad->image[n] = p->image[n];
537 prad->image[n].origin(prad->image[n].origin().x(), prad->image[n].origin().y(), -rad_start);
538 #ifdef HAVE_GCD
539 dispatch_apply(nz, dispatch_get_global_queue(0, 0), ^(size_t z){
540 img_radial_section(p, prad, n, z, rad_start, rad_step);
541 });
542 #else
543 #pragma omp parallel for
544 for ( long z=0; z<nz; z++ )
545 img_radial_section(p, prad, n, z, rad_start, rad_step);
546 #endif
547 }
548
549 prad->statistics();
550
551 return prad;
552 }
553
573 Bimage* img_polar_transform(Bimage* p, int nannuli, int nangles, int ann_min, int ann_max)
574 {
575 p->change_type(Float);
576
577 int i, j, n, x, y, z, xx, yy, ix, iy, iz, iyn, izn, ann, ipsi, maxrad, num = 0;
578 double dann, dpsi, cos_psi, sin_psi, xpoint, ypoint, wx, wy, sum = 0, sqsum = 0;
579
580 if ( ann_min > ann_max ) swap(ann_min, ann_max);
581 if ( ann_min < 0 ) ann_min = 0;
582 if ( ann_max >= nannuli ) ann_max = nannuli - 1;
583 if ( ann_min == ann_max ) {
584 ann_min = 0;
585 ann_max = nannuli - 1;
586 }
587
588 maxrad = p->sizeX();
589 if ( maxrad < p->sizeY() ) maxrad = p->sizeY();
590 maxrad /= 2;
591 dann = maxrad*1.0/nannuli;
592 dpsi = M_PI*2.0/nangles;
593
594 Bimage* pp = new Bimage(Float, TSimple, nangles, nannuli, p->sizeZ(), p->images());
595
596 if ( verbose & VERB_PROCESS ) {
597 cout << "Calculating a polar image:" << endl;
598 cout << "Annular step size: " << dann << " pixels" <<endl;
599 cout << "Angular step size: " << dpsi*180/M_PI << " degrees" << endl;
600 cout << "Annular range: " << ann_min << " - " << ann_max << endl << endl;
601 } else if ( verbose & VERB_LABEL )
602 cout << "Calculating a polar image" << endl << endl;
603
604 for ( n=0; n<pp->images(); n++ ) {
605 if ( verbose & VERB_FULL )
606 cout << "Origin: " << p->image[n].origin() << endl;
607 for ( z=0; z<pp->sizeZ(); z++ ) {
608 iz = n*pp->sizeZ() + z;
609 izn = iz*p->sizeY()*p->sizeX();
610 for ( ipsi=0; ipsi<nangles; ipsi++ ) {
611 cos_psi = dann*bcos(dpsi*ipsi);
612 sin_psi = dann*bsin(dpsi*ipsi);
613 for ( ann=ann_min; ann<=ann_max; ann++ ) {
614 j = (iz*nannuli + ann)*nangles + ipsi;
615 xpoint = ann*cos_psi + p->image[n].origin().x();
616 ypoint = ann*sin_psi + p->image[n].origin().y();
617 while ( xpoint < 0 ) xpoint += p->sizeX(); // Wrapping
618 while ( ypoint < 0 ) ypoint += p->sizeY();
619 while ( xpoint >= p->sizeX() ) xpoint -= p->sizeX();
620 while ( ypoint >= p->sizeY() ) ypoint -= p->sizeY();
621 x = (int) xpoint;
622 y = (int) ypoint;
623 wx = xpoint - x;
624 wy = ypoint - y;
625 for ( yy=y; yy<y+2; yy++ ) {
626 wy = 1 - wy;
627 iy = ( yy >= p->sizeY() )? iy = yy - p->sizeY(): yy;
628 iyn = izn + iy*p->sizeX();
629 for ( xx=x; xx<x+2; xx++ ) {
630 wx = 1 - wx;
631 ix = ( xx >= p->sizeX() )? ix = xx - p->sizeX(): xx;
632 i = iyn + ix;
633 pp->set(j, (*pp)[j] + wx*wy*(*p)[i]);
634 }
635 }
636 num++;
637 sum += (*pp)[j];
638 sqsum += (*pp)[j]*(*pp)[j];
639 }
640 }
641 }
642 }
643
644 if ( verbose & VERB_DEBUG )
645 cout << "DEBUG img_polar_transform: Calculating statistics" << endl;
646
647 pp->statistics();
648
649 return pp;
650 }
651
673 Bimage* img_polar_power_spectrum(Bimage* p, int nannuli, int npsi,
674 int transform_flag, int norm_flag)
675 {
676 // Put the transform into an image structure as a new 2D data set
677 Bimage* pps = p->copy();
678
679 if ( transform_flag ) pps->fft();
680
681 if ( pps->compound_type() == TComplex ) pps->complex_to_intensities();
682
683 pps->change_type(Float);
684
685 unsigned long i, j, n, x, y;
686 long xx, yy, ix, iy, iann, ipsi, maxrad, ilarge;
687 long nlarge = npsi * ((long) (M_PI*pps->sizeX()*1.0/npsi + 1));
688 double psi_ratio = npsi*1.0/nlarge;
689 double dlarge = M_PI*2.0/nlarge;
690 double dpsi = M_PI*2.0/npsi;
691 double dann, xpoint, ypoint, wx, wy, max;
692
693 maxrad = pps->sizeX();
694 if ( maxrad < pps->sizeY() ) maxrad = pps->sizeY();
695 maxrad /= 2;
696 dann = maxrad*1.0/nannuli;
697
698 unsigned long datasize = (unsigned long) pps->images()*nannuli*npsi;
699
700 float* pdata = new float[datasize];
701 for ( i=0; i<datasize; i++ ) pdata[i] = 0;
702
703 float* avg = new float[nannuli];
704 float* mov_avg;
705
706 if ( verbose & VERB_PROCESS ) {
707 cout << "Calculating a polar power spectrum:" << endl;
708 cout << "Origin: " << pps->image[0].origin() << endl;
709 cout << "Fourier transform size: " << pps->sizeX() << " x " << pps->sizeY() << " pixels" << endl;
710 cout << "Polar power spectrum size: " << nannuli << " annuli x " << npsi << " angles" << endl;
711 cout << "Annular step size: " << dann << " pixels" << endl;
712 cout << "Angular step size: " << dpsi*180/M_PI << " degrees" << endl << endl;
713 } else if ( verbose & VERB_LABEL )
714 cout << "Calculating a polar power spectrum" << endl << endl;
715
716 if ( verbose & VERB_DEBUG )
717 cout << "DEBUG img_polar_power_spectrum: nlarge=" << nlarge << " psi_ratio=" << psi_ratio << endl;
718
719 for ( n=0; n<pps->images(); n++ ) {
720 for ( j=0; j<nannuli; j++ ) avg[j] = 0;
721 for ( iann=0; iann<nannuli; iann++ ) {
722 for ( ilarge=0; ilarge<nlarge; ilarge++ ) {
723 ipsi = (long) (ilarge*psi_ratio + 0.5);
724 if ( ipsi >= npsi ) ipsi -= npsi;
725 j = (n*nannuli + iann)*npsi + ipsi;
726 xpoint = iann*dann*bcos(dlarge*ilarge) + pps->image[n].origin().x();
727 ypoint = iann*dann*bsin(dlarge*ilarge) + pps->image[n].origin().y();
728 // cout << "%g\t%g\t%g\t%g\n", xpoint, ypoint, dlarge*ilarge, dpsi*ipsi);
729 if ( xpoint < 0 ) xpoint += pps->sizeX();
730 if ( ypoint < 0 ) ypoint += pps->sizeY();
731 if ( xpoint >= pps->sizeX() ) xpoint -= pps->sizeX();
732 if ( ypoint >= pps->sizeY() ) ypoint -= pps->sizeY();
733 x = (long) floor(xpoint);
734 y = (long) floor(ypoint);
735 for ( xx=x; xx<x+2; xx++ ) {
736 wx = 1.0 - fabs(xx - xpoint);
737 ix = xx;
738 if ( ix >= pps->sizeX() ) ix -= pps->sizeX();
739 for ( yy=y; yy<y+2; yy++ ) {
740 wy = 1.0 - fabs(yy - ypoint);
741 iy = yy;
742 if ( iy >= pps->sizeY() ) iy -= pps->sizeY();
743 i = (n*pps->sizeY() + iy)*pps->sizeX() + ix;
744 pdata[j] += wx*wy*(*pps)[i];
745 }
746 }
747 }
748 max = 0;
749 for ( ipsi=0; ipsi<npsi; ipsi++ ) {
750 j = (n*nannuli + iann)*npsi + ipsi;
751 pdata[j] *= psi_ratio;
752 if ( max < pdata[j] ) max = pdata[j];
753 avg[iann] += pdata[j];
754 }
755 avg[iann] /= npsi;
756 if ( norm_flag & 0x01 ) {
757 if ( max ) {
758 for ( ipsi=0; ipsi<npsi; ipsi++ ) {
759 j = (n*nannuli + iann)*npsi + ipsi;
760 pdata[j] /= max;
761 }
762 avg[iann] /= max;
763 }
764 }
765 }
766 if ( norm_flag & 0x02 ) {
767 mov_avg = moving_average(nannuli, avg, nannuli/4);
768 for ( iann=0; iann<nannuli; iann++ ) {
769 for ( ipsi=0; ipsi<npsi; ipsi++ ) {
770 j = (n*nannuli + iann)*npsi + ipsi;
771 pdata[j] -= mov_avg[iann];
772 }
773 }
774 delete[] mov_avg;
775 }
776 }
777
778 delete[] avg;
779
780 // Put the polar power spectrum into an image structure as a 2D data set
781 pps->sampling(dpsi, dann*p->sampling().x(), 1);
782 pps->size(npsi, nannuli, 1);
783 pps->page_size(npsi, nannuli, 1);
784 pps->data_type(Float);
785 pps->data_assign((unsigned char *) pdata);
786
787 if ( verbose & VERB_DEBUG )
788 cout << "DEBUG img_polar_power_spectrum: Calculating statistics" << endl;
789
790 pps->statistics();
791
792 return pps;
793 }
794
808 Bimage* img_polar_power_spectrum(Bimage* p, double resolution, long num_angle)
809 {
810 if ( resolution < 2*p->sampling().x() ) resolution = 2*p->sampling().x();
811
812 unsigned long max_rad = (unsigned long) (p->sizeX()*p->sampling().x()/resolution);
813 if ( max_rad > p->sizeX()/2 ) max_rad = p->sizeX()/2;
814 unsigned long max_ang = num_angle*max_rad;
815 Bimage* pps = new Bimage(Double, TSimple, max_ang, max_rad, 1, p->images());
816
817 unsigned long i, j, n, r, a;
818 long ix, ix1, iy, iy1;
819 double ang, x, y, fx, fy;
820 double v00, v01, v10, v11;
821
822 if ( verbose & VERB_FULL )
823 cout << "Calculating a radial power spectrum: " << max_rad << " annuli x " << max_ang << " angles" << endl;
824
825 for ( n=0; n<pps->images(); n++ ) {
826 for ( r=1; r<max_rad; r++ ) {
827 max_ang = num_angle*r;
828 for ( a=0; a<max_ang; a++ ) {
829 j = (n*pps->sizeY() + r)*pps->sizeX() + a;
830 // ang = a*fac/r;
831 ang = a*TWOPI/max_ang;
832 x = r*cos(ang);
833 y = r*sin(ang);
834 ix = (long) floor(x);
835 iy = (long) floor(y);
836 ix1 = ix + 1;
837 iy1 = iy + 1;
838 fx = x - ix;
839 fy = y - iy;
840 if ( ix < 0 ) ix += p->sizeX();
841 if ( ix1 < 0 ) ix1 += p->sizeX();
842 if ( iy < 0 ) iy += p->sizeY();
843 if ( iy1 < 0 ) iy1 += p->sizeY();
844 i = (n*p->sizeY() + iy)*p->sizeX() + ix;
845 v00 = (p->complex(i)).amp();
846 i = (n*p->sizeY() + iy)*p->sizeX() + ix1;
847 v01 = (p->complex(i)).amp();
848 i = (n*p->sizeY() + iy1)*p->sizeX() + ix;
849 v10 = (p->complex(i)).amp();
850 i = (n*p->sizeY() + iy1)*p->sizeX() + ix1;
851 v11 = (p->complex(i)).amp();
852 pps->set(j, (v00 - fx*(v00 - v01) - fy*(v00 - v10) + fx*fy*(v00 - v01 - v10 + v11)) * r);
853 }
854 }
855 }
856
857 return pps;
858 }
859
874 Bimage* img_polar2D(Bimage* p, int nannuli, int nseg)
875 {
876 Bimage* ppol = p->copy();
877
878 ppol->change_type(Float);
879
880 unsigned long i, j, n, x, y, z;
881 long nz, np, iann, iseg;
882 double ann, fraction;
883 double xx, yy, x2, y2, z2, dann = 1, angle;
884 Vector3<double> realsize(p->real_size());
885
886 if ( nseg < 1 ) nseg = 1;
887 if ( nseg > 360 ) nseg = 360;
888 if ( nannuli < 1 || nannuli > p->sizeX()/2 ) nannuli = p->sizeX()/2;
889 if ( p->sizeX() > 1 ) dann = realsize.x()/(2.0*nannuli);
890 if ( p->sizeY() > 1 && dann > p->sampling().y() ) dann = realsize.y()/(2.0*nannuli);
891 if ( p->sizeZ() > 1 && dann > p->sampling().z() ) dann = realsize.z()/(2.0*nannuli);
892
893 double dseg = M_PI*2.0/nseg;
894
895 unsigned long datasize = (unsigned long) ppol->images()*ppol->sizeZ()*nseg*nannuli;
896
897 float* pdata = new float[datasize];
898 float* num = new float[datasize];
899
900 for ( i=0; i<datasize; i++ ) pdata[i] = num[i] = 0;
901
902 ppol->size(nannuli, nseg, 1);
903 ppol->sampling(dann, dseg, 1);
904 ppol->data_assign((unsigned char *) pdata);
905
906 if ( verbose & VERB_PROCESS ) {
907 cout << "Calculating radial segments:" << endl;
908 cout << "First image origin: " << ppol->image[0].origin() << endl;
909 cout << "Number of annuli: " << nannuli << endl;
910 cout << "Number of segments: " << nseg << endl;
911 cout << "Annular step size: " << dann << " A" << endl;
912 cout << "Segment width: " << dseg*180.0/M_PI << " degrees" << endl << endl;
913 } else if ( verbose & VERB_LABEL )
914 cout << "Calculating radial segments" << endl << endl;
915
916 for ( n=0; n<ppol->images(); n++ ) {
917 if ( ppol->sizeZ() < 2 )
918 ppol->image[n].origin(ppol->image[n].origin().x(), ppol->image[n].origin().y(), 0);
919 for ( z=0; z<ppol->sizeZ(); z++ ) {
920 z2 = (z - ppol->image[n].origin().z())*ppol->sampling().z();
921 z2 *= z2;
922 nz = (n*ppol->sizeZ() + z)*ppol->sizeY();
923 np = (n*ppol->sizeZ() + z)*nseg;
924 for ( y=0; y<ppol->sizeY(); y++ ) {
925 yy = y2 = (y - ppol->image[n].origin().y())*ppol->sampling().y();
926 y2 *= y2;
927 for ( x=0; x<ppol->sizeX(); x++ ) {
928 xx = x2 = (x - ppol->image[n].origin().x())*ppol->sampling().x();
929 x2 *= x2;
930 ann = sqrt(x2 + y2 + z2)/dann;
931 iann = (long) ann;
932 if ( iann < nannuli ) {
933 angle = atan2(yy,xx);
934 if ( angle < 0 ) angle += TWOPI;
935 iseg = (long) floor(angle/dseg);
936 if ( iseg >= nseg ) iseg = nseg - 1;
937 j = (nz + y)*ppol->sizeX() + x;
938 i = (np + iseg)*nannuli + iann;
939 fraction = 1.0 - ann + iann;
940 num[i] += fraction;
941 pdata[i] += fraction*(*ppol)[j];
942 if ( iann < nannuli - 1 ) {
943 fraction = 1.0 - fraction;
944 i++;
945 num[i] += fraction;
946 pdata[i] += fraction*(*ppol)[j];
947 }
948 }
949 }
950 }
951 }
952 ppol->image[n].origin(0, 0, 0);
953 }
954
955 for ( i=0; i<datasize; i++ )
956 if ( num[i] ) pdata[i] /= num[i];
957
958 if ( verbose & VERB_DEBUG )
959 write_img("pol1.map", ppol);
960
961 int i0, i1, i2, i3;
962 float di;
963 float* seg = new float[nseg*2];
964
965 for ( i=0; i<nseg*2; i++ ) seg[i] = 0;
966
967 // Interpolate to fill in missing values
968 for ( n=0; n<ppol->images(); n++ ) {
969 for ( z=0; z<ppol->sizeZ(); z++ ) {
970 np = (n*ppol->sizeZ() + z)*nseg;
971 for ( iann=0; iann<nannuli; iann++ ) {
972 i0 = i1 = i2 = i3 = -1;
973 for ( iseg=0; iseg<nseg; iseg++ ) {
974 i = (np + iseg)*nannuli + iann;
975 seg[iseg] = seg[iseg+nseg] = pdata[i]; // Fill up the temporary array
976 if ( i1 < 0 && num[i] > 1e-30 ) i0 = i1 = iseg; // First value
977 if ( num[i] > 1e-30 ) i3 = iseg + nseg; // Last value
978 }
979 while ( i1 < i3 ) {
980 for ( i2=i1+1; fabs(seg[i2]) < 1e-30 && i2 < 2*nseg-1; i2++ ) ;
981 di = 1.0/(i2 - i1);
982 for ( i=i1+1; i<i2; i++ )
983 seg[i] = ((i2 - i)*seg[i1] + (i - i1)*seg[i2])*di;
984 i1 = i2;
985 }
986 for ( iseg=0; iseg<nseg; iseg++ ) {
987 i = (np + iseg)*nannuli + iann;
988 if ( iseg < i0 ) pdata[i] = seg[iseg+nseg];
989 else pdata[i] = seg[iseg];
990 }
991 }
992 }
993 }
994
995 if ( verbose & VERB_DEBUG )
996 write_img("pol2.map", ppol);
997
998 delete[] num;
999 delete[] seg;
1000
1001 return ppol;
1002 }
1003
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1408
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:321
img_polar_transform
Bimage * img_polar_transform(Bimage *p, int nannuli, int nangles, int ann_min, int ann_max)
Transforms a cartesian image to polar or cylindrical coordinates.
Definition: img_polar.cpp:573
moving_average.h
Header file moving average calculations.
bcos
double bcos(double x)
Avoid non-zero values for cos(PI/2) and cos(-PI/2).
Definition: trigonometry.cpp:27
Vector3::length
double length()
Definition: Vector3.h:198
Bimage::fft
int fft()
Definition: Bimage.h:596
utilities.h
Header file for general utilities.
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:104
verbose
int verbose
Bimage::compound_type
CompoundType compound_type()
Definition: Bimage.h:296
Float
Definition: Bimage.h:60
img_polar2D
Bimage * img_polar2D(Bimage *p, int nannuli, int nseg)
Calculates radial segment averages from an image.
Definition: img_polar.cpp:874
Vector3< float >
Matrix.h
Generalized matrix class.
kill_symmetry
int kill_symmetry(Bsymmetry *sym)
Deallocates a symmetry structure.
Definition: symmetry.cpp:206
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:99
TComplex
Definition: Bimage.h:72
Bimage::index
size_t index(size_t nx, size_t ny)
Definition: Bimage.h:325
img_set_radial_distances
int img_set_radial_distances(Bimage *p, double spherical_fraction, Bstring &symmetry_string)
Definition: img_polar.cpp:404
Bimage::interpolate
double interpolate(size_t cc, double xx, double yy, double zz, size_t nn, double fill) const
Interpolates using a given location.
Definition: Bimage.cpp:1155
Bimage::statistics
size_t statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
bsin
double bsin(double x)
Avoid non-zero values for sin(PI) and sin(-PI).
Definition: trigonometry.cpp:48
TSimple
Definition: Bimage.h:71
Bimage
General image parameter class.
Definition: Bimage.h:153
moving_average
float * moving_average(int number, float *x, int window)
Calculates a moving average over an array of data.
Definition: moving_average.cpp:28
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:400
M_PI
#define M_PI
Definition: utilities.h:51
Bimage::FOM_initialize
float * FOM_initialize()
Allocates and initializes the FOM block.
Definition: Bimage.cpp:598
Bimage::complex
Complex< double > complex(size_t j)
Returns a complex value at the given index.
Definition: Bimage.cpp:792
Bimage::sampling
void sampling(double s)
Definition: Bimage.h:403
img_radial_shells
int img_radial_shells(Bimage *p)
Calculates an image with slices representing radial shell projections.
Definition: img_polar.cpp:252
Bimage::data_assign
unsigned char * data_assign(unsigned char *nudata)
Assign image data.
Definition: Bimage.cpp:544
Bimage::FOM
float * FOM()
Definition: Bimage.h:238
img_fourier.h
General FFT for n-dimensional data.
init_point_group_symmetry
Bsymmetry * init_point_group_symmetry(Bstring symmetry_string)
Sets up a symmetry structure from a string identifier.
Definition: symmetry.cpp:38
Vector3::scalar
double scalar(const Vector3 &v) const
Definition: Vector3.h:219
Bimage::complex_to_intensities
void complex_to_intensities()
The intensities from a complex image is written to a simple image.
Definition: Bimage_complex.cpp:92
img_polar.h
Library routines for polar and spherical transformations and calculations.
trigonometry.h
Header file for trigonometry functions.
Bimage::size
Vector3< size_t > size()
Definition: Bimage.h:316
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:133
Bimage::set
void set(size_t j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:884
img_radial_sections
Bimage * img_radial_sections(Bimage *p, double rad_start, double rad_end, double rad_step, double spherical_fraction, Bstring &symmetry_string)
Calculates an image with slices giving the radial section projections.
Definition: img_polar.cpp:509
write_img
int write_img(const char *filename, Bimage *p)
General driver function to write multiple image formats This is the only image writing function that ...
Definition: rwimg.cpp:251
Bsymmetry::label
Bstring label
Definition: symmetry.h:49
Bsymmetry
Definition: symmetry.h:46
Bimage::images
size_t images()
Definition: Bimage.h:401
symmetry_get_axes
Vector3< float > * symmetry_get_axes(Bsymmetry *sym, int *n)
Get all symmetry axes.
Definition: symmetry.cpp:290
Bimage::data_size
size_t data_size()
Definition: Bimage.h:224
Bstring
Definition: Bstring.h:25
Bimage::copy
Bimage * copy()
Copies the header information and data of an image into a new image structure.
Definition: Bimage.cpp:2251
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:319
img_cartesian_to_spherical
int img_cartesian_to_spherical(Bimage *p, int nannuli, int nphi, int ntheta)
Calculates an image with spherical coordinates.
Definition: img_polar.cpp:50
Vector3::normalize
double normalize()
Definition: Vector3.h:208
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:320
radius_wrt_sym_axes
double radius_wrt_sym_axes(Vector3< float > c, int ns, Vector3< float > *vs)
Definition: img_polar.cpp:389
img_cylindrical_shells
int img_cylindrical_shells(Bimage *p)
Calculates an image with slices representing cylindrical shell projections.
Definition: img_polar.cpp:327
Bimage::page_size
Vector3< size_t > page_size()
Definition: Bimage.h:394
Double
Definition: Bimage.h:61
img_polar_power_spectrum
Bimage * img_polar_power_spectrum(Bimage *p, int nannuli, int npsi, int transform_flag, int norm_flag)
Calculates the polar power spectrum from a Fourier transform.
Definition: img_polar.cpp:673
img_radial_section
int img_radial_section(Bimage *p, Bimage *prad, unsigned long n, long zr, double rad_start, double rad_step)
Definition: img_polar.cpp:457
VERB_FULL
#define VERB_FULL
Definition: utilities.h:101
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:98
Bimage::data_type
DataType data_type()
Definition: Bimage.h:294
TWOPI
#define TWOPI
Definition: utilities.h:60
img_cartesian_to_cylindrical
int img_cartesian_to_cylindrical(Bimage *p, int nannuli, int nphi)
Calculates an image with cylindrical coordinates.
Definition: img_polar.cpp:154
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:184