| 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_helix.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10 #include "img_helix.h"
11 #include "mg_reconstruct.h"
12 #include "matrix_linear.h"
13 #include "trigonometry.h"
14 #include "symmetry.h"
15 #include "utilities.h"
16
17 // Declaration of global variables
18 extern int verbose; // Level of output to the screen
19
20
37 Bplot* img_find_helix_parameters(Bimage* p, double angle_start, double angle_end, double angle_step,
38 int bin, double hires, double lores, double radius)
39 {
40 angle_step = fabs(angle_step);
41 if ( angle_step < 0.0001 ) angle_step = 0.0001;
42 if ( angle_start > angle_end ) swap(angle_start, angle_end);
43
44 if ( bin < 1 ) bin = 1;
45 if ( bin > 4 ) bin = 4;
46
47 if ( lores > 0 && hires > lores ) swap(hires, lores);
48 if ( hires < 2*bin*p->sampling().x() ) hires = 2*bin*p->sampling().x();
49 if ( lores < hires ) lores = p->size().x()*p->sampling().x();
50
51 if ( radius < 1 ) radius = p->sizeX()/2;
52 if ( radius > p->image->origin().x() ) radius = p->image->origin().x();
53 if ( radius > p->sizeX() - p->image->origin().x() ) radius = p->sizeX() - p->image->origin().x();
54 if ( radius > p->image->origin().y() ) radius = p->image->origin().y();
55 if ( radius > p->sizeY() - p->image->origin().y() ) radius = p->sizeY() - p->image->origin().y();
56
57 size_t i, j, na, max_iter(10);
58 double rise, angle, offset, bestrise(0), bestangle(0);
59 double cc, dd, bestcc(0), mincc(1);
60
61 Bimage* pt;
62
63 if ( verbose ) {
64 cout << "Searching for helical parameters by cross-correlation:" << endl;
65 cout << "Angular range " << angle_start*180.0/M_PI << " - "
66 << angle_end*180.0/M_PI << " degrees" << endl;
67 cout << "Angular increment: " << angle_step*180.0/M_PI << " degrees" << endl;
68 cout << "Resolution limits: " << hires << " - " << lores << " A" << endl;
69 cout << "Radius: " << radius << endl;
70 cout << "Binning: " << bin << endl << endl;
71 }
72
73 radius /= bin;
74 angle_end += angle_step/2; // To ensure the final angle is sampled
75
76 for ( na=0, angle = angle_start; angle <= angle_end; angle += angle_step ) na++;
77
78 Bimage* pb = p->copy();
79 pb->integer_interpolation(bin, 42);
80 pb->calculate_background();
81
82 if ( verbose & VERB_DEBUG )
83 cout << "DEBUG img_find_helix_parameters: binned size = " << pb->size() << endl;
84
85 Vector3<size_t> size(pb->size());
86 Vector3<double> origin(pb->image->origin());
87 Vector3<double> bestorigin, scale(1,1,1), translate, axis(0,0,1);
88 Vector3<size_t> mask_size((size_t) (2*radius), (size_t) (2*radius), (pb->sizeZ()*3)/4);
89 Vector3<double> mask_start(pb->image->origin().x() - radius, pb->image->origin().y() - radius, pb->sizeZ()/8);
90 Matrix3 mat;
91 Vector3<double> shift;
92
93 Bstring title("Helical parameter search");
94 int ncol(3);
95 Bplot* plot = new Bplot(1, na, 3);
96 plot->title(title);
97 plot->page(0).title(title);
98 plot->page(0).columns(3);
99 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
100 plot->page(0).column(0).label("Rise (A)");
101 plot->page(0).column(0).axis(1);
102 plot->page(0).column(1).type(4);
103 plot->page(0).column(1).label("Rotation angle (degrees)");
104 plot->page(0).column(1).axis(3);
105 plot->page(0).column(2).type(4);
106 plot->page(0).column(2).label("CC");
107 plot->page(0).column(2).axis(5);
108 plot->page(0).axis(3).min(angle_start*180.0/M_PI);
109 plot->page(0).axis(3).max(angle_end*180.0/M_PI);
110
111 if ( verbose )
112 cout << "Rise\tAngle\tOffset\tCC" << endl;
113 for ( i=0, angle = angle_start; angle <= angle_end; angle += angle_step, i++ ) {
114 mat = Matrix3(axis, angle);
115 translate = 0;
116 shift[2] = 1;
117 dd = 1;
118 for ( j=0; j<max_iter && fabs(shift.z()) > 0.001; j++ ) {
119 pt = pb->transform(size, scale, origin, translate, mat, FILL_BACKGROUND, 0);
120 // write_img("t.pif", pt);
121 pt->edge(2, mask_size, mask_start, 2, FILL_BACKGROUND, 0);
122 shift = pb->find_shift(pt, NULL, hires, lores, pb->sizeZ()/4.0, 0, 1, cc);
123 delete pt;
124 if ( fabs(shift.z()) > 0.001 ) {
125 translate[2] += dd*shift.z();
126 // cout << angle*180.0/M_PI << tab << shift << tab << translate.z() << tab << cc << endl;
127 }
128 dd *= 0.9;
129 }
130 rise = pb->sampling().z()*translate.z();
131 offset = pb->sampling().z()*sqrt(translate.x()*translate.x() + translate.y()*translate.y());
132 (*plot)[i] = rise;
133 (*plot)[i+na] = angle*180.0/M_PI;
134 (*plot)[i+2*na] = cc;
135 if ( bestcc < cc ) {
136 bestcc = cc;
137 bestangle = angle;
138 bestrise = rise;
139 }
140 if ( mincc > cc ) mincc = cc;
141 if ( verbose )
142 cout << setprecision(6) << rise << tab << angle*180.0/M_PI
143 << tab << offset << tab << cc << endl << flush;
144 }
145
146 delete pb;
147
148 if ( bestrise < 0 ) {
149 bestrise = -bestrise;
150 bestangle = -bestangle;
151 }
152
153 if ( verbose ) {
154 cout << "Best helical rise: " << bestrise << " A" << endl;
155 cout << "Best helical rotation angle: " << bestangle*180.0/M_PI << " degrees" << endl;
156 cout << "Best correlation coefficient: " << bestcc << endl << endl;
157 }
158
159 Bstring txt;
160
161 txt = Bstring(bestrise, "Best helical rise: %g A");
162 plot->page(0).add_text(txt);
163 txt = Bstring(bestangle*180.0/M_PI, "Best helical rotation angle: %g degrees");
164 plot->page(0).add_text(txt);
165 txt = Bstring(bestcc, "Best correlation coefficient: %g");
166 plot->page(0).add_text(txt);
167 txt = Bstring(mincc, "Minimum correlation coefficient: %g");
168 plot->page(0).add_text(txt);
169
170 return plot;
171 }
172
189 Bplot* img_find_helix_parameters(Bimage* p, double rise_start, double rise_end,
190 double rise_step, double angle_start, double angle_end, double angle_step,
191 int bin, double radius)
192 {
193 rise_step = fabs(rise_step);
194 if ( rise_step < 0.001 ) rise_step = 0.001;
195 if ( rise_start > rise_end ) swap(rise_start, rise_end);
196
197 angle_step = fabs(angle_step);
198 if ( angle_step < 0.0001 ) angle_step = 0.0001;
199 if ( angle_start > angle_end ) swap(angle_start, angle_end);
200
201 if ( bin < 1 ) bin = 1;
202 if ( bin > 4 ) bin = 4;
203
204 if ( radius < 1 ) radius = p->sizeX()/2;
205 if ( radius > p->image->origin().x() ) radius = p->image->origin().x();
206 if ( radius > p->sizeX() - p->image->origin().x() ) radius = p->sizeX() - p->image->origin().x();
207 if ( radius > p->image->origin().y() ) radius = p->image->origin().y();
208 if ( radius > p->sizeY() - p->image->origin().y() ) radius = p->sizeY() - p->image->origin().y();
209
210 unsigned long i, na;
211 double rise, angle, bestrise(0), bestangle(0);
212 double cc, bestcc(0), mincc(1);
213
214 Bimage* pt;
215
216 if ( verbose ) {
217 cout << "Searching for helical parameters:" << endl;
218 cout << "Rise range " << rise_start << " - "
219 << rise_end << " A" << endl;
220 cout << "Rise increment: " << rise_step << " A" << endl;
221 cout << "Angular range " << angle_start*180.0/M_PI << " - "
222 << angle_end*180.0/M_PI << " degrees" << endl;
223 cout << "Angular increment: " << angle_step*180.0/M_PI << " degrees" << endl;
224 cout << "Binning: " << bin << endl;
225 // cout << "Resolution limits: " << hires << " - " << lores << " A" << endl;
226 cout << "Radius: " << radius << endl << endl;
227 }
228
229 radius /= bin;
230 rise_end += rise_step/2;
231 angle_end += angle_step/2; // To ensure the final angle is sampled
232
233 for ( na=0, rise = rise_start; rise < rise_end; rise += rise_step )
234 for ( angle = angle_start; angle <= angle_end; angle += angle_step ) na++;
235
236 Bimage* pb = p->copy();
237 pb->integer_interpolation(bin, 42);
238 p->calculate_background();
239
240 if ( verbose & VERB_DEBUG )
241 cout << "DEBUG img_find_helix_parameters: binned size = " << pb->size() << endl;
242
243 Vector3<int> size(pb->size());
244 Vector3<float> origin(pb->image->origin());
245 Vector3<float> bestorigin, scale(1,1,1), translate, axis(0,0,1);
246 Vector3<int> mask_size((int) (2*radius), (int) (2*radius), (pb->sizeZ()*3)/4);
247 Vector3<float> mask_start(pb->image->origin().x() - radius, pb->image->origin().y() - radius, pb->sizeZ()/8);
248 Matrix3 mat;
249
250 Bstring title("Helical parameter search");
251 int ncol(3);
252 Bplot* plot = new Bplot(1, na, 3);
253 plot->title(title);
254 plot->page(0).title(title);
255 plot->page(0).columns(3);
256 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
257 plot->page(0).column(0).label("Rise (A)");
258 plot->page(0).column(0).axis(1);
259 plot->page(0).column(1).type(4);
260 plot->page(0).column(1).label("Rotation angle (degrees)");
261 plot->page(0).column(1).axis(3);
262 plot->page(0).column(2).type(4);
263 plot->page(0).column(2).label("CC");
264 plot->page(0).column(2).axis(5);
265 plot->page(0).axis(3).min(angle_start*180.0/M_PI);
266 plot->page(0).axis(3).max(angle_end*180.0/M_PI);
267
268 if ( verbose )
269 cout << "Rise\tAngle\tCC" << endl;
270 for ( i=0, rise = rise_start; rise < rise_end; rise += rise_step ) {
271 for ( angle = angle_start; angle <= angle_end; angle += angle_step, i++ ) {
272 mat = Matrix3(axis, angle);
273 translate[2] = rise/pb->sampling().z();
274 // pt = img_transform_copy(pb, size, scale, origin, translate, mat, FILL_BACKGROUND, 0);
275 pt = pb->transform(size, scale, origin, translate, mat, FILL_BACKGROUND, 0);
276 // write_img("t.pif", pt);
277 // bexit(0);
278 // img_edge_cylinder(pt, mask_size, mask_start, 2, 0, FILL_BACKGROUND);
279 pt->edge(2, mask_size, mask_start, 2, FILL_USER, 0);
280 cc = pb->correlate(pt);
281 delete pt;
282 (*plot)[i] = rise;
283 (*plot)[i+na] = angle*180.0/M_PI;
284 (*plot)[i+2*na] = cc;
285 if ( bestcc < cc ) {
286 bestcc = cc;
287 bestangle = angle;
288 bestrise = rise;
289 }
290 if ( mincc > cc ) mincc = cc;
291 if ( verbose )
292 cout << setprecision(6) << rise << tab << angle*180.0/M_PI
293 << tab << cc << endl << flush;
294 }
295 }
296
297 delete pb;
298
299 if ( bestrise < 0 ) {
300 bestrise = -bestrise;
301 bestangle = -bestangle;
302 }
303
304 if ( verbose ) {
305 cout << "Best helical rise: " << bestrise << " A" << endl;
306 cout << "Best helical rotation angle: " << bestangle*180.0/M_PI << " degrees" << endl;
307 cout << "Best correlation coefficient: " << bestcc << endl << endl;
308 }
309
310 Bstring txt;
311
312 txt = Bstring(bestrise, "Best helical rise: %g A");
313 plot->page(0).add_text(txt);
314 txt = Bstring(bestangle*180.0/M_PI, "Best helical rotation angle: %g degrees");
315 plot->page(0).add_text(txt);
316 txt = Bstring(bestcc, "Best correlation coefficient: %g");
317 plot->page(0).add_text(txt);
318 txt = Bstring(mincc, "Minimum correlation coefficient: %g");
319 plot->page(0).add_text(txt);
320
321 return plot;
322 }
323
324
325 int img_helix_segment_correlation_one(Bimage* p, long i,
326 double angle_start, double angle_end, double angle_step,
327 int bin, double hires, double lores, double radius,
328 fft_plan planf, fft_plan planb, double* cc)
329 {
330 long k;
331 long m = (long) ((angle_end - angle_start)/angle_step) + 1;
332
333 double angle;
334 Vector3<double> axis(0,0,1);
335 Bimage* p1, *p2;
336
337 for ( k = i*m, angle = angle_start; angle <= angle_end; angle += angle_step, k++ ) {
338 p1 = p->extract(i);
339 p2 = p->extract(i+1);
340 p1->rotate(axis, angle);
341 p1->find_shift(p2, NULL, hires, lores, p1->sizeX()/4, 0, 1, planf, planb, cc[k]);
342 delete p2;
343 delete p1;
344 }
345
346 return 0;
347 }
348
368 Bplot* img_helix_segment_correlation(Bimage* p, int thickness,
369 double angle_start, double angle_end, double angle_step,
370 int bin, double hires, double lores, double radius)
371 {
372 if ( hires > lores ) swap(hires, lores);
373
374 if ( radius <= 0 || radius > p->sizeX()/2 ) radius = p->sizeX()/2;
375
376 Vector3<size_t> start, size, tile_size(p->sizeX(), p->sizeY(), thickness);
377 Vector3<size_t> mask_size((size_t) (2*radius), (size_t) (2*radius), p->sizeZ());
378 Vector3<double> mask_start(p->image->origin().x() - radius, p->image->origin().y() - radius, 0);
379
380 p->calculate_background();
381 p->edge(2, mask_size, mask_start, 2, FILL_BACKGROUND, 0);
382
383 // cout << mask_start << tab << mask_size << endl;
384 // cout << start << tab << p->size() << endl;
385 // cout << tile_size << endl;
386
387 Bimage* ptiles = p->extract_tiles(0, start, p->size(), tile_size, 0);
388
389 // write_img("ptiles.pif", ptiles);
390
391 if ( bin > 1 ) {
392 ptiles->integer_interpolation(bin, 42);
393 ptiles->calculate_background();
394 }
395
396 long i, j, k;
397 long nt(ptiles->images());
398 long m = (long) ((angle_end - angle_start)/angle_step) + 1;
399 double angle;
400
401 for ( i=0; i<nt; i++ ) ptiles->image[i].origin(ptiles->size()/2);
402
403 if ( verbose ) {
404 cout << "Calculating cross-correlations between helical segments:" << endl;
405 cout << "Thickness: " << tile_size.z() << endl;
406 cout << "Angular range " << angle_start*180.0/M_PI << " - "
407 << angle_end*180.0/M_PI << " degrees" << endl;
408 cout << "Angular increment: " << angle_step*180.0/M_PI << " degrees" << endl;
409 cout << "Resolution limits: " << hires << " - " << lores << " A" << endl;
410 cout << "Radius: " << radius << endl;
411 cout << "Binning: " << bin << endl << endl;
412 }
413
414 double* cc = new double[m*nt];
415 for ( i=0; i<m*nt; i++ ) cc[i] = 0;
416
417 fft_plan planf = ptiles->fft_setup(FFTW_FORWARD, 1);
418 fft_plan planb = ptiles->fft_setup(FFTW_BACKWARD, 1);
419
420 #ifdef HAVE_GCD
421 dispatch_apply(nt-1, dispatch_get_global_queue(0, 0), ^(size_t i){
422 img_helix_segment_correlation_one(ptiles, i,
423 angle_start, angle_end, angle_step,
424 bin, hires, lores, radius,
425 planf, planb, cc);
426 });
427 #endif
428
429 Bstring title("Helix segment correlation");
430 int ncol(nt);
431 RGB<float> color;
432 Bplot* plot = new Bplot(1, m, ncol);
433 plot->title(title);
434 plot->page(0).title(title);
435 plot->page(0).columns(ncol);
436 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
437 plot->page(0).column(0).label("Angle");
438 plot->page(0).column(0).axis(1);
439 for ( i=1; i<ncol; i++ ) {
440 plot->page(0).column(i).type(2);
441 plot->page(0).column(i).label("CC");
442 plot->page(0).column(i).axis(3);
443 color.spectrum(i,1,ncol-1);
444 plot->page(0).column(i).color(color.r(),color.g(),color.b());
445 }
446 plot->page(0).axis(1).label("Angle");
447 plot->page(0).axis(1).min(angle_start*180.0/M_PI);
448 plot->page(0).axis(1).max(angle_end*180.0/M_PI);
449 plot->page(0).axis(3).label("CC");
450 plot->page(0).axis(3).min(0);
451 plot->page(0).axis(3).max(1);
452
453 if ( verbose ) {
454 cout << endl << "Angle";
455 for ( i=0; i<nt-1; i++ ) cout << "\tCC(" << i+1 << ")";
456 cout << endl;
457 for ( k=0, angle = angle_start; angle <= angle_end; angle += angle_step, k++ ) {
458 cout << setprecision(4) << angle*180.0/M_PI;
459 for ( i=0; i<nt-1; i++ ) cout << tab << cc[i*m + k];
460 cout << endl;
461 }
462 }
463
464 for ( k=0, angle = angle_start; angle <= angle_end; angle += angle_step, k++ ) {
465 (*plot)[k] = angle*180.0/M_PI;
466 for ( i=0; i<nt-1; i++ ) (*plot)[(i+1)*m+k] = cc[i*m + k];
467 }
468
469 fft_destroy_plan(planf);
470 fft_destroy_plan(planb);
471
472 delete[] cc;
473 delete ptiles;
474
475 return plot;
476 }
477
489 int img_distort_elliptically(Bimage* p, double angle, double shift)
490 {
491 p->change_type(Float);
492
493 if ( verbose ) {
494 cout << "Elliptical distortion: " << endl;
495 cout << "Major axis angle: " << angle*180.0/M_PI << " degrees" << endl;
496 cout << "Shift at major axis: " << shift << " pixels" << endl << endl;
497 }
498
499 unsigned long xx, yy, zz, nn, i, j, inz, ix, iy;
500 unsigned long datasize = p->data_size();
501 double dx, dy, a, r, s, rx, ry, fx, fy;
502 float* nudata = new float[datasize];
503
504 for ( i=0; i<datasize; i++ ) nudata[i] = 0;
505
506 for ( j=nn=0; nn<p->images(); nn++ ) {
507 for ( zz=0; zz<p->sizeZ(); zz++ ) {
508 inz = (nn*p->sizeZ() + zz)*p->sizeY()*p->sizeX();
509 for ( yy=0; yy<p->sizeY(); yy++ ) {
510 dy = yy - p->image[nn].origin().x();
511 for ( xx=0; xx<p->sizeX(); xx++, j++ ) {
512 dx = xx - p->image[nn].origin().x();
513 r = sqrt(dx*dx + dy*dy);
514 a = 2*(atan2(dy, dx) - angle);
515 s = shift*cos(a)/r;
516 // cout << x << tab << y << tab << z << tab << n << tab << s << endl;
517 if ( s < 1 ) {
518 rx = dx*(1 - s) + p->image[nn].origin().x();
519 ry = dy*(1 - s) + p->image[nn].origin().y();
520 ix = (unsigned long) rx;
521 iy = (unsigned long) ry;
522 if ( ix < p->sizeX()-1 && iy < p->sizeY()-1 ) {
523 fx = rx - ix;
524 fy = ry - iy;
525 i = inz + iy*p->sizeX() + ix;
526 nudata[j] = (1-fx)*(1-fy)*(*p)[i] + fx*(1-fy)*(*p)[i+1] +
527 (1-fx)*fy*(*p)[i+p->sizeX()] + fx*fy*(*p)[i+p->sizeX()+1];
528 }
529 }
530 }
531 }
532 }
533 }
534 // cout << "***" << endl;
535 p->data_assign((unsigned char *) nudata);
536
537 p->statistics();
538
539 return 0;
540 }
541
542 /*
543 @brief Transforms rows in a 2D image and shift the phases to the origin.
544 @param *p image (converted to complex floating point).
545 @return int 0, <0 on error.
546
547 Each row of pixels is transformed and phase shifted.
548 Only 2D images are transformed.
549 **/
550 int img_transform_lines(Bimage* p)
551 {
552 if ( p->sizeZ() > 1 ) {
553 cerr << "Error: Line transforms can only be calculated from 2D images!" << endl;
554 return -1;
555 }
556
557 p->simple_to_complex();
558 p->change_type(Float);
559
560 fft_plan plan = fft_setup_plan(p->sizeX(), 1, 1, FFTW_FORWARD, 1);
561
562 if ( verbose & VERB_FULL )
563 cout << "Transforming lines of size: " << p->sizeX() << endl;
564
565 unsigned long i, xx, yy, nn, hx(p->sizeX()/2);
566 double dx, shift, phi, sx(p->sizeX());
567 Complex<float>* data = (Complex<float> *) p->data_pointer();
568
569 for ( i=nn=0; nn<p->images(); nn++ ) {
570 shift = -p->image[nn].origin().x()/p->sizeX();
571 if ( verbose & VERB_FULL )
572 cout << "Shift: " << shift << endl;
573 for ( yy=0; yy<p->sizeY(); yy++ ) {
574 data = (Complex<float> *) (p->data_pointer(2*i));
575 fftw(plan, data);
576 for ( xx=0; xx<p->sizeX(); xx++, i++ ) {
577 dx = (xx < hx)? xx: xx - sx;
578 phi = MIN2PI*dx*shift;
579 data[xx].shift_phi(phi);
580 }
581 }
582 }
583
584 fft_destroy_plan(plan);
585
586 if ( verbose & VERB_FULL )
587 cout << "Finished transforming" << endl << endl;
588
589 return 0;
590 }
591
607 Bimage* img_helical_cross_section(Bimage* p, double helix_rise, double helix_angle, double scale, double hires)
608 {
609 if ( p->sizeZ() > 1 ) {
610 cerr << "Error: Cross sections can only be calculated from 2D images!" << endl;
611 return NULL;
612 }
613
614 if ( hires < p->sampling().x() ) hires = p->sampling().x();
615
616 if ( p->sizeX() > p->sizeY() ) {
617 if ( verbose & VERB_PROCESS )
618 cout << "Rotating image" << endl;
619 Bstring order("-yxz");
620 p->reslice(order);
621 }
622
623 Vector3<int> size((int) (p->sizeX()*scale), (int) (p->sizeX()*scale), 1);
624
625 unsigned long i, j, xx, yy, nn;
626 long ix, iy;
627 double pad_factor(2), a, cosang, sinang, dx;
628 int ft_size = part_ft_size(size.x(), 1, (int)pad_factor);
629 double pix_rise = helix_rise/p->sampling().y();
630 double apz = helix_angle/pix_rise;
631
632 Vector3<int> pad_size(ft_size, p->sizeY(), p->sizeZ());
633 Bimage* pp = p->pad_copy(pad_size, FILL_BACKGROUND, p->image->background());
634
635 if ( verbose & VERB_PROCESS ) {
636 cout << "2D reconstruction:" << endl;
637 cout << "Size: " << size << endl;
638 cout << "Helical rise and angle: " << helix_rise << " " << helix_angle*180/M_PI << endl;
639 cout << "Rotation per pixel along axis: " << apz*180/M_PI << endl;
640 cout << "Resolution limit: " << hires << " Å" << endl;
641 cout << "Fourier transform size: " << ft_size << endl;
642 }
643
644 img_transform_lines(pp);
645
646 Bimage* pcs = new Bimage(Float, TComplex, size, p->images());
647 pcs->sampling(p->sampling()/scale);
648 float* fom = pcs->FOM_initialize();
649 // cout << "*** Channels = " << pcs->channels() << endl;
650 // cout << "*** Compound type = " << pcs->compound_type() << endl;
651
652 double hx = pp->sizeX()/2;
653 double sx = pp->sizeX();
654 double rscale = pcs->sizeX()/(scale*sx);
655 double mx = sx * pp->sampling().x() / hires;
656 if ( mx > sx ) mx = sx;
657
658 if ( verbose & VERB_DEBUG )
659 cout << "DEBUG img_helical_cross_section: sampling=" << pp->sampling().x() << " mx=" << mx << endl;
660
661 for ( i=nn=0; nn<pp->images(); nn++ ) {
662 for ( yy=0; yy<pp->sizeY(); yy++ ) {
663 // Set view
664 a = -(yy - pp->image[nn].origin().y())*apz;
665 cosang = cos(a);
666 sinang = sin(a);
667 // Calculate from helical parameters and write line into reconstruction
668 for ( xx=0; xx<pp->sizeX(); xx++, i++ ) {
669 dx = ( xx < hx )? xx: xx - sx;
670 if ( fabs(dx) <= mx ) {
671 dx *= rscale;
672 ix = (long) floor(dx*cosang + 0.5);
673 iy = (long) floor(dx*sinang + 0.5);
674 if ( ix < 0 ) ix += pcs->sizeX();
675 if ( iy < 0 ) iy += pcs->sizeY();
676 if ( ix >= 0 && iy >= 0 && ix < pcs->sizeX() && iy < pcs->sizeY() ) {
677 j = (nn*pcs->sizeY() + iy)*pcs->sizeX() + ix;
678 pcs->add(j, pp->complex(i));
679 fom[j] += 1;
680 }
681 }
682 }
683 }
684 }
685
686 delete pp;
687
688 // Weigh reconstructions
689 if ( verbose & VERB_PROCESS )
690 cout << "Weighing reconstruction" << endl;
691 for ( i=0; i<pcs->size().volume() * pcs->images(); i++ )
692 if ( fom[i] > 0 ) pcs->set(i, pcs->complex(i) / fom[i]);
693
694 pcs->FOM_delete();
695
696 pcs->phase_shift_to_center();
697
698 if ( verbose & VERB_PROCESS )
699 cout << "Backtransforming reconstruction" << endl << endl;
700 pcs->fft_back();
701
702 pcs->statistics();
703
704 return pcs;
705 }
706
717 double img_snvariance(Bimage* p, double snradius)
718 {
719 if ( snradius < 1 || snradius > p->sizeX()/2 ) snradius = p->sizeX()/4;
720
721 unsigned long nn, i, xx, yy, fn, bn;
722 double x2, y2, r2(snradius*snradius), v, fa, fv, ba, bv, snr;
723
724 if ( verbose )
725 cout << "Image\tSNR" << endl;
726 for ( i=nn=0; nn<p->images(); nn++ ) {
727 fn = bn = 0;
728 fa = fv = ba = bv = 0;
729 for ( yy=0; yy<p->sizeY(); yy++ ) {
730 y2 = yy - p->image[nn].origin().y();
731 y2 *= y2;
732 for ( xx=0; xx<p->sizeX(); xx++, i++ ) {
733 x2 = xx - p->image[nn].origin().x();
734 x2 *= x2;
735 v = (*p)[i];
736 if ( x2 + y2 <= r2 ) {
737 fa += v;
738 fv += v*v;
739 fn++;
740 } else {
741 ba += v;
742 bv += v*v;
743 bn++;
744 }
745 }
746 }
747 fa /= fn;
748 ba /= bn;
749 fv = fv/fn - fa*fa;
750 bv = bv/bn - ba*ba;
751 if ( fv < 0 ) fv = 0;
752 if ( bv < 0 ) bv = 0;
753 if ( bv ) {
754 snr = fv/bv - 1;
755 } else {
756 snr = 0;
757 cerr << "Error: The background variance is zero or less! (" << bv << ")" << endl;
758 }
759 if ( verbose )
760 cout << nn+1 << tab << snr << endl;
761 }
762
763 if ( verbose )
764 cout << endl;
765
766 return snr;
767 }
768
782 int img_extrude_cross_section(Bimage* p, int length, double helix_rise, double helix_angle, int fill_type, double fill)
783 {
784 p->change_type(Float);
785
786 p->FOM_delete();
787
788 if ( fill_type == FILL_AVERAGE ) fill = p->average();
789 if ( fill_type == FILL_AVERAGE ) fill = p->average();
790
791 unsigned long i, xx, yy, zz;
792 double a, ca, sa, dx, dy, cx, cy;
793
794 if ( verbose ) {
795 cout << "Extruding the image:" << endl;
796 cout << "Helical rise and rotation: " << helix_rise << " A " << helix_angle*180.0/M_PI << "°" << endl;
797 cout << "Length: " << length << endl;
798 }
799
800 unsigned long nusize = (unsigned long) (p->size().volume() * length);
801 float* nudata = new float[nusize];
802 for ( i=0; i<nusize; i++ ) nudata[i] = 0;
803
804 for ( i=zz=0; zz<length; zz++ ) {
805 a = zz*helix_angle*p->sampling().x()/helix_rise;
806 // cout << "z = " << z << " angle = " << a*180.0/M_PI << endl;
807 ca = cos(a);
808 sa = sin(a);
809 for ( yy=0; yy<p->sizeY(); yy++ ) {
810 dy = yy - p->image->origin().y();
811 for ( xx=0; xx<p->sizeX(); xx++, i++ ) {
812 dx = xx - p->image->origin().x();
813 cx = dx*ca - dy*sa + p->image->origin().x();
814 cy = dx*sa + dy*ca + p->image->origin().y();
815 nudata[i] = p->interpolate(cx, cy, 0, 0, fill);
816 }
817 }
818 }
819
820 p->sizeZ(length);
821 p->data_assign((unsigned char *)nudata);
822
823 return 0;
824 }
825
837 Bplot* img_filament_width(Bimage* p, int width, int lim_lo, int lim_hi)
838 {
839 if ( lim_lo > lim_hi ) swap(lim_lo, lim_hi);
840 if ( lim_lo < 1 ) lim_lo = 1;
841 if ( lim_hi < 1 || lim_hi > p->sizeX() ) lim_hi = p->sizeX();
842
843 unsigned long i, xx, yy, zz, nn, left, right;
844 long n1, n2, hw(width/2);
845 double ox(p->image->origin().x()), a, b, ci, slope_max, slope_min;
846 if ( ox < hw || ox > p->sizeX() - hw ) ox = p->sizeX()/2;
847
848 double* vx = new double[p->sizeX()];
849 double* vy = new double[p->sizeX()];
850
851 long leftmin = (long) (ox - lim_hi/2);
852 long leftmax = (long) (ox - lim_lo/2);
853 long rightmin = (long) (ox + lim_lo/2);
854 long rightmax = (long) (ox + lim_hi/2);
855 if ( leftmin < 0 ) leftmin = 0;
856 if ( leftmax <= leftmin ) leftmax = leftmin + 1;
857 if ( rightmax >= p->sizeX() ) rightmax = p->sizeX() - 1;
858 if ( rightmin >= rightmax ) rightmin = rightmax - 1;
859
860 for ( xx=0; xx<p->sizeX(); xx++ ) vx[xx] = xx;
861
862 if ( verbose ) {
863 cout << "Calculating filament width:" << endl;
864 cout << "Origin: " << ox << endl;
865 cout << "Moving line window width: " << width << endl;
866 cout << "Allowed filament width range: " << lim_lo << " - " << lim_hi << endl;
867 cout << " " <<
868 lim_lo*p->sampling().y() << " - " << lim_hi*p->sampling().y() << " A" << endl << endl;
869 }
870
871 Bstring title("Filament width");
872 int ncol(2);
873 Bplot* plot = new Bplot(1, p->sizeY(), ncol);
874 plot->title(title);
875 plot->page(0).title(title);
876 plot->page(0).columns(ncol);
877 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
878 plot->page(0).column(0).label("Distance (A)");
879 plot->page(0).column(0).axis(1);
880 plot->page(0).column(1).type(2);
881 plot->page(0).column(1).label("Width (A)");
882 plot->page(0).column(1).axis(3);
883 // plot->page(0).axis(1).min(0);
884 // plot->page(0).axis(1).max(360);
885 // plot->page(0).axis(1).inc(30);
886
887 if ( verbose )
888 cout << "y\ty(A)\tleft\tright\twidth\twidth(A)" << endl;
889 for ( i=nn=0; nn<p->images(); nn++ ) {
890 for ( zz=0; zz<p->sizeZ(); zz++ ) {
891 for ( yy=0; yy<p->sizeY(); yy++ ) {
892 left = right = 0;
893 for ( xx=0; xx<p->sizeX(); xx++, i++ ) vy[xx] = (*p)[i];
894 slope_max = slope_min = 0;
895 for ( xx=0; xx<p->sizeX(); xx++ ) {
896 n1 = (long)xx - hw;
897 if ( n1 < 0 ) n1 = 0;
898 n2 = xx + hw;
899 if ( n2 >= p->sizeX() ) n2 = p->sizeX() - 1;
900 ci = linear_least_squares(n1, n2, vx, vy, a, b);
901 // cout << " " << b;
902 if ( xx >= leftmin && xx <= leftmax && slope_max < b ) {
903 slope_max = b;
904 left = xx;
905 }
906 if ( xx >= rightmin && xx <= rightmax && slope_min > b ) {
907 slope_min = b;
908 right = xx;
909 }
910 }
911 (*plot)[yy] = yy*p->sampling().y();
912 (*plot)[yy+p->sizeY()] = (right - left)*p->sampling().y();
913 // cout << endl;
914 if ( verbose )
915 cout << yy << tab << yy*p->sampling().y() << tab << left << tab
916 << right << tab << right - left << tab
917 << (right - left)*p->sampling().x() << endl;
918 }
919 }
920 }
921
922 delete[] vx;
923 delete[] vy;
924
925 return plot;
926 }
927
941 Bimage* img_filament_density(Bimage* p, double width)
942 {
943 if ( p->sizeY() < p->sizeX() ) {
944 Bstring order("y-xz");
945 p->reslice(order);
946 order = 0;
947 }
948
949 if ( width < 1 || width >= p->sizeX() ) width = p->sizeX()/2;
950
951 if ( verbose & VERB_FULL ) {
952 cout << "Calculating filament density per pixel length:" << endl;
953 cout << "Filament width: " << width <<
954 " (" << width*p->sampling().x() << " A)" << endl;
955 cout << "Image width: " << p->sizeX() << endl << endl;
956 }
957
958 unsigned long i, xx, yy, zz, nn;
959 double t, tl, tr, hw((p->sizeX()-width)/2), hwm(p->sizeX()-hw);
960
961 Bimage* pd = new Bimage(Float, TSimple, p->sizeY(), 1, 1, p->images());
962 pd->sampling(p->sampling());
963
964 for ( nn=0; nn<p->images(); nn++ ) {
965 for ( zz=0; zz<p->sizeZ(); zz++ ) {
966 for ( yy=0; yy<p->sizeY(); yy++ ) {
967 t = tl = tr = 0;
968 i = p->index(0, 0, yy, zz, nn);
969 for ( xx=0; xx<hw; xx++, i++ )
970 tl += (*p)[i];
971 for ( ; xx<hwm; xx++, i++ )
972 t += (*p)[i];
973 for ( ; xx<p->sizeX(); xx++, i++ )
974 tr += (*p)[i];
975 tl /= hw;
976 tr /= hw;
977 t /= width;
978 if ( tl < tr ) t -= tl;
979 else t -= tr;
980 i = nn*pd->sizeX() + yy;
981 pd->set(i, t);
982 // cout << i << tab << t << endl;
983 }
984 }
985 }
986
987 pd->statistics();
988
989 return pd;
990 }
991
992
993
994
995
996
997
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1544
Vector3::z
Type z()
Definition: Vector3.h:139
fft_setup_plan
fft_plan fft_setup_plan(size_t x, size_t y, size_t z, fft_direction dir, int opt)
Sets up a plan for fast Fourier transforms.
Definition: fft.cpp:31
Bimage::edge
int edge(int type, Vector3< size_t > 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:227
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:332
Baxis::label
Bstring & label()
Definition: Bplot.h:28
img_filament_density
Bimage * img_filament_density(Bimage *p, double width)
Estimates the density per pixel length of a filament.
Definition: img_helix.cpp:941
FILL_BACKGROUND
#define FILL_BACKGROUND
Definition: utilities.h:167
Bimage.h
Header file for image class.
img_find_helix_parameters
Bplot * img_find_helix_parameters(Bimage *p, double angle_start, double angle_end, double angle_step, int bin, double hires, double lores, double radius)
Finds the best helix parameters for helical map.
Definition: img_helix.cpp:37
fftw
void fftw(fftw_plan plan, int howmany, fftw_complex *in, int istride, int idist, fftw_complex *out, int ostride, int odist)
Definition: executor.c:402
img_helix_segment_correlation_one
int img_helix_segment_correlation_one(Bimage *p, long i, double angle_start, double angle_end, double angle_step, int bin, double hires, double lores, double radius, fft_plan planf, fft_plan planb, double *cc)
Definition: img_helix.cpp:325
Baxis::min
double min()
Definition: Bplot.h:30
Bimage::extract_tiles
Bimage * extract_tiles(size_t nn, size_t ntiles, Vector3< size_t > *coords, Vector3< size_t > tile_size)
Extracts a set of tiles at specified positions from an image into a new image.
Definition: Bimage_extract.cpp:325
Bplot::title
Bstring & title()
Definition: Bplot.h:195
img_filament_width
Bplot * img_filament_width(Bimage *p, int width, int lim_lo, int lim_hi)
Estimates the width of a filament.
Definition: img_helix.cpp:837
RGB::g
Type g()
Definition: Color.h:43
symmetry.h
Header file for general symmetry functions.
Bimage::calculate_background
int calculate_background(size_t nn)
Calculates the background for one sub-image.
Definition: Bimage_background.cpp:26
Bimage::fft_back
int fft_back()
Definition: Bimage.h:683
utilities.h
Header file for general utilities.
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:105
Bcolumn::label
Bstring & label()
Definition: Bplot.h:63
Bsub_image::background
double background()
Definition: Bimage.h:126
img_helix.h
Dealing with images with helical symmetry.
img_transform_lines
int img_transform_lines(Bimage *p)
Definition: img_helix.cpp:550
Matrix3
Definition: Matrix3.h:17
FILL_AVERAGE
#define FILL_AVERAGE
Definition: utilities.h:166
img_snvariance
double img_snvariance(Bimage *p, double snradius)
Calculates the ratio of variance inside and outside a given radius.
Definition: img_helix.cpp:717
Vector3
Vector class for 3-value vectors used in 3D space. The internal variables are an array of 3 numbers...
Definition: Quaternion.h:17
Bimage::index
size_t index(size_t nx, size_t ny) const
Definition: Bimage.h:336
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:100
Bcolumn::color
double * color()
Definition: Bplot.h:76
TComplex
Definition: Bimage.h:52
Bimage::average
double average(size_t cc, double xf, double yf, double zf, size_t nn, double iscale)
Averages in the xy plane when scaling is less than 1.
Definition: Bimage.cpp:1209
Bpage::column
Bcolumn & column(long i)
Definition: Bplot.h:110
Bimage::correlate
double correlate(Bimage *p)
Calculates correlation coefficient between two images.
Definition: Bimage_correlate.cpp:37
Bimage::size
Vector3< size_t > size() const
Definition: Bimage.h:327
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:1246
Bimage::statistics
size_t statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
b
long b
Definition: jpegint.h:371
TSimple
Definition: Bimage.h:51
Baxis::max
double max()
Definition: Bplot.h:32
Float
Definition: utilities.h:150
img_helical_cross_section
Bimage * img_helical_cross_section(Bimage *p, double helix_rise, double helix_angle, double scale, double hires)
Calculates a helical cross section from line transforms of a filament.
Definition: img_helix.cpp:607
part_ft_size
int part_ft_size(int xsize, double scale, int pad_factor)
Sets the Fourier transform size for 2D particle images for reconstruction.
Definition: mg_reconstruct.cpp:36
Bimage
General image parameter class.
Definition: Bimage.h:152
Bimage::transform
int transform(Vector3< double > scale, Vector3< double > origin, Vector3< double > translate, Matrix3 mat, int fill_type=0, double fill=0)
Transforms an image by translation, rotation, scaling and skewing, in place.
Definition: Bimage_transform.cpp:37
Bimage::pad_copy
Bimage * pad_copy(size_t sz, int fill_type=0, double fill=0)
Pads an image to a new size with a given fill value.
Definition: Bimage_resize.cpp:385
M_PI
#define M_PI
Definition: utilities.h:52
Bimage::FOM_initialize
float * FOM_initialize()
Allocates and initializes the FOM block.
Definition: Bimage.cpp:677
Bimage::phase_shift_to_center
int phase_shift_to_center()
Phase shifts a set of reflections to the nominal center of the image origin.
Definition: Bimage_complex.cpp:335
Bcolumn::number
long number()
Definition: Bplot.h:61
Bimage::complex
Complex< double > complex(size_t j)
Returns a complex value at the given index.
Definition: Bimage.cpp:885
Bimage::sampling
void sampling(double s)
Definition: Bimage.h:440
Bimage::data_assign
unsigned char * data_assign(unsigned char *nudata)
Assign image data.
Definition: Bimage.cpp:623
Bcolumn::type
long type()
Definition: Bplot.h:66
Bpage::axis
Baxis & axis(long id)
Definition: Bplot.h:117
Bimage::simple_to_complex
void simple_to_complex()
A simple image is converted to a complex image.
Definition: Bimage_complex.cpp:22
RGB
Definition: Color.h:24
Bpage::title
Bstring & title()
Definition: Bplot.h:100
Bimage::FOM_delete
void FOM_delete()
Deallocates the FOM block.
Definition: Bimage.cpp:715
Vector3::x
Type x()
Definition: Vector3.h:137
img_distort_elliptically
int img_distort_elliptically(Bimage *p, double angle, double shift)
Transforms a tubular cylinder to an elliptical profile.
Definition: img_helix.cpp:489
trigonometry.h
Header file for trigonometry functions.
FILL_USER
#define FILL_USER
Definition: utilities.h:165
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:132
Bimage::add
void add(size_t j, double v)
Definition: Bimage.h:268
Bimage::set
void set(size_t j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:977
Bimage::extract
Bimage * extract(size_t nn)
Extracts one sub-image into new image structure.
Definition: Bimage_extract.cpp:21
RGB::r
Type r()
Definition: Color.h:42
Bimage::reslice
void reslice(const char *order)
Definition: Bimage.h:596
fftwnd_data
Definition: fftw.h:355
Bpage::add_text
void add_text(Bstring &s)
Definition: Bplot.h:122
Bimage::images
size_t images()
Definition: Bimage.h:438
Complex
Definition: Complex.h:23
MIN2PI
#define MIN2PI
Definition: utilities.h:64
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:231
Bimage::data_size
size_t data_size()
Definition: Bimage.h:225
Bstring
Definition: Bstring.h:28
Bimage::copy
Bimage * copy()
Copies the header information and data of an image into a new image structure.
Definition: Bimage.cpp:2414
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:330
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
Bplot::page
Bpage & page(long i)
Definition: Bplot.h:217
matrix_linear.h
Header file for matrix functions.
FFTW_BACKWARD
Definition: fftw.h:64
fft_destroy_plan
int fft_destroy_plan(fft_plan plan)
Deallocates a plan for fast Fourier transforms.
Definition: fft.cpp:97
img_extrude_cross_section
int img_extrude_cross_section(Bimage *p, int length, double helix_rise, double helix_angle, int fill_type, double fill)
Extrudes a 2D cross section into a 3D continuous helix.
Definition: img_helix.cpp:782
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:331
Bimage::rotate
int rotate()
Rotates an image using parameters defined in the image in place.
Definition: Bimage_transform.cpp:220
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:672
Bpage::columns
void columns(long ncol)
Definition: Bplot.h:105
Bimage::integer_interpolation
int integer_interpolation(int integer_factor)
Definition: Bimage_bin.cpp:16
RGB::spectrum
void spectrum(double value, double cmin, double cmax)
Definition: Color.h:84
data
JSAMPIMAGE data
Definition: jpeglib.h:945
verbose
int verbose
mg_reconstruct.h
Functions for reconstruction.
FFTW_FORWARD
Definition: fftw.h:64
VERB_FULL
#define VERB_FULL
Definition: utilities.h:102
Vector3::y
Type y()
Definition: Vector3.h:138
RGB::b
Type b()
Definition: Color.h:44
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
img_helix_segment_correlation
Bplot * img_helix_segment_correlation(Bimage *p, int thickness, double angle_start, double angle_end, double angle_step, int bin, double hires, double lores, double radius)
Calculates the correlation over rotation angles between helical segments.
Definition: img_helix.cpp:368
Bimage::image
Bsub_image * image
Definition: Bimage.h:183
Bcolumn::axis
long axis()
Definition: Bplot.h:68
Bplot
Definition: Bplot.h:146
linear_least_squares
double linear_least_squares(int n1, int n2, double *x, double *y, double &a, double &b)
Does a linear least squares fit between two vectors.
Definition: matrix_linear.cpp:28