| Bsoft 2.0.5 Bernard's software package

Bimage_polar.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10 #include "simplex.h"
11 #include "utilities.h"
12 #include "Matrix.h"
13
14 // Declaration of global variables
15 extern int verbose; // Level of output to the screen
16
33 Bimage* Bimage::radial(long minrad, long maxrad, double rad_step, int wrap)
34 {
35 return radial(minrad, maxrad, rad_step, 1, 0, NULL, wrap);
36 }
37
55 Bimage* Bimage::radial(long minrad, long maxrad, double rad_step, Bimage* pmask, int wrap)
56 {
57 return radial(minrad, maxrad, rad_step, 1, 0, pmask, wrap);
58 }
59
79 Bimage* Bimage::radial(long minrad, long maxrad, double rad_step,
80 double ellipticity, double angle, Bimage* pmask, int wrap)
81 {
82 long i, j, nn, xx, yy, zz, ir, nrad(0);
83 double dx, dy, dz, x2, y2, z2, a, r, f, f1;
84
85 if ( rad_step < 0.1 ) rad_step = 1;
86
87 Vector3<long> h(size()/2);
88 Vector3<double> origin;
89 Vector3<double> scale(1/rad_step, 1/rad_step, 1/rad_step);
90 if ( z < 2 ) scale[2] = 1;
91
92 if ( maxrad < minrad ) swap(minrad, maxrad);
93 if ( maxrad < 1 ) maxrad = size().max()/(2*rad_step);
94 else if ( maxrad > size().max()/(2*rad_step) ) maxrad = size().max()/(2*rad_step);
95
96 Bimage* prad = new Bimage(Float, TSimple, maxrad, 1, 1, n);
97 prad->sampling(rad_step*image->sampling()[0], 1, 1);
98
99 float* num = new float[maxrad];
100
101 if ( pmask )
102 if ( pmask->data_type() != UCharacter || pmask->minimum() != 0 || pmask->maximum() != 1 )
103 pmask->to_mask();
104
105 if ( verbose & VERB_PROCESS ) {
106 cout << "Calculating a radial profile:" << endl;
107 cout << "Minimum and maximum pixels: " << minrad << " " << maxrad << endl;
108 cout << "Radial step size: " << rad_step << endl;
109 cout << "Minimum and maximum radius: " << minrad*image->sampling()[0] << " " << maxrad*image->sampling()[0] << " A" << endl;
110 cout << "Radial step size: " << rad_step*image->sampling()[0] << " A" << endl;
111 if ( pmask )
112 cout << "Mask file: " << pmask->file_name() << endl;
113 }
114
115 if ( verbose & VERB_PROCESS )
116 cout << "Image\toriX\toriY\toriZ" << endl;
117 for ( i=nn=0; nn<n; nn++ ) {
118 for ( j=0; j<maxrad; j++ ) num[j] = 0;
119 if ( x > 1 ) origin[0] = image[nn].origin()[0];
120 if ( y > 1 ) origin[1] = image[nn].origin()[1];
121 if ( z > 1 ) origin[2] = image[nn].origin()[2];
122 // if ( (vector3_origin_to_shift(origin, size())).length() < x/10 ) wrap = 1;
123 // else wrap = 0;
124 if ( verbose & VERB_PROCESS )
125 cout << nn+1 << tab << origin << endl;
126 dz = -origin[2];
127 if ( wrap && dz < -h[2] ) dz += z;
128 for ( zz=0; zz<z; zz++, dz++ ) {
129 if ( wrap && dz > h[2] ) dz -= z;
130 z2 = dz * scale[2];
131 z2 *= z2;
132 dy = -origin[1];
133 if ( wrap && dy < -h[1] ) dy += y;
134 for ( yy=0; yy<y; yy++, dy++ ) {
135 if ( wrap && dy > h[1] ) dy -= y;
136 y2 = dy * scale[1];
137 y2 *= y2;
138 dx = -origin[0];
139 if ( wrap && dx < -h[0] ) dx += x;
140 for ( xx=0; xx<x; xx++, dx++, i++ ) if ( ( !pmask ) || ( pmask && (*pmask)[i] ) ) {
141 if ( wrap && dx > h[0] ) dx -= x;
142 x2 = dx * scale[0];
143 x2 *= x2;
144 r = sqrt(x2 + y2 + z2);
145 if ( fabs(ellipticity - 1) > 0.001 ) {
146 a = atan2(dy, dx) - angle;
147 r *= sqrt((ellipticity*ellipticity+1)/
148 (2*(ellipticity*ellipticity*cos(a)*cos(a)+
149 sin(a)*sin(a))));
150 }
151 ir = (long) r;
152 if ( ( ir >= minrad ) && ( ir < maxrad ) ) {
153 f = r - ir;
154 f1 = 1 - f;
155 j = ir + nn*maxrad; // Add for multiple images
156 num[ir] += f1;
157 prad->add(j, f1*(*this)[i]);
158 ir++;
159 if ( ir < maxrad ) {
160 j++;
161 num[ir] += f;
162 prad->add(j, f*(*this)[i]);
163 }
164 nrad++;
165 }
166 }
167 }
168 }
169 for ( j=0, ir = nn*maxrad; j<maxrad; j++, ir++ ) {
170 if ( num[j] ) {
171 prad->set(ir, (*prad)[ir]/num[j]);
172 }
173 }
174 prad->image[nn].origin(0.0,0.0,0.0);
175 }
176
177 delete[] num;
178
179 if ( verbose & VERB_PROCESS )
180 cout << "Pixels in radial averages: " << nrad << endl;
181
182 if ( verbose & VERB_DEBUG )
183 cout << "DEBUG Bimage:radial: prad size = " << prad->sizeX() << endl;
184
185 prad->statistics();
186
187 return prad;
188 }
189
190 /*
191 @brief Least squares function for the radial_fit function.
192 @param &simp a simplex structure.
193 @return double the least squares R value.
194
195 A radial profile is fitted to a reference profile using an iterative
196 simplex down-hill method. The equations solved are:
197 xref = x*m
198 yref(xref) = y(x)*a + b
199 where m is the dimension scaling (or magnification).
200 a is the amplitude scaling.
201 b is the amplitude shift.
202 The least squares function is:
203 sum(weight*(yref(xref) - y(x)*a - b)^2)
204 R = sqrt(---------------------------------------)
205 sum(weight)
206 **/
207 double radial_R(Bsimplex& simp)
208 {
209 vector<double>& y = simp.dependent_values();
210 vector<double>& yref = simp.independent_values();
211
212 int i, iref, n(0);
213 double fraction, xref, df, R(0), sum(0), weight;
214
215 for ( i=0; i<simp.points(); i++ ) {
216 xref = simp.parameter(0)*i;
217 iref = (int) xref;
218 if ( iref >= 0 && iref < simp.points() - 1 ) {
219 fraction = xref - iref;
220 df = (1.0 - fraction)*yref[iref] + fraction*yref[iref + 1]
221 - simp.parameter(1)*y[i] - simp.parameter(2);
222 // weight = i*(fabs(yref[iref]) + fabs(y[i]));
223 weight = i;
224 // weight = fabs(y[i]);
225 sum += weight;
226 R += df*df*weight;
227 n++;
228 }
229 }
230 if ( sum && n > 0.2*simp.points() ) R = sqrt(R/sum);
231 else R = 1e30; // Out of range
232
233 if ( verbose & VERB_DEBUG )
234 cout << "DEBUG radial_R: " << simp.parameter(0) << " " <<
235 simp.parameter(1) << " " << simp.parameter(2) << " R=" << R << endl;
236
237 return R;
238 }
239
254 double* Bimage::radial_fit(Bimage* pref)
255 {
256 long i, npoint(x);
257 if ( x < pref->sizeX() ) npoint = pref->sizeX();
258
259 // 3 parameters: Dimension scaling, amplitude scaling, amplitude shift
260 vector<double> ax(npoint), fx(npoint);
261 for ( i=0; i<npoint; i++ ) ax[i] = (*pref)[i];
262 for ( i=0; i<npoint; i++ ) fx[i] = (*this)[i];
263
264 Bsimplex simp(1, 3, 0, npoint, ax, fx);
265
266 // Dimension scaling estimated from the input units
267 simp.parameter(0, image->sampling()[0]/pref->sampling()[0]);
268
269 // Amplitude scaling estimated from the standard deviations
270 simp.parameter(1, 1);
271 if ( std != 0 && pref->standard_deviation() != 0 )
272 simp.parameter(1, pref->standard_deviation()/std);
273 else if ( max - min > 0 && pref->maximum() - pref->minimum() > 0 )
274 simp.parameter(1, (pref->maximum() - pref->minimum())/(max - min));
275
276 // Amplitude shift estimated from the averages
277 simp.parameter(2, pref->average() - avg*simp.parameter(1));
278 // if ( simp.parameter(2] < 1e-6 && max - min > 0 && pref->maximum() - pref->minimum() > 0 )
279 // simp.parameter(2, (pref->maximum() - pref->minimum() + max - min)/2.0;
280
281 // Parameter limits
282 simp.limits(0, 0.8*simp.parameter(0), 1.2*simp.parameter(0));
283 simp.limits(1, 0.1*simp.parameter(1), 10*simp.parameter(1));
284 simp.limits(2, simp.parameter(2) - 10*pref->standard_deviation(), simp.parameter(2) + 10*pref->standard_deviation());
285
286 if ( verbose & VERB_PROCESS ) {
287 cout << "Radial fit initial parameters:" << endl;
288 cout << "Dimension scale: " << simp.parameter(0) << endl;
289 cout << "Amplitude scale and shift: " << simp.parameter(1) << " " << simp.parameter(2) << endl;
290 }
291
292 // Do the downhill simplex iterative fit
293 double R = simp.run(10000, 1e-12*pref->standard_deviation(), radial_R) / pref->standard_deviation();
294
295 int idat;
296 double fraction, xdat, f;
297
298 if ( verbose & VERB_PROCESS ) {
299 cout << "Radial fit final parameters:" << endl;
300 cout << "Dimension scale: " << simp.parameter(0) << endl;
301 cout << "Relative dimension scale: " << simp.parameter(0)*pref->sampling()[0]/image->sampling()[0] << endl;
302 cout << "Amplitude scale and shift: " << simp.parameter(1) << " " << simp.parameter(2) << endl;
303 cout << "R: " << R << endl << endl;
304 cout << "Radial averages:" << endl;
305 cout << "Radius(A) " << file_name() << " " << pref->file_name() << endl;
306 }
307
308 if ( verbose & VERB_PROCESS ) {
309 for ( i=0; i<pref->sizeX(); i++ ) {
310 xdat = i/simp.parameter(0);
311 idat = (int) xdat;
312 if ( idat >= 0 && idat < x - 1 ) {
313 fraction = xdat - idat;
314 f = simp.parameter(1)*((1.0 - fraction)*(*this)[idat]
315 + fraction*(*this)[idat+1]) + simp.parameter(2);
316 } else {
317 f = 0;
318 }
319 cout << pref->sampling()[0]*i << " " << f << " " << (*pref)[i] << endl;
320 }
321 }
322
323 double* result = new double[simp.parameters()];
324 for ( i=0; i<simp.parameters(); i++ ) result[i] = simp.parameter(i);
325
326 return result;
327 }
328
338 Bimage* Bimage::radial_to_full(Vector3<long> nusize, Vector3<double> origin)
339 {
340 if ( nusize.volume() < 1 ) return NULL;
341
342 Bimage* p = copy_header();
343 p->data_type(Float);
344 p->size(nusize);
345 if ( p->sizeX() < 2 ) origin[0] = 0;
346 if ( p->sizeY() < 2 ) origin[1] = 0;
347 if ( p->sizeZ() < 2 ) origin[2] = 0;
348 p->data_alloc();
349
350 long i, nn, xx, yy, zz, ir, nexp(0);
351 double r, f, v;
352 Vector3<double> d;
353
354 if ( verbose ) {
355 cout << "Calculating a full image from a radial profile:" << endl;
356 cout << "Size: " << p->size() << endl;
357 cout << "Origin: " << origin << endl;
358 }
359
360 for ( nn=i=0; nn<n; nn++ ) {
361 for ( zz=0; zz<p->sizeZ(); zz++ ) {
362 d[2] = zz - origin[2];
363 for ( yy=0; yy<p->sizeY(); yy++ ) {
364 d[1] = yy - origin[1];
365 for ( xx=0; xx<p->sizeX(); xx++, i++ ) {
366 d[0] = xx - origin[0];
367 r = d.length();
368 ir = (long) r;
369 v = (*p)[i];
370 if ( ir < x ) {
371 f = 1 - r + ir;
372 v += f*(*this)[ir];
373 ir++;
374 f = 1 - f;
375 if ( ir < x ) v += f*(*this)[ir];
376 else v += f*background(nn);
377 nexp++;
378 } else {
379 v = background(nn);
380 }
381 p->set(i, v);
382 }
383 }
384 }
385 // p->image[nn].origin(origin);
386 p->image[nn].origin(origin);
387 }
388
389 if ( verbose )
390 cout << "Pixels generated: " << nexp << endl << endl;
391
392 p->statistics();
393
394 return p;
395 }
396
397
428 Bimage* Bimage::cartesian_to_spherical(long nannuli, long nphi, long ntheta)
429 {
430 long j, nn, ann, phi, theta;
431 double maxrad, scale;
432
433 maxrad = size().max()/2;
434
435 if ( nannuli < 1 ) nannuli = (long) maxrad;
436 if ( nphi < 1 ) nphi = 90;
437 if ( y < 2 ) nphi = 1;
438 if ( ntheta < 1 ) ntheta = 50;
439 if ( z < 2 ) ntheta = 1;
440
441 double dannulus(maxrad*1.0/nannuli); // Step size in each dimension
442 double dphi(TWOPI/nphi);
443 double dtheta(M_PI/ntheta);
444 double cos_phi, sin_phi, cos_theta, sin_theta;
445 Vector3<double> coor;
446 Vector3<double> u(image->sampling());
447
448 Bimage* psph = new Bimage(Float, TSimple, nannuli, nphi, ntheta, n);
449 psph->sampling(dannulus*u[0], dphi*180.0/M_PI, dtheta*180.0/M_PI);
450 u = psph->image->sampling();
451
452 if ( verbose & VERB_PROCESS ) {
453 cout << "Spherical image size: " << psph->size() << endl;
454 cout << "Step sizes: " << u[0] << " A\t"
455 << u[1] << " degree\t" << u[2] << " degree" << endl;
456 }
457
458 // Interpolate cartesian points to get spherical voxel values
459 if ( verbose & VERB_FULL )
460 cout << "Image\tOrigin" << endl;
461 for ( nn=0; nn<n; nn++ ) {
462 if ( verbose & VERB_FULL )
463 cout << nn+1 << tab << image[nn].origin() << endl;
464 for ( theta=0; theta<ntheta; theta++ ) {
465 cos_theta = dannulus*cos(dtheta*theta);
466 sin_theta = dannulus*sin(dtheta*theta);
467 for ( phi=0; phi<nphi; phi++ ) {
468 cos_phi = cos(dphi*phi);
469 sin_phi = -sin(dphi*phi);
470 for ( ann=0; ann<nannuli; ann++ ) {
471 j = psph->index(ann, phi, theta, nn);
472 scale = ann*sin_theta;
473 coor = Vector3<double>(scale*cos_phi, scale*sin_phi, ann*cos_theta);
474 coor += image[nn].origin();
475 psph->set(j, interpolate(coor, nn, 0));
476 }
477 }
478 }
479 psph->image[nn].origin(0.0, nphi/2, ntheta/2);
480 }
481
482 if ( verbose & VERB_PROCESS ) cout << endl;
483
484 if ( verbose & VERB_DEBUG )
485 cout << "DEBUG Bimage::cartesian_to_spherical: Calculating statistics" << endl;
486
487 statistics();
488
489 return psph;
490 }
491
519 Bimage* Bimage::cartesian_to_cylindrical(long nannuli, long nphi, int flag)
520 {
521 long j, nn, zz, ann, phi;
522 double maxrad;
523
524 maxrad = x/2; // Maximum radius taken from largest x and y dimension
525 if ( maxrad < y/2 ) maxrad = y/2;
526
527 if ( nannuli < 1 ) nannuli = (long) maxrad;
528 if ( nphi < 1 ) nphi = 90;
529 if ( y < 2 ) nphi = 1;
530
531 double dannulus(maxrad*1.0/nannuli); // Step size in each dimension
532 double dphi(TWOPI/nphi);
533 double cos_phi, sin_phi;
534 Vector3<double> coor;
535 Vector3<double> u(image->sampling());
536
537 Bimage* pcyl;
538
539 switch ( flag ) {
540 case 0:
541 pcyl = new Bimage(Float, TSimple, nannuli, nphi, z, n);
542 pcyl->sampling(dannulus*u[0], dphi*180.0/M_PI, u[2]);
543 break;
544 case 1:
545 pcyl = new Bimage(Float, TSimple, nphi, nannuli, z, n);
546 pcyl->sampling(dphi*180.0/M_PI, dannulus*u[0], u[2]);
547 break;
548 case 2:
549 pcyl = new Bimage(Float, TSimple, z, nannuli, nphi, n);
550 pcyl->sampling(u[2], dannulus*u[0], dphi*180.0/M_PI);
551 break;
552 default:
553 cerr << "Bimage::cartesian_to_cylindrical: flag = " << flag << " not supported!" << endl;
554 return NULL;
555 }
556
557 if ( verbose & VERB_PROCESS ) {
558 cout << "Cylindrical image size: " << pcyl->size() << endl;
559 cout << "Step sizes: " << dannulus*image->sampling()[0] << " A\t"
560 << dphi*180.0/M_PI << " degree" << endl;
561 }
562
563 // Interpolate cartesian points to get spherical voxel values
564 if ( verbose & VERB_FULL )
565 cout << "Image\tOrigin" << endl;
566 for ( nn=0; nn<n; nn++ ) {
567 if ( verbose & VERB_FULL )
568 cout << nn+1 << tab << image[nn].origin() << endl;
569 for ( zz=0; zz<z; zz++ ) {
570 coor[2] = zz;
571 for ( phi=0; phi<nphi; phi++ ) {
572 cos_phi = cos(dphi*phi);
573 sin_phi = sin(dphi*phi);
574 for ( ann=0; ann<nannuli; ann++ ) {
575 switch ( flag ) {
576 case 0: j = pcyl->index(ann, phi, zz, nn); break;
577 case 1: j = pcyl->index(phi, ann, zz, nn); break;
578 case 2: j = pcyl->index(zz, ann, phi, nn); break;
579 default: j=0;
580 }
581 coor[0] = ann*cos_phi + image[nn].origin()[0];
582 coor[1] = ann*sin_phi + image[nn].origin()[1];
583 pcyl->set(j, interpolate(coor, nn, 0));
584 }
585 }
586 }
587 if ( flag < 1 )
588 // pcyl->image[nn].origin(0, nphi/2, image[nn].origin()[2]);
589 pcyl->image[nn].origin(0.0, nphi/2, image[nn].origin()[2]);
590 else
591 // pcyl->image[nn].origin(nphi/2, 0, image[nn].origin()[2]);
592 pcyl->image[nn].origin(nphi/2, 0.0, image[nn].origin()[2]);
593 }
594
595 if ( verbose & VERB_PROCESS ) cout << endl;
596
597 if ( verbose & VERB_DEBUG )
598 cout << "DEBUG Bimage::cartesian_to_cylindrical: Calculating statistics" << endl;
599
600 statistics();
601
602 return pcyl;
603 }
604
626 Bimage* Bimage::polar_transform(long nangles, long ann_min, long ann_max,
627 long dann, long zmin, long zmax, long zinc)
628 {
629 change_type(Float);
630
631 if ( dann < 1 ) dann = 1;
632 if ( ann_min >= x/2 ) ann_min = x/2;
633 if ( ann_max < 1 || ann_max >= x/2 ) ann_max = x/2;
634 if ( ann_max >= y/2 ) ann_max = y/2;
635 if ( ann_min > ann_max ) swap(ann_min, ann_max);
636 if ( ann_min == ann_max ) ann_max = ann_min + dann;
637
638 if ( zinc < 1 ) zinc = 1;
639 if ( zmin > zmax ) swap(zmin, zmax);
640 if ( zmin == zmax ) zmax = zmin + zinc;
641 if ( zmax >= z ) zmax = z - 1;
642
643 long i, ann, ang, r, zz, iz;
644 long nannuli((ann_max - ann_min)/dann + 1);
645 long nz((zmax - zmin)/zinc + 1);
646 double a, cosa, sina;
647 double dang(M_PI*2.0/nangles);
648 Vector3<double> coor;
649
650 Bimage* p = new Bimage(Float, TSimple, nangles, nannuli, nz, 1);
651
652 if ( verbose & VERB_PROCESS ) {
653 cout << "Calculating a polar image from " << file_name() << endl;
654 cout << "Image size: " << nangles << " x " << nannuli << " x " << nz << endl;
655 cout << "Angular step size: " << dang*180/M_PI << " degrees" << endl;
656 cout << "Annular range: " << ann_min << " - " << ann_max << " pixels" << endl;
657 cout << "Annular step size: " << dann << " pixels" << endl;
658 cout << "Z range: " << zmin << " - " << zmax << " pixels" << endl;
659 cout << "Z step size: " << zinc << " pixels" << endl << endl;
660 } else if ( verbose & VERB_LABEL )
661 cout << "Calculating a polar image" << endl << endl;
662
663 for ( i=0, zz=zmin; zz<=zmax; zz+=zinc ) {
664 for ( ann=ann_min; ann<=ann_max; ann+=dann ) {
665 for ( ang=0; ang<nangles; ang++, i++ ) {
666 a = dang*ang;
667 cosa = cos(a);
668 sina = sin(a);
669 for ( iz=zz; iz<zz+zinc; iz++ ) {
670 for ( r=ann; r<ann+dann; r++ ) {
671 coor[0] = r*cosa + image->origin()[0];
672 coor[1] = r*sina + image->origin()[1];
673 coor[2] = iz;
674 p->add(i, interpolate(coor));
675 }
676 }
677 }
678 }
679 }
680
681 if ( verbose & VERB_DEBUG )
682 cout << "DEBUG Bimage::polar_transform: Calculating statistics" << endl;
683
684 p->statistics();
685
686 return p;
687 }
688
701 Bimage* Bimage::polar_power_spectrum(double resolution, long num_angle)
702 {
703 if ( resolution < 2*image->sampling()[0] ) resolution = 2*image->sampling()[0];
704
705 long max_rad = (long) (x*image->sampling()[0]/resolution);
706 if ( max_rad > x/2 ) max_rad = x/2;
707 long max_ang = num_angle*max_rad;
708 Bimage* pps = new Bimage(Double, TSimple, max_ang, max_rad, 1, n);
709
710 long j, nn, r, a;
711 double ang, xx, yy, fac;
712
713 if ( verbose & VERB_FULL )
714 cout << "Calculating a radial power spectrum: " << max_rad << " annuli x " << max_ang << " angles" << endl;
715
716 for ( nn=0; nn<n; nn++ ) {
717 for ( r=1; r<max_rad; r++ ) {
718 max_ang = num_angle*r;
719 fac = TWOPI/max_ang;
720 for ( a=0; a<max_ang; a++ ) {
721 j = (nn*pps->sizeY() + r)*pps->sizeX() + a;
722 ang = a*fac;
723 xx = r*cos(ang);
724 yy = r*sin(ang);
725 pps->set(j, interpolate_wrap(xx, yy, 0, nn));
726 }
727 }
728 }
729
730 return pps;
731 }
732
741 int Bimage::line_powerspectra(fft_plan plan)
742 {
743 long i, is, isx, xx, yy, zz;
744 double sum;
745 Complex<float>* data = new Complex<float>[x];
746
747 // cout << "Doing 1D transforms" << endl;
748
749 for ( is=zz=0; zz<z; zz++ ) {
750 for ( yy=0; yy<y; yy++, is++ ) {
751 isx = is*x;
752 for ( xx=0, i=isx; xx<x; xx++, i++ )
753 data[xx] = Complex<float>((*this)[i], 0);
754 fftw(plan, data);
755 set(isx, 0); // Zero order
756 for ( xx=1, i=isx+1, sum=0; xx<x; xx++, i++ ) {
757 set(i, data[xx].power());
758 sum += (*this)[i];
759 }
760 if ( sum ) for ( xx=1, i=isx+1; xx<x; xx++, i++ )
761 set(i, (*this)[i]/sum);
762 }
763 }
764
765 delete[] data;
766
767 return 0;
768 }
769
783 int Bimage::radial_shells()
784 {
785 change_type(Float);
786
787 long i, j, nn, xx, yy, zz;
788 long rz;
789 double dx2, dy2, dz, dz2, d2, oldz, fraction;
790
791 float* shell = new float[datasize];
792
793 if ( verbose & ( VERB_PROCESS | VERB_LABEL ) )
794 cout << "Converting to radial shells" << endl << endl;
795
796 // Interpolate cartesian points to get spherical voxel values
797 if ( verbose & VERB_FULL )
798 cout << "Image\tOrigin" << endl;
799 for ( j=nn=0; nn<n; nn++ ) {
800 if ( verbose & VERB_FULL )
801 cout << nn+1 << tab << image[nn].origin() << endl;
802 for ( zz=0; zz<z; zz++ ) {
803 dz = zz - image[nn].origin()[2];
804 dz2 = dz*dz;
805 for ( yy=0; yy<y; yy++ ) {
806 dy2 = yy - image[nn].origin()[1];
807 dy2 *= dy2;
808 for ( xx=0; xx<x; xx++, j++ ) {
809 dx2 = xx - image[nn].origin()[0];
810 dx2 *= dx2;
811 d2 = dz2 - dy2 - dx2;
812 if ( d2 >= 0 ) {
813 if ( dz < 0 ) oldz = image[nn].origin()[2] - sqrt(d2);
814 else oldz = image[nn].origin()[2] + sqrt(d2);
815 rz = (long) oldz;
816 if ( rz >= 0 && rz < z ) {
817 fraction = 1 + rz - oldz;
818 i = index(0,xx,yy,rz,nn);
819 shell[j] = fraction*(*this)[i];
820 rz++;
821 if ( rz < z ) {
822 fraction = 1 - fraction;
823 i += y*x;
824 shell[j] += fraction*(*this)[i];
825 }
826 }
827 }
828 }
829 }
830 }
831 }
832
833 if ( verbose & VERB_FULL ) cout << "" << endl;
834
835 data_assign((unsigned char *) shell);
836
837 statistics();
838
839 return 0;
840 }
841
855 int Bimage::cylindrical_shells()
856 {
857 change_type(Float);
858
859 long i, j, nn, xx, yy, zz;
860 long ry;
861 double dx, dy, dx2, dy2, d2, oldy, fraction;
862
863 float* shell = new float[datasize];
864
865 if ( verbose & ( VERB_PROCESS | VERB_LABEL ) )
866 cout << "Converting to cylindrical shells" << endl << endl;
867
868 // Interpolate cartesian points to get cylindrical voxel values
869 if ( verbose & VERB_FULL )
870 cout << "Image\tOrigin" << endl;
871 for ( j=nn=0; nn<n; nn++ ) {
872 if ( verbose & VERB_FULL )
873 cout << nn+1 << tab << image[nn].origin() << endl;
874 for ( zz=0; zz<z; zz++ ) {
875 // dz = zz - image[nn].origin()[2];
876 // dz2 = dz*dz;
877 for ( yy=0; yy<y; yy++ ) {
878 dy = yy - image[nn].origin()[1];
879 dy2 = dy*dy;
880 for ( xx=0; xx<x; xx++, j++ ) {
881 dx = xx - image[nn].origin()[0];
882 dx2 = dx*dx;
883 d2 = dy2 - dx2;
884 if ( dy2 >= dx2 ) {
885 if ( dy < 0 ) oldy = image[nn].origin()[1] - sqrt(d2);
886 else oldy = image[nn].origin()[1] + sqrt(d2);
887 ry = (long) oldy;
888 if ( ry >= 0 && ry < y ) {
889 fraction = 1 + ry - oldy;
890 i = index(0,xx,ry,zz,nn);
891 shell[j] = fraction*(*this)[i];
892 ry++;
893 if ( ry < y ) {
894 fraction = 1 - fraction;
895 i += x;
896 shell[j] += fraction*(*this)[i];
897 }
898 }
899 }
900 }
901 }
902 }
903 }
904
905 if ( verbose & VERB_FULL ) cout << endl;
906
907 data_assign((unsigned char *) shell);
908
909 statistics();
910
911 return 0;
912 }
913
914 double radius_wrt_sym_axes(Vector3<double> coor, long ns, Vector3<double>* vs)
915 {
916 int i;
917 double r, rmax(0);
918 Vector3<double> v(coor);
919 v.normalize();
920
921 for ( i=0; i<ns; i++ ) {
922 r = v.scalar(vs[i]);
923 if ( rmax < r ) rmax = r;
924 }
925
926 return rmax;
927 }
928
929 int Bimage::set_radial_distances(double spherical_fraction, Bsymmetry* sym)
930 {
931 change_type(Float);
932
933 long i, xx, yy, zz, nn;
934 double r, rf;
935 Vector3<double> coor;
936
937 long ns(0);
938 Vector3<double>* vs = symmetry_get_axes(sym, ns);
939 if ( !vs ) return -1;
940
941 if ( !sym || ns < 2 ) spherical_fraction = 1;
942
943 if ( verbose ) {
944 cout << "Calculating radial distances:" << endl;
945 if ( sym )
946 cout << "Symmetry: " << sym->label << " (" << ns << ")" << endl;
947 cout << "Spherical fraction: " << spherical_fraction << endl;
948 }
949
950 next = new Bimage(Float, TSimple, size(), n);
951
952 for ( i=nn=0; nn<n; nn++ ) {
953 for ( zz=0; zz<z; zz++ ) {
954 coor[2] = zz - image[nn].origin()[2];
955 for ( yy=0; yy<y; yy++ ) {
956 coor[1] = yy - image[nn].origin()[1];
957 for ( xx=0; xx<x; xx++, i++ ) {
958 coor[0] = xx - image[nn].origin()[0];
959 r = coor.length();
960 rf = 1;
961 if ( ns > 1 ) {
962 rf = radius_wrt_sym_axes(coor, ns, vs);
963 rf = rf + spherical_fraction*(1 - rf);
964 r = r*rf;
965 }
966 next->set(i, r);
967 }
968 }
969 }
970 }
971
972 delete[] vs;
973
974 return 0;
975 }
976
977 int Bimage::radial_section(Bimage* prad, long nn,
978 long zr, double rad_start, double rad_step)
979 {
980 long j, j1, xx, yy, zz, zj;
981 long slice_size = x*y;
982 long image_size = slice_size*z;
983 long i = (long) (nn*prad->size().volume() + zr*slice_size);
984 double r = rad_step*zr + rad_start;
985 double dr, drp;
986
987 for ( yy=0; yy<y; yy++ ) {
988 for ( xx=0; xx<prad->sizeX(); xx++, i++ ) {
989 j = nn*image_size + yy*x + xx;
990 for ( zz=0, zj=z+1, drp=1; zz<z && zj>=z; zz++, j+=slice_size ) {
991 dr = (*next)[j] - r;
992 if ( dr > 0 && drp <= 0 ) zj = zz;
993 drp = dr;
994 }
995 if ( zj < z ) {
996 j1 = nn*image_size + zj*slice_size + yy*x + xx;
997 j = j1 - slice_size;
998 dr = ((*next)[j1] - r)/((*next)[j1] - (*next)[j]);
999 prad->set(i, dr*(*this)[j]);
1000 dr = 1 - dr;
1001 prad->add(i, dr*(*this)[j1]);
1002 }
1003 }
1004 }
1005
1006 return 0;
1007 }
1008
1027 Bimage* Bimage::radial_sections(double rad_start, double rad_end, double rad_step,
1028 double spherical_fraction, Bsymmetry* sym)
1029 {
1030 if ( rad_start < 0 ) rad_start = 0;
1031 if ( rad_start >= z/2 ) rad_start = z/2;
1032 if ( rad_end <= 0 ) rad_end = z/2;
1033 if ( rad_end >= z/2 ) rad_end = z/2 - 1;
1034 if ( rad_end < rad_start ) rad_end = rad_start;
1035 if ( rad_step <= 0 ) rad_step = 1;
1036
1037 if ( set_radial_distances(spherical_fraction, sym) < 0 )
1038 return NULL;
1039
1040 long nn, nz = (long) ((rad_end - rad_start)/rad_step + 1);
1041
1042 if ( verbose ) {
1043 cout << "Calculating radial shells:" << endl;
1044 cout << "Radial range: " << rad_start << " - " << rad_end << endl;
1045 cout << "Radial step size: " << rad_step << endl;
1046 cout << "New image size: " << x << " x " << y << " x " << nz << " x " << n << endl << endl;
1047 }
1048
1049 Bimage* prad = new Bimage(Float, TSimple, x, y, nz, n);
1050 prad->sampling(sampling()[0], sampling()[1], sampling()[2] * rad_step);
1051
1052 for ( nn=0; nn<n; nn++ ) {
1053 prad->image[nn] = image[nn];
1054 // prad->image[nn].origin(prad->image[nn].origin()[0], prad->image[nn].origin()[1], -rad_start);
1055 prad->image[nn].origin(prad->image[nn].origin()[0], prad->image[nn].origin()[1], -rad_start);
1056 #ifdef HAVE_GCD
1057 dispatch_apply(nz, dispatch_get_global_queue(0, 0), ^(size_t zz){
1058 radial_section(prad, nn, zz, rad_start, rad_step);
1059 });
1060 #else
1061 #pragma omp parallel for
1062 for ( long zz=0; zz<nz; zz++ )
1063 radial_section(prad, nn, zz, rad_start, rad_step);
1064 #endif
1065 }
1066
1067 prad->statistics();
1068
1069 return prad;
1070 }
1071
1079 Bimage* Bimage::radial_coverage(double threshold, double rad_step)
1080 {
1081 if ( rad_step <= 0 ) rad_step = 1;
1082
1083 to_mask(threshold);
1084
1085 Bimage* prad = radial(0, x/2, rad_step);
1086
1087 if ( verbose ) {
1088 cout << "Calculating radial shell coverage:" << endl;
1089 cout << "Threshold: " << threshold << endl;
1090 cout << "Radial step size: " << rad_step << endl;
1091 cout << "Radius\tCoverage" << endl;
1092 }
1093
1094 long i, xx, nn;
1095
1096 for ( i=nn=0; nn<n; nn++ ) {
1097 for ( xx=0; xx<prad->x; ++xx, ++i )
1098 cout << xx << tab << (*prad)[i] << endl;
1099 }
1100
1101 delete prad;
1102
1103 return 0;
1104 }
1105
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bimage::copy_header
Bimage * copy_header()
Definition: Bimage.h:650
Vector3::normalize
double normalize()
Definition: Vector3.h:236
Bimage.h
Header file for image class.
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
Vector3::length
double length()
Definition: Vector3.h:222
Bimage::add
void add(long j, double v)
Definition: Bimage.h:308
Bimage::file_name
string & file_name()
Definition: Bimage.h:231
Bimage::image_size
long image_size()
Definition: Bimage.h:267
Bimage::radial_to_full
Bimage * radial_to_full(Vector3< long > nusize, Vector3< double > origin)
Generates a full 2D or 3D image from a radial profile in a 1D image.
Definition: Bimage_polar.cpp:338
utilities.h
Header file for general utilities.
Bsimplex
Structure used in the downhill simplex method.
Definition: simplex.h:42
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
Bimage::interpolate_wrap
double interpolate_wrap(long cc, double xx, double yy=0, double zz=0, long nn=0) const
Interpolates using a given location with wrapping.
Definition: Bimage.cpp:1502
Bsimplex::parameter
void parameter(long i, double p)
Definition: simplex.h:69
Bimage::index
long index(long nx, long ny) const
Definition: Bimage.h:383
Bsimplex::dependent_values
vector< double > & dependent_values()
Definition: simplex.h:83
Bimage::polar_transform
Bimage * polar_transform(long nangles, long ann_min, long ann_max, long dann, long zmin, long zmax, long zinc)
Calculates an image with cylindrical coordinates by integration.
Definition: Bimage_polar.cpp:626
Matrix.h
Generalized matrix class.
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bimage::file_name
void file_name(string s)
Definition: Bimage.h:230
Bimage::Bimage
Bimage()
Initializes an image.
Definition: Bimage.cpp:44
Bimage::interpolate
double interpolate(long cc, double xx, double yy=0, double zz=0, long nn=0, double fill=0) const
Interpolates using a given location.
Definition: Bimage.cpp:1392
radius_wrt_sym_axes
double radius_wrt_sym_axes(Vector3< double > coor, long ns, Vector3< double > *vs)
Definition: Bimage_polar.cpp:914
Bsimplex::run
double run(long maxcycles, double tolerance, double(funk)(Bsimplex &))
Definition: simplex.cpp:76
verbose
int verbose
TSimple
Definition: Bimage.h:58
Float
Definition: utilities.h:157
Bimage::sizeX
long sizeX() const
Definition: Bimage.h:380
Vector3::max
Type max()
Definition: Vector3.h:175
Bimage
General image parameter class.
Definition: Bimage.h:163
Bimage::power
void power(double v)
Calculates the power of an image.
Definition: Bimage.cpp:3288
Bimage::data_alloc
unsigned char * data_alloc()
Definition: Bimage.h:256
Bsimplex::independent_values
vector< double > & independent_values()
Definition: simplex.h:82
M_PI
#define M_PI
Definition: utilities.h:59
Bsimplex::points
long points()
Definition: simplex.h:64
Bimage::maximum
double maximum()
Definition: Bimage.h:535
Double
Definition: utilities.h:158
Vector3::scalar
double scalar(const Vector3 &v) const
Definition: Vector3.h:247
Bimage::statistics
long statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
Bimage::radial_sections
Bimage * radial_sections(double rad_start, double rad_end, double rad_step, double spherical_fraction, Bsymmetry *sym)
Calculates an image with slices giving the radial section projections.
Definition: Bimage_polar.cpp:1027
Bimage::radial_fit
double * radial_fit(Bimage *pref)
Fits a radial profile to a reference radial profile.
Definition: Bimage_polar.cpp:254
Bimage::data_assign
unsigned char * data_assign(unsigned char *nudata)
Assign image data.
Definition: Bimage.cpp:852
fft_plan
fftwf_plan fft_plan
Definition: fft.h:16
symmetry_get_axes
Vector3< double > * symmetry_get_axes(Bsymmetry *sym, long &nax)
Get all symmetry axes.
Definition: symmetry.cpp:379
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::sum
void sum(long m, Bimage **p)
Sums an array of images with their FOM blocks.
Definition: Bimage_combine.cpp:23
Bimage::size
Vector3< long > size() const
Definition: Bimage.h:373
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:127
Bsub_image::sampling
void sampling(double x, double y, double z)
Definition: Bimage.h:123
Bimage::standard_deviation
double standard_deviation()
Definition: Bimage.h:537
Bsymmetry::label
Bstring label
Definition: symmetry.h:41
Bimage::set
void set(long j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:1096
Bsymmetry
Definition: symmetry.h:38
Bimage::cartesian_to_spherical
Bimage * cartesian_to_spherical(long nannuli, long nphi, long ntheta)
Calculates an image with spherical coordinates.
Definition: Bimage_polar.cpp:428
Bimage::next
Bimage * next
Definition: Bimage.h:165
Bimage::to_mask
long to_mask()
Definition: Bimage.h:1299
Complex
Definition: Complex.h:23
Bimage::shell
int shell(Vector3< double > center, double minrad, double maxrad, double width, int fill_type=0, double fill=0)
Fills a shell within an image with a uniform value.
Definition: Bimage_edit.cpp:544
simplex.h
Nelder and Mead downhill simplex method for generalized parameter fitting.
UCharacter
Definition: utilities.h:149
Bimage::sizeX
void sizeX(long nx)
Definition: Bimage.h:377
Bimage::sizeZ
void sizeZ(long nz)
Definition: Bimage.h:379
Vector3< long >
Bsimplex::parameters
long parameters()
Definition: simplex.h:65
radial_R
double radial_R(Bsimplex &simp)
Definition: Bimage_polar.cpp:207
fftw
int fftw(fft_plan plan, Complex< float > *a)
Fast Fourier transforms a data array.
Definition: fft.cpp:106
Bimage::cylindrical_shells
int cylindrical_shells()
Calculates an image with slices representing cylindrical shell projections.
Definition: Bimage_polar.cpp:855
Bimage::radial_shells
int radial_shells()
Calculates an image with slices representing radial shell projections.
Definition: Bimage_polar.cpp:783
Bimage::average
double average(long cc, double xf, double yf, double zf, long nn, double iscale)
Averages in 3D when scaling is less than 1.
Definition: Bimage.cpp:1349
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
Bimage::radial_coverage
Bimage * radial_coverage(double threshold, double rad_step=1)
Calculates the coverage in each radial shell.
Definition: Bimage_polar.cpp:1079
Bimage::line_powerspectra
int line_powerspectra(fft_plan plan)
Calculates the 1D power spectrum of each line in an image.
Definition: Bimage_polar.cpp:741
Vector3::volume
double volume()
Definition: Vector3.h:235
Bimage::radial
Bimage * radial(long minrad, long maxrad, double rad_step=1, int wrap=0)
Calculates the radial average of an image.
Definition: Bimage_polar.cpp:33
VERB_FULL
#define VERB_FULL
Definition: utilities.h:109
Bimage::background
double background(long nn)
Definition: Bimage.h:542
Bimage::sizeY
void sizeY(long ny)
Definition: Bimage.h:378
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:106
Bimage::data_type
DataType data_type()
Definition: Bimage.h:349
Bsimplex::limits
void limits(long i, double vlo, double vhi)
Definition: simplex.h:75
Bimage::minimum
double minimum()
Definition: Bimage.h:534
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