| Bsoft 2.0.5 Bernard's software package

mg_ctf_fit.cpp
Go to the documentation of this file.
1
9 #include "rwimg.h"
10 #include "mg_ctf_fit.h"
11 #include "mg_processing.h"
12 #include "simplex.h"
13 #include "moving_average.h"
14 #include "utilities.h"
15 #include "timer.h"
16
17 #include <sys/stat.h>
18
19 // Declaration of global variables
20 extern int verbose; // Level of output to the screen
21
22 // Internal function prototypes
23 double ctf_fit_baseline(Bimage* prad, double real_size, CTFparam& em_ctf, double lores, double hires);
24 double ctf_fit_envelope(Bimage* prad, double real_size, CTFparam& em_ctf, double lores, double hires);
25
46 Bimage* img_ctf_radial_average(Bimage* p, long n, CTFparam& em_ctf)
47 {
48 if ( em_ctf.check_defocus() || em_ctf.check_Cs() )
49 cerr << "in img_ctf_radial_average" << endl;
50
51 long nrad = p->sizeX()/2;
52 Bimage* prad = new Bimage(Double, TSimple, nrad, 1, 1, 1);
53 prad->sampling(p->sampling()[0], 1, 1);
54
55 long i, x, y, z;
56 long iradius;
57 double dx, dy, dz, dr, radius, angle, fraction, cosang, sinang;
58 double smin2 = 1-em_ctf.defocus_deviation()/em_ctf.defocus_average();
59 double smax2 = 1+em_ctf.defocus_deviation()/em_ctf.defocus_average();
60 vector<double> num(nrad);
61 double* rdata = (double *) prad->data_pointer();
62
63 if ( verbose & VERB_FULL ) {
64 cout << "Radial average for CTF fitting:" << endl;
65 cout << "Size: " << nrad << endl;
66 cout << "Power spectrum origin: " << p->image->origin() << endl;
67 cout << "Defocus, deviation, angle: " <<
68 em_ctf.defocus_average() << " " << em_ctf.defocus_deviation() << " " << em_ctf.astigmatism_angle() << endl;
69 }
70
71 if ( p->sizeZ() < 2 ) {
72 if ( verbose & VERB_DEBUG )
73 cout << "DEBUG img_ctf_radial_average: doing image " << n+1 << endl;
74 for ( i=0; i<nrad; i++ ) num[i] = 0;
75 for ( y=0; y<p->sizeY(); y++ ) {
76 dy = y - p->image[n].origin()[1];
77 for ( x=0; x<p->sizeX(); x++ ) {
78 dx = x - p->image[n].origin()[0];
79 radius = sqrt(dx*dx + dy*dy);
80 iradius = (long) radius;
81 if ( iradius < nrad ) {
82 angle = atan2(dy, dx) - em_ctf.astigmatism_angle();
83 cosang = cos(angle);
84 sinang = sin(angle);
85 dr = smax2*cosang*cosang + smin2*sinang*sinang;
86 if ( dr >= 0) {
87 radius *= sqrt(dr);
88 // if ( !isfinite(radius) )
89 // cerr << "Warning: radius for " << iradius << " not finite!" << endl;
90 iradius = (long) radius;
91 if ( iradius < nrad - 1 ) {
92 fraction = radius - iradius;
93 num[iradius] += 1.0 - fraction;
94 i = p->index(0,x,y,0,n);
95 rdata[iradius] += (1.0 - fraction)*(*p)[i];
96 iradius++;
97 if ( iradius < nrad ) {
98 num[iradius] += fraction;
99 rdata[iradius] += fraction*(*p)[i];
100 }
101 }
102 }
103 }
104 }
105 }
106 for ( iradius=0; iradius<nrad; iradius++ )
107 if ( num[iradius] ) rdata[iradius] /= num[iradius];
108 } else {
109 if ( verbose & VERB_DEBUG )
110 cout << "DEBUG img_ctf_radial_average: calculating 3D RPS" << endl;
111 for ( i=0; i<nrad; i++ ) num[i] = 0;
112 for ( z=0; z<p->sizeZ(); z++ ) {
113 dz = z - p->image[n].origin()[2];
114 for ( y=0; y<p->sizeY(); y++ ) {
115 dy = y - p->image[n].origin()[1];
116 for ( x=0; x<p->sizeX(); x++ ) {
117 dx = x - p->image[n].origin()[0];
118 radius = sqrt(dx*dx + dy*dy + dz*dz);
119 iradius = (long) radius;
120 if ( iradius < nrad - 1 ) {
121 fraction = radius - iradius;
122 num[iradius] += 1.0 - fraction;
123 i = p->index(0,x,y,z,n);
124 rdata[n*nrad+iradius] += (1.0 - fraction)*(*p)[i];
125 iradius++;
126 if ( iradius < nrad ) {
127 num[iradius] += fraction;
128 rdata[iradius] += fraction*(*p)[i];
129 }
130 }
131 }
132 }
133 }
134 for ( iradius=0; iradius<nrad; iradius++ )
135 if ( num[iradius] ) rdata[iradius] /= num[iradius];
136 }
137
138 prad->statistics();
139
140 return prad;
141 }
142
143 double img_ctf_fit_residual(Bimage* p, long n, CTFparam& em_ctf, double lores, double hires)
144 {
145 long rmin = (long) (p->real_size()[0]/lores);
146 long rmax = (long) (p->real_size()[0]/hires);
147
148 long i, m(0);
149 double s, s2, b, e, c, d, R(0);
150
151 Bimage* prad = img_ctf_radial_average(p, n, em_ctf);
152
153 for ( i=rmin; i<=rmax; ++i ) {
154 s = i/p->real_size()[0];
155 s2 = s*s;
156 b = em_ctf.calc_baseline(s);
157 e = em_ctf.calc_envelope(s);
158 c = em_ctf.calculate(s2, 0);
159 c *= c;
160 d = b + e*c - (*prad)[i];
161 d /= b;
162 R += d*d;
163 m++;
164 cout << i << tab << (*prad)[i] << tab << b + e*c << tab << d << endl;
165 }
166
167 delete prad;
168
169 R = sqrt(R/m);
170
171 return R;
172 }
173
209 double img_ctf_fit(Bimage* p, long n, CTFparam& em_ctf, double lores, double hires,
210 double def_start, double def_end, double def_inc, int flag)
211 {
212 if ( hires < 2*p->sampling()[0] ) hires = 2*p->sampling()[0];
213 if ( lores < hires ) lores = p->real_size()[0];
214 if ( lores > p->real_size()[0] ) lores = p->real_size()[0];
215
216 if ( hires > 3 && em_ctf.baseline_type() > 3 )
217 em_ctf.baseline_type(em_ctf.baseline_type()-3);
218
219 if ( verbose & VERB_PROCESS ) {
220 cout << "Determining CTF parameters:" << endl;
221 cout << "Sampling: " << p->sampling()[0] << " A" << endl;
222 em_ctf.show();
223 cout << "Resolution range: " << hires << " - " << lores << " A" << endl;
224 cout << "Baseline type: " << em_ctf.baseline_type() << endl;
225 cout << "Envelope type: " << em_ctf.envelope_type() << endl;
226 cout << "Defocus min, max, inc: " << def_start << " - " << def_end << " ∆ " << def_inc << endl << endl;
227 }
228
229 if ( em_ctf.defocus_average() < 1 || em_ctf.defocus_average() > 2e5 )
230 em_ctf.defocus_average(2e4);
231
232 em_ctf.defocus_deviation(0);
233 em_ctf.astigmatism_angle(0);
234 em_ctf.fom(0);
235
236 double fom = img_ctf_find_defocus(p, n, em_ctf, lores, hires, def_start, def_end, def_inc);
237
238 img_ctf_fit_baseline(p, n, em_ctf, lores, hires);
239
240 img_ctf_fit_envelope(p, n, em_ctf, lores, hires);
241
242 long i(0), imax(10);
243 double pfom(0);
244 // double hires_astig = 2*hires*lores/(lores+hires);
245 // double hires_dec = (hires_astig - hires)/imax;
246
247 if ( flag ) for ( i=0; i<imax && ( fabs(fom - pfom) > 1e-30 ); ++i ) {
248 // if ( flag ) for ( i=0; i<imax; ++i ) {
249 if ( verbose )
250 cout << "Defocus [" << i << "]: "
251 << em_ctf.defocus_average()
252 << " +- " << em_ctf.defocus_deviation()
253 << " @ " << em_ctf.astigmatism_angle()*180/M_PI
254 << " (" << fom << ")" << endl;
255 pfom = fom;
256 // cout << i << tab << hires_astig << endl;
257 def_start = em_ctf.defocus_average()/10;
258 def_end = em_ctf.defocus_average()*10;
259 def_inc = def_start;
260 // cout << def_start << " - " << def_end << " ∆ " << def_inc << endl;
261 fom = img_ctf_fit_astigmatism(p, n, em_ctf, lores, hires);
262 img_ctf_find_defocus(p, n, em_ctf, lores, hires, def_start, def_end, def_inc);
263 img_ctf_fit_baseline(p, n, em_ctf, lores, hires);
264 img_ctf_fit_envelope(p, n, em_ctf, lores, hires);
265 // fom = img_ctf_fit_residual(p, n, em_ctf, lores, hires);
266 // hires_astig -= hires_dec;
267 }
268
269 double wri = img_water_ring_index(p, n, em_ctf);
270
271 if ( verbose ) {
272 cout << "Best defocus: "
273 << em_ctf.defocus_average()
274 << " +- " << em_ctf.defocus_deviation()
275 << " @ " << em_ctf.astigmatism_angle()*180/M_PI
276 << " (" << fom << ")" << endl;
277 cout << "Water ring index: "
278 << wri << endl;
279 // << p->meta_data()["image"][n]["water_ring"].real() << endl;
280 }
281
282 return wri;
283 }
284
299 double img_ctf_fit_baseline(Bimage* p, long n, CTFparam& em_ctf, double lores, double hires)
300 {
301 Bimage* prad = img_ctf_radial_average(p, n, em_ctf);
302
303 if ( !prad ) {
304 cerr << "Error in img_ctf_fit_baseline: No radial power spectrum calculated!" << endl;
305 return -1;
306 }
307
308 double R = ctf_fit_baseline(prad, p->real_size()[0], em_ctf, lores, hires);
309
310 delete prad;
311
312 if ( verbose & VERB_PROCESS )
313 em_ctf.show_baseline();
314
315 return R;
316 }
317
332 double img_ctf_fit_envelope(Bimage* p, long n, CTFparam& em_ctf, double lores, double hires)
333 {
334 Bimage* prad = img_ctf_radial_average(p, n, em_ctf);
335
336 if ( !prad ) {
337 cerr << "Error in img_ctf_fit_envelope: No radial power spectrum calculated!" << endl;
338 return -1;
339 }
340
341 double R = ctf_fit_envelope(prad, p->real_size()[0], em_ctf, lores, hires);
342
343 delete prad;
344
345 if ( verbose & VERB_PROCESS )
346 em_ctf.show_envelope();
347
348 return R;
349 }
350
351 double ctf_test_defocus(CTFparam& em_ctf, double def, long nx,
352 double step_size, vector<double>& r, long rmin, long rmax)
353 {
354 long i;
355 long nr(rmax-rmin+1);
356 double fom(0);
357
358 em_ctf.defocus_average(def);
359
360 vector<double> c = em_ctf.calculate(nx, 1, step_size);
361
362 if ( !c.size() ) {
363 cerr << "Error in ctf_test_defocus: CTF not calculated!" << endl;
364 return fom;
365 }
366
367 for ( i=rmin; i<=rmax; i++ ) fom += (c[i]*c[i] - 0.5)*r[i];
368 fom /= nr;
369
370 return fom;
371 }
372
391 double img_ctf_find_defocus(Bimage* p, long n, CTFparam& em_ctf,
392 double lores, double hires,
393 double def_start, double def_end, double def_inc)
394 {
395 if ( def_start < 100 ) def_start = 100;
396 if ( def_end > 2e5 ) def_end = 2e5;
397 if ( em_ctf.defocus_average() < def_start || em_ctf.defocus_average() > def_end )
398 em_ctf.defocus_average((def_end - def_start)/2);
399
400 if ( hires < 2*p->sampling()[0] ) hires = 2*p->sampling()[0];
401 if ( lores < hires ) lores = 100;
402 if ( lores > 100 ) lores = 100;
403
404 Bimage* prad = img_ctf_radial_average(p, n, em_ctf);
405
406 long i, nx(p->sizeX()/2);
407 double step_size = 1/p->real_size()[0];
408 long rmin = (long) (p->real_size()[0]/lores);
409 long rmax = (long) (p->real_size()[0]/hires);
410
411 for ( i=0; i<rmin; i++ ) prad->set(i, (*prad)[rmin]);
412
413 vector<double> r = moving_polynomial(2, nx, (double *) prad->data_pointer(), nx/5);
414
415 for ( i=0; i<nx; i++ )
416 if ( r[i] ) r[i] = (*prad)[i]/r[i] - 1;
417 else r[i] = 0;
418
419 double def, def_best(em_ctf.defocus_average());
420 double fom, fom_max(-2);
421
422 if ( verbose & VERB_PROCESS ) {
423 cout << "Defocus range: " << def_start*1e-4 << " - " << def_end*1e-4 << " um" << endl;
424 cout << "Defocus increment: " << def_inc*1e-4 << " um" << endl;
425 cout << "Frequency pixel range: " << rmin << " - " << rmax << endl;
426 cout << "Frequency step size: " << step_size << " 1/A" << endl;
427 }
428
429 double ds(def_start), de(def_end);
430
431 if ( verbose & VERB_FULL )
432 cout << "Defocus\tCC" << endl;
433 while ( def_inc >= 50 ) {
434 for ( def=ds; def<=de; def+=def_inc ) {
435 fom = ctf_test_defocus(em_ctf, def, nx, step_size, r, rmin, rmax);
436 if ( fom_max < fom ) {
437 fom_max = fom;
438 def_best = def;
439 }
440 if ( verbose & VERB_FULL )
441 cout << def*1e-4 << tab << fom << endl;
442 }
443 ds = def_best - 2*def_inc;
444 de = def_best + 2*def_inc;
445 def_inc /= 1.6;
446 if ( ds < def_start ) ds = def_start;
447 if ( de > def_end ) de = def_end;
448 // cout << "def_start=" << def_start << endl;
449 }
450
451 delete prad;
452
453 em_ctf.defocus_average(def_best);
454 if ( fom_max > -1 ) em_ctf.fom(fom_max);
455
456 return em_ctf.fom();
457 }
458
459 //Expects a radial average
460 Bimage* img_ctf_radial_subtract_baseline(Bimage* prad, double real_size, CTFparam& em_ctf)
461 {
462 long i;
463 double s, recip_interval = 1.0/real_size;
464 Bimage* prmb = prad->copy();
465
466 for ( i=0; i<prmb->sizeX(); i++ ) {
467 s = i*recip_interval;
468 prmb->set(i, (*prmb)[i] - em_ctf.calc_baseline(s));
469 }
470
471 return prmb;
472 }
473
474 /*
475 Expects a radial power spectrum
476 Measures the astigmatism between the resolution limits
477 The variable real_size is the box x-size in angstrom
478 Zeroes are calculated, given in spatial frequency units
479 For every two successive zeroes between the resolution limits:
480 the minimum within a kernel is found at each zero: [ib1]:b1 and [ib2]:b2
481 the maximum halfway between the zeroes within a kernel is found: [im]:m
482 Measure: sum(im*(m - (b1+b2)/2))
483 the intent is that this measure should be maximum for the correct astigmatism parameters
484 */
485 double img_ctf_astigmatism_measure(Bimage* p, long n, double real_size, CTFparam& em_ctf, double lores, double hires)
486 {
487 Bimage* prad = img_ctf_radial_average(p, n, em_ctf);
488
489 if ( !prad ) {
490 cerr << "Error in img_ctf_astigmatism_measure: No radial power spectrum calculated!" << endl;
491 return -1;
492 }
493
494 double pixel_size = prad->sampling()[0];
495 if ( pixel_size <= 0 ) pixel_size = 1;
496
497 long i, ib1, ib2, im, j, nn(0);
498 long k = prad->sizeX()/100;
499 if ( k < 2 ) k = 2;
500 long ilo = (long) (real_size/lores + 0.5);
501 long ihi = (long) (real_size/hires + 0.5);
502 if ( ihi >= prad->sizeX() ) ihi = prad->sizeX() - 1;
503 double b1, b2, m, OM(0);
504 double max_s = 0.45/pixel_size;
505
506 Bimage* prmb = img_ctf_radial_subtract_baseline(prad, real_size, em_ctf);
507
508 vector<double> zero = em_ctf.zeroes(max_s);
509 long nz(zero.size());
510
511 if ( nz > prad->sizeX() ) nz = prad->sizeX();
512
513 for ( i=1; i<nz; i++ ) {
514 ib1 = (long) (zero[i-1]*real_size + 0.5);
515 ib2 = (long) (zero[i]*real_size + 0.5);
516 im = (ib1 + ib2)/2;
517 if ( im >= ilo && im <= ihi ) {
518 for ( b1=(*prmb)[ib1], j=ib1-k; j<=ib1+k; j++ )
519 if ( b1 > (*prmb)[j] ) b1 = (*prmb)[j];
520 for ( b2=(*prmb)[ib2], j=ib2-k; j<=ib2+k; j++ )
521 if ( b2 > (*prmb)[j] ) b2 = (*prmb)[j];
522 for ( m=(*prmb)[im], j=im-k; j<=im+k; j++ )
523 if ( m < (*prmb)[j] ) m = (*prmb)[j];
524 OM += im*(m - (b1 + b2)/2);
525 nn += im;
526 }
527 }
528
529 OM /= nn;
530
531 delete prad;
532 delete prmb;
533
534 if ( verbose & VERB_FULL )
535 cout << "Fitting measure: " << OM << endl;
536
537 return OM;
538 }
539
557 double img_ctf_fit_astigmatism(Bimage* p, long n, CTFparam& em_ctf, double lores, double hires)
558 {
559 long i, j, na;
560 double real_size = p->real_size()[0];
561 double angle, angle_min(-M_PI_2), angle_max(M_PI_2), angle_range(M_PI), angle_inc(M_PI/9);
562 double def_dev(100), ddiff, prev_fom(0);
563 double best_dev(em_ctf.defocus_deviation()), best_ang(em_ctf.astigmatism_angle());
564 if ( em_ctf.defocus_deviation() > 0 ) def_dev = em_ctf.defocus_deviation(); // Use the input deviation
565 double* fom;
566 CTFparam* ec;
567
568 double best_fom = img_ctf_astigmatism_measure(p, n, real_size, em_ctf, lores, hires);
569
570 if ( verbose & VERB_FULL )
571 cout << "Starting astigmatism: " << em_ctf.defocus_average() << " "
572 << em_ctf.defocus_deviation() << " " << em_ctf.astigmatism_angle() << " " << best_fom << endl;
573
574 long maxiter(20);
575 for ( i=0; i<maxiter && ( best_fom/prev_fom - 1 > 1e-10 ); i++ ) {
576 for ( na=0, angle=angle_min; angle<=angle_max; angle+=angle_inc ) na++;
577 ec = new CTFparam[na];
578 fom = new double[na];
579 em_ctf.defocus_deviation(def_dev);
580 for ( angle=angle_min, j=0; angle<=angle_max; angle+=angle_inc, j++ ) {
581 ec[j] = em_ctf;
582 ec[j].astigmatism_angle(angle);
583 }
584
585 #ifdef HAVE_GCD
586 dispatch_apply(na, dispatch_get_global_queue(0, 0), ^(size_t k){
587 fom[k] = img_ctf_astigmatism_measure(p, n, real_size, ec[k], lores, hires);
588 });
589 #else
590 #pragma omp parallel for
591 for ( j=0; j<na; j++ ) {
592 fom[j] = img_ctf_astigmatism_measure(p, n, real_size, ec[j], lores, hires);
593 }
594 #endif
595
596 for ( j=0; j<na; j++ ) {
597 if ( best_fom < fom[j] ) {
598 prev_fom = best_fom;
599 best_fom = fom[j];
600 best_dev = def_dev;
601 best_ang = ec[j].astigmatism_angle();
602 }
603 if ( verbose & VERB_FULL )
604 cout << em_ctf.defocus_average() << tab << def_dev << tab << ec[j].astigmatism_angle() << tab << fom[j] << tab <<
605 em_ctf.defocus_average() << tab << best_dev << tab << best_ang << tab << best_fom << endl;
606 }
607 ddiff = best_dev - def_dev;
608
609 delete[] ec;
610 delete[] fom;
611
612 if ( ddiff == 0 ) {
613 def_dev += 10;
614 angle_range /= 1.5;
615 angle_min = best_ang - angle_range/2;
616 angle_max = best_ang + angle_range/2;
617 angle_inc /= 1.5;
618 } else def_dev += ddiff/1.5;
619 }
620
621 if ( best_ang < -M_PI_2 ) best_ang += M_PI;
622 if ( best_ang > M_PI_2 ) best_ang -= M_PI;
623
624 em_ctf.defocus_deviation(best_dev);
625 em_ctf.astigmatism_angle(best_ang);
626
627 if ( verbose & VERB_PROCESS )
628 cout << "Astigmatism refined: " << em_ctf.defocus_average() << " +- "
629 << em_ctf.defocus_deviation() << " @ " << em_ctf.astigmatism_angle()*180.0/M_PI << " (OM = " << best_fom << ")" << endl;
630
631 return best_fom;
632 }
633
651 double img_water_ring_index(Bimage* p, long img_num, CTFparam& em_ctf)
652 {
653 Bimage* prad = img_ctf_radial_average(p, img_num, em_ctf);
654
655 double wri = img_water_ring_index(prad);
656
657 delete prad;
658
659 if ( verbose & VERB_FULL )
660 cout << "Water ring index for image " << img_num << ": " << wri << endl;
661
662 return wri;
663 }
664
680 double img_water_ring_index(Bimage* prad)
681 {
682 if ( !prad ) {
683 cerr << "Error in img_water_ring_index: No radial power spectrum calculated!" << endl;
684 return -1;
685 }
686
687 long i, n1(0), n2(0), nw(0);
688 double s, b1(0), b2(0), wp(0), wri(0);
689 double f = 0.5/prad->real_size()[0];
690
691 for ( i=0, s=f/2; i<prad->sizeX() && s < 0.4; ++i, s+=f ) if ( s > 0.1 ) {
692 if ( s < 0.2 ) {
693 b1 += (*prad)[i];
694 n1++;
695 } else if ( s > 0.3 ) {
696 b2 += (*prad)[i];
697 n2++;
698 } else {
699 wp += (*prad)[i];
700 nw++;
701 }
702 }
703
704 n1 += n2;
705 if ( n1 ) b1 = (b1 + b2)/n1;
706 if ( nw ) wp /= nw;
707
708 if ( b1 ) wri = wp/b1 - 1;
709
710 return wri;
711 }
712
713 double gaussian_R(Bsimplex& simp)
714 {
715 long i;
716 double R(0), df, s2;
717 vector<double>& f = simp.dependent_values();
718 vector<double>& x = simp.independent_values();
719
720 for ( i=0; i<simp.points(); i++ ) {
721 s2 = x[i]*x[i];
722 df = f[i] - (simp.parameter(0) + simp.parameter(1)*exp(simp.parameter(2)*s2));
723 R += df*df;
724 }
725
726 R = sqrt(R/i);
727
728 return R;
729 }
730
731 double gaussian1_R(Bsimplex& simp)
732 {
733 long i;
734 double R(0), df, ds, w, wsum(0);
735 double cen(M_PI_2 / ( simp.points() - 1));
736 vector<double>& f = simp.dependent_values();
737 vector<double>& x = simp.independent_values();
738
739 for ( i=0; i<simp.points(); i++ ) {
740 w = 1 - cos(cen*i);
741 ds = simp.parameter(3) - x[i];
742 df = f[i] - (simp.parameter(0) + simp.parameter(1)*x[i] +
743 simp.parameter(2)*exp(simp.parameter(4)*ds*ds));
744 R += w*df*df;
745 wsum += w;
746 }
747
748 R = sqrt(R/wsum);
749
750 return R;
751 }
752
753 double double_gaussian_R(Bsimplex& simp)
754 {
755 long i;
756 double R(0), df, s2;
757 vector<double>& f = simp.dependent_values();
758 vector<double>& x = simp.independent_values();
759
760 for ( i=0; i<simp.points(); i++ ) {
761 s2 = x[i]*x[i];
762 df = f[i] - (simp.parameter(0) + simp.parameter(1)*exp(simp.parameter(2)*s2) +
763 simp.parameter(3)*exp(simp.parameter(4)*s2));
764 R += df*df;
765 }
766
767 R = sqrt(R/i);
768
769 return R;
770 }
771
772 double eman_baseline_R(Bsimplex& simp)
773 {
774 long i;
775 double R(0), df;
776 vector<double>& f = simp.dependent_values();
777 vector<double>& x = simp.independent_values();
778
779 for ( i=0; i<simp.points(); i++ ) {
780 df = f[i] - (simp.parameter(0) + simp.parameter(1)*
781 exp(simp.parameter(2)*sqrt(x[i]) + simp.parameter(3)*x[i]*x[i]));
782 R += df*df;
783 }
784
785 R = sqrt(R/i);
786
787 return R;
788 }
789
790 /*
791 @brief Fits a double gaussian function.
792 @param n number of data points.
793 @param *x x array (at least order+1 values).
794 @param *y y array (at least order+1 values).
795 @param coeff array in which 5 coefficients are returned
796 (if NULL, no coefficients returned).
797 @return double R value.
798
799 Double gaussian function:
800 y = a + b*exp(c*s^2) + d*exp(f*s^2)
801 **/
802 double ctf_fit_polynomial(long n, vector<double>& x, vector<double>& y, vector<double>& coeff)
803 {
804 long nc(5);
805 if ( n < 5 ) nc = n - 1;
806
807 double R = fit_polynomial(n, x, y, nc, coeff);
808
809 return R;
810 }
811
812 /*
813 @brief Fits a double gaussian function.
814 @param n number of data points.
815 @param *x x array (at least order+1 values).
816 @param *y y array (at least order+1 values).
817 @param coeff array in which 5 coefficients are returned
818 (if NULL, no coefficients returned).
819 @return double R value.
820
821 Double gaussian function:
822 y = a + b*exp(c*s^2) + d*exp(f*s^2)
823 **/
824 double ctf_fit_double_gaussian_baseline(long n, vector<double>& x, vector<double>& y, vector<double>& coeff)
825 {
826 long i;
827
828 Bsimplex simp(1, 5, 0, n, x, y);
829
830 simp.parameters(5, coeff);
831 simp.limits(0, 0, 1000);
832 simp.limits(1, 0, 100);
833 simp.limits(2, -1000, -0.1);
834
835 if ( n > 5 ) {
836 simp.limits(3, 0, 1000);
837 simp.limits(4, -10000, -1);
838 }
839
840 double R = simp.run(10000, 0.01, double_gaussian_R);
841
842 for ( i=0; i<5; i++ ) coeff[i] = simp.parameter(i);
843
844 return R;
845 }
846
847 /*
848 @brief Fits an EMAN-style baseline function.
849 @param n number of data points.
850 @param *x x array (at least order+1 values).
851 @param *y y array (at least order+1 values).
852 @param coeff array in which 4 coefficients are returned
853 (if NULL, no coefficients returned).
854 @return double R value.
855
856 EMAN baseline function:
857 y = a + b*exp( c*sqrt(s) + d*s^2 )
858 **/
859 double ctf_fit_eman_to_baseline(long n, vector<double>& x, vector<double>& y, vector<double>& coeff)
860 {
861 long i;
862
863 Bsimplex simp(1, 4, 0, n, x, y);
864
865 simp.parameters(4, coeff);
866 simp.limits(0, 0, 1000);
867 simp.limits(1, 0, 1000);
868 simp.limits(2, -100, 100);
869 simp.limits(3, -100, 0);
870
871 double R = simp.run(10000, 0.001, eman_baseline_R);
872
873 for ( i=0; i<4; i++ ) coeff[i] = simp.parameter(i);
874
875 return R;
876 }
877
878 /*
879 @brief Fits a gaussian function.
880 @param n number of data points.
881 @param *x x array (at least order+1 values).
882 @param *y y array (at least order+1 values).
883 @param coeff array in which 3 coefficients are returned
884 (if NULL, no coefficients returned).
885 @return double R value.
886
887 Gaussian function:
888 y = a + b*exp(c*s^2)
889 **/
890 double ctf_fit_gaussian(long n, vector<double>& x, vector<double>& y, vector<double>& coeff)
891 {
892 long i;
893
894 Bsimplex simp(1, 3, 0, n, x, y);
895
896 simp.parameters(3, coeff);
897 if ( coeff[0] ) simp.limits(0, 0, 1000);
898 simp.limits(1, 0.001, 100);
899 simp.limits(2, -1e4, -0.1);
900
901 double R = simp.run(10000, 0.01, gaussian_R);
902
903 for ( i=0; i<3; i++ ) coeff[i] = simp.parameter(i);
904
905 return R;
906 }
907
908 double ctf_fit_baseline_bump(long n, vector<double>& x, vector<double>& y, vector<double>& coeff)
909 {
910 long i, ilo(0), ns;
911 double slo(0.2), shi(0.3);
912
913 coeff[5] = 0;
914 coeff[6] = 0.25;
915 coeff[7] = -1e4;
916
917 vector<double> xb, yb;
918
919 for ( i=ns=0; i<n; i++ ) if ( x[i] > slo && x[i] < shi ) {
920 if ( !ilo ) ilo = i;
921 if ( coeff[5] < y[i] ) {
922 coeff[5] = y[i];
923 coeff[6] = x[i];
924 }
925 xb.push_back(x[i]);
926 yb.push_back(y[i]);
927 ns++;
928 // cout << x[i] << tab << y[i] << endl;
929 }
930
931 double slope((y[ilo+ns-1] - y[ilo])/(x[ilo+ns-1] - x[ilo]));
932 double inter(y[ilo] - slope*x[ilo]);
933
934 coeff[5] -= 0.5*(y[ilo] + y[ilo+ns-1]);
935
936 Bsimplex simp(1, 5, 0, ns, xb, yb);
937
938 // simp.parameters(5, &coeff[3]);
939 simp.parameter(0, inter);
940 simp.parameter(1, slope);
941 simp.parameter(2, coeff[5]);
942 simp.parameter(3, coeff[6]);
943 simp.parameter(4, coeff[7]);
944 simp.limits(0, 0.1*inter, 10*inter);
945 simp.limits(1, -5*fabs(slope), 5*fabs(slope));
946 simp.limits(2, 0.1*coeff[5], 10*coeff[5]);
947 simp.limits(3, 0.2, 0.3);
948 simp.limits(4, -1e5, -1e3);
949
950 // for ( i=0; i<5; i++ ) cout << tab << simp.parameter(i);
951 // cout << endl;
952
953 double R = simp.run(10000, 0.0001, gaussian1_R);
954
955 for ( i=2; i<5; i++ ) coeff[i+3] = simp.parameter(i);
956
957 // for ( i=0; i<5; i++ ) cout << tab << simp.parameter(i);
958 // cout << tab << R << endl;
959
960 return R;
961 }
962
963 /*
964 @brief Fits a double gaussian function.
965 @param n number of data points.
966 @param *x x array (at least order+1 values).
967 @param *y y array (at least order+1 values).
968 @param coeff array in which 5 coefficients are returned
969 (if NULL, no coefficients returned).
970 @return double R value.
971
972 Double gaussian function:
973 y = a + b*exp(c*s^2) + d*exp(f*s^2)
974 with a = 0
975 **/
976 double ctf_fit_double_gaussian_envelope(long n, vector<double>& x, vector<double>& y, vector<double>& coeff)
977 {
978 long i;
979
980 Bsimplex simp(1, 5, 0, n, x, y);
981
982 simp.parameters(5, coeff);
983 if ( coeff[0] ) simp.limits(0, 0, 1000);
984 simp.limits(1, 0.001, 100);
985 simp.limits(2, -500, -0.1);
986
987 if ( n > 5 ) {
988 simp.limits(3, 0.01, 100);
989 simp.limits(4, -5000, -1);
990 }
991
992 double R = simp.run(10000, 0.01, double_gaussian_R);
993
994 for ( i=0; i<5; i++ ) coeff[i] = simp.parameter(i);
995
996 return R;
997 }
998
999 double ctf_fit_baseline(Bimage* prad, double real_size, CTFparam& em_ctf, double lores, double hires)
1000 {
1001 double pixel_size = prad->sampling()[0];
1002 if ( pixel_size <= 0 ) pixel_size = 1;
1003
1004 long i, j, ib, nc(4);
1005 long istart = (long) (real_size/lores);
1006 long iend = (long) (real_size/hires);
1007 if ( istart < 1 ) istart = 1;
1008 if ( iend >= prad->sizeX() ) iend = prad->sizeX() - 1;
1009 long w = (iend - istart)/10;
1010
1011 double recip_interval = 1.0/real_size;
1012 double max_s = 0.45/pixel_size;
1013 long k = prad->sizeX()/100;
1014 if ( k < 1 ) k = 1;
1015
1016 double R = 1e30;
1017 vector<double> coeff(NCTFPARAM);
1018 for ( i=0; i<NCTFPARAM; i++ ) coeff[i] = em_ctf.baseline(i);
1019
1020 vector<double> s(prad->sizeX(), 0);
1021 vector<double> d(prad->sizeX(), 0);
1022
1023 vector<double> zero = em_ctf.zeroes(max_s);
1024 long n(zero.size());
1025
1026 if ( n > prad->sizeX() ) n = prad->sizeX();
1027
1028 if ( verbose & VERB_DEBUG )
1029 cout << "DEBUG ctf_fit_baseline: zeroes=" << n << endl;
1030
1031 double min = 1e10;
1032 double* mavg = NULL;
1033
1034 if ( n > 3 ) { // Enough zeroes to fit the baseline
1035 for ( i=0; i<n; i++ ) {
1036 ib = (long) (zero[i]*real_size + 0.5);
1037 s[i] = zero[i];
1038 d[i]=(*prad)[ib];
1039 for ( j=(ib>k)?ib-k:0; j<=ib+k && j<prad->sizeX(); j++ ) // minimum within kernel
1040 if ( d[i] > (*prad)[j] ) d[i] = (*prad)[j];
1041 }
1042 } else { // Too few zeroes, use local minima
1043 mavg = moving_average(prad->sizeX(), (double *) prad->data_pointer(), prad->sizeX()/10);
1044 for ( i=istart, n=0; i<iend; i++ ) {
1045 if ( min > (*prad)[i] - mavg[i] ) {
1046 min = (*prad)[i] - mavg[i];
1047 s[n] = recip_interval*i;
1048 d[n] = (*prad)[i];
1049 if ( d[n] > mavg[i] ) d[n] = mavg[i];
1050 }
1051 if ( i%w == 0 ) {
1052 min = 1e10;
1053 n++;
1054 }
1055 }
1056 s[n] = 10;
1057 d[n] = 0;
1058 n++;
1059 delete[] mavg;
1060 }
1061
1062 if ( verbose & VERB_DEBUG )
1063 cout << "DEBUG ctf_fit_baseline: fitting baseline type " << em_ctf.baseline_type() << endl;
1064
1065 if ( em_ctf.baseline_type() > 3 ) {
1066 ctf_fit_baseline_bump(n, s, d, coeff);
1067 for ( i=0; i<n; i++ )
1068 d[i] -= coeff[5] * exp(coeff[7] * (coeff[6] - s[i]) * (coeff[6] - s[i]));
1069 }
1070
1071 switch ( em_ctf.baseline_type() ) {
1072 case 1:
1073 case 4:
1074 if ( n < 5 ) nc = n - 1;
1075 R = fit_polynomial(n, s, d, nc, coeff);
1076 break;
1077 case 2:
1078 case 5:
1079 R = ctf_fit_double_gaussian_baseline(n, s, d, coeff);
1080 break;
1081 case 3:
1082 case 6:
1083 R = ctf_fit_eman_to_baseline(n, s, d, coeff);
1084 break;
1085 default:
1086 cerr << "Error: Baseline type " << em_ctf.baseline_type() << " not supported" << endl;
1087 }
1088
1089 if ( em_ctf.baseline_type() > 0 && em_ctf.baseline_type() < 7 )
1090 em_ctf.baseline(coeff);
1091
1092 return R;
1093 }
1094
1095 double ctf_fit_envelope(Bimage* prad, double real_size, CTFparam& em_ctf, double lores, double hires)
1096 {
1097 double pixel_size = prad->sampling()[0];
1098 if ( pixel_size <= 0 ) pixel_size = 1;
1099
1100 long i, j, ib;
1101 long k = prad->sizeX()/80;
1102 if ( k < 1 ) k = 1;
1103
1104 double max_s = 0.45/pixel_size;
1105 double R = 1e30;
1106
1107 vector<double> zero = em_ctf.zeroes(max_s);
1108 long nzero(zero.size());
1109
1110 if ( nzero > prad->sizeX() ) nzero = prad->sizeX();
1111
1112 double b, si;
1113 vector<double> coeff(NCTFPARAM);
1114 vector<double> s(nzero);
1115 vector<double> d(nzero);
1116 for ( i=0; i<NCTFPARAM; i++ ) coeff[i] = 0;
1117 for ( i=0; i<nzero; i++ ) s[i] = d[i] = 0;
1118
1119 ib = (long) (zero[0]*real_size + 0.5);
1120 d[0] = 0;
1121 for ( i=ib/2; i<ib; i++ ) {
1122 si = i/real_size;
1123 b = (*prad)[i] - em_ctf.calc_baseline(si);
1124 if ( d[0] < b ) {
1125 d[0] = b;
1126 s[0] = si;
1127 }
1128 }
1129
1130 for ( i=1; i<nzero; i++ ) {
1131 s[i] = (zero[i-1]+zero[i])*0.5;
1132 ib = (long) (s[i]*real_size + 0.5);
1133 b = em_ctf.calc_baseline(s[i]);
1134 d[i] = (*prad)[ib] - b;
1135 for ( j=(ib>k)?ib-k:0; j<=ib+k && j<prad->sizeX(); j++ ) // maximum within kernel
1136 if ( d[i] < (*prad)[j] - b ) d[i] = (*prad)[j] - b;
1137 }
1138
1139 if ( verbose & VERB_DEBUG ) {
1140 cout << "DEBUG ctf_fit_envelope: type " << em_ctf.envelope_type() << endl;
1141 for ( i=0; i<5; i++ ) cout << tab << em_ctf.envelope(i);
1142 cout << endl;
1143 }
1144
1145 switch ( em_ctf.envelope_type() ) {
1146 case 1: // Single gaussian
1147 for ( i=0; i<2; i++ ) coeff[i+1] = em_ctf.envelope(i);
1148 R = ctf_fit_gaussian(nzero-1, s, d, coeff);
1149 for ( i=0; i<2; i++ ) coeff[i] = coeff[i+1];
1150 coeff[i] = 0;
1151 break;
1152 case 2: // Single gaussian with constant
1153 for ( i=0; i<3; i++ ) coeff[i] = em_ctf.envelope(i);
1154 R = ctf_fit_gaussian(nzero-1, s, d, coeff);
1155 break;
1156 case 3: // Double gaussian
1157 for ( i=0; i<4; i++ ) coeff[i+1] = em_ctf.envelope(i);
1158 R = ctf_fit_double_gaussian_envelope(nzero, s, d, coeff);
1159 for ( i=0; i<4; i++ ) coeff[i] = coeff[i+1];
1160 coeff[i] = 0;
1161 break;
1162 case 4: // Double gaussian with constant
1163 for ( i=0; i<5; i++ ) coeff[i] = em_ctf.envelope(i);
1164 R = ctf_fit_double_gaussian_envelope(nzero, s, d, coeff);
1165 break;
1166 default: break;
1167 }
1168
1169 if ( verbose & VERB_DEBUG ) {
1170 cout << "DEBUG ctf_fit_envelope:";
1171 for ( i=0; i<5; i++ ) cout << tab << coeff[i];
1172 cout << endl;
1173 }
1174
1175 em_ctf.envelope(coeff);
1176
1177 return R;
1178 }
1179
M_PI_2
#define M_PI_2
Definition: utilities.h:62
CTFparam::baseline_type
long baseline_type()
Definition: ctf.h:106
moving_average
double * moving_average(long number, double *x, long window)
Calculates a moving average over an array of data.
Definition: moving_average.cpp:28
fit_polynomial
double fit_polynomial(int n, double *x, double *y, int order, double *coeff)
Fits a data set to a polynomial function.
Definition: matrix_linear.cpp:166
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
moving_average.h
Header file moving average calculations.
img_ctf_radial_subtract_baseline
Bimage * img_ctf_radial_subtract_baseline(Bimage *prad, double real_size, CTFparam &em_ctf)
Definition: mg_ctf_fit.cpp:460
utilities.h
Header file for general utilities.
CTFparam::astigmatism_angle
double astigmatism_angle()
Definition: ctf.h:104
Bsimplex
Structure used in the downhill simplex method.
Definition: simplex.h:42
ctf_fit_polynomial
double ctf_fit_polynomial(long n, vector< double > &x, vector< double > &y, vector< double > &coeff)
Definition: mg_ctf_fit.cpp:802
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
CTFparam::calc_envelope
double calc_envelope(double s)
Definition: ctf.h:189
Bsimplex::parameter
void parameter(long i, double p)
Definition: simplex.h:69
ctf_fit_double_gaussian_envelope
double ctf_fit_double_gaussian_envelope(long n, vector< double > &x, vector< double > &y, vector< double > &coeff)
Definition: mg_ctf_fit.cpp:976
Bimage::index
long index(long nx, long ny) const
Definition: Bimage.h:383
Bsimplex::dependent_values
vector< double > & dependent_values()
Definition: simplex.h:83
CTFparam::show_envelope
void show_envelope()
Definition: ctf.h:267
ctf_test_defocus
double ctf_test_defocus(CTFparam &em_ctf, double def, long nx, double step_size, vector< double > &r, long rmin, long rmax)
Definition: mg_ctf_fit.cpp:351
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
img_water_ring_index
double img_water_ring_index(Bimage *p, long img_num, CTFparam &em_ctf)
Calculates the water ring index from a power spectrum.
Definition: mg_ctf_fit.cpp:651
double_gaussian_R
double double_gaussian_R(Bsimplex &simp)
Definition: mg_ctf_fit.cpp:753
Bsimplex::run
double run(long maxcycles, double tolerance, double(funk)(Bsimplex &))
Definition: simplex.cpp:76
TSimple
Definition: Bimage.h:58
timer.h
Utilities for timing functions.
ctf_fit_envelope
double ctf_fit_envelope(Bimage *prad, double real_size, CTFparam &em_ctf, double lores, double hires)
Definition: mg_ctf_fit.cpp:1095
Bimage
General image parameter class.
Definition: Bimage.h:163
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:487
CTFparam::check_defocus
bool check_defocus()
Definition: ctf.h:123
CTFparam::calc_baseline
double calc_baseline(double s)
Definition: ctf.h:161
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
CTFparam::check_Cs
bool check_Cs()
Definition: ctf.h:131
Double
Definition: utilities.h:158
ctf_fit_baseline_bump
double ctf_fit_baseline_bump(long n, vector< double > &x, vector< double > &y, vector< double > &coeff)
Definition: mg_ctf_fit.cpp:908
gaussian1_R
double gaussian1_R(Bsimplex &simp)
Definition: mg_ctf_fit.cpp:731
Bimage::statistics
long statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
moving_polynomial
vector< double > moving_polynomial(long order, long number, double *x, long window)
Calculates a moving polynomial fit over an array of data.
Definition: moving_average.cpp:122
img_ctf_astigmatism_measure
double img_ctf_astigmatism_measure(Bimage *p, long n, double real_size, CTFparam &em_ctf, double lores, double hires)
Definition: mg_ctf_fit.cpp:485
img_ctf_fit_baseline
double img_ctf_fit_baseline(Bimage *p, long n, CTFparam &em_ctf, double lores, double hires)
Fits only the baseline for a given CTF.
Definition: mg_ctf_fit.cpp:299
CTFparam::defocus_deviation
double defocus_deviation()
Definition: ctf.h:102
CTFparam::calculate
double calculate(double s2, double angle)
Definition: ctf.h:149
img_ctf_fit_residual
double img_ctf_fit_residual(Bimage *p, long n, CTFparam &em_ctf, double lores, double hires)
Definition: mg_ctf_fit.cpp:143
CTFparam::show
void show()
Definition: ctf.h:232
CTFparam::envelope_type
long envelope_type()
Definition: ctf.h:113
NCTFPARAM
#define NCTFPARAM
Definition: ctf.h:15
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:127
ctf_fit_baseline
double ctf_fit_baseline(Bimage *prad, double real_size, CTFparam &em_ctf, double lores, double hires)
Definition: mg_ctf_fit.cpp:999
ctf_fit_eman_to_baseline
double ctf_fit_eman_to_baseline(long n, vector< double > &x, vector< double > &y, vector< double > &coeff)
Definition: mg_ctf_fit.cpp:859
Bimage::set
void set(long j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:1096
img_ctf_radial_average
Bimage * img_ctf_radial_average(Bimage *p, long n, CTFparam &em_ctf)
Calculates the power spectrum radial average corrected for astigmatism.
Definition: mg_ctf_fit.cpp:46
CTFparam::fom
double fom()
Definition: ctf.h:120
CTFparam::zeroes
vector< double > zeroes(double max_s)
Calculates the zeroes of a CTF curve on the spatial frequency scale.
Definition: ctf.cpp:115
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:261
simplex.h
Nelder and Mead downhill simplex method for generalized parameter fitting.
img_ctf_fit
double img_ctf_fit(Bimage *p, long n, CTFparam &em_ctf, double lores, double hires, double def_start, double def_end, double def_inc, int flag)
Determines the CTF parameters from a power spectrum.
Definition: mg_ctf_fit.cpp:209
Bimage::copy
Bimage * copy()
Copies the header information and data of an image into a new image structure.
Definition: Bimage.cpp:2695
Bimage::sizeX
void sizeX(long nx)
Definition: Bimage.h:377
img_ctf_fit_envelope
double img_ctf_fit_envelope(Bimage *p, long n, CTFparam &em_ctf, double lores, double hires)
Fits only the envelope for a given CTF.
Definition: mg_ctf_fit.cpp:332
eman_baseline_R
double eman_baseline_R(Bsimplex &simp)
Definition: mg_ctf_fit.cpp:772
img_ctf_fit_astigmatism
double img_ctf_fit_astigmatism(Bimage *p, long n, CTFparam &em_ctf, double lores, double hires)
Fits the astigmatism with a given defocus, baseline and envelope.
Definition: mg_ctf_fit.cpp:557
Bimage::sizeZ
void sizeZ(long nz)
Definition: Bimage.h:379
ctf_fit_double_gaussian_baseline
double ctf_fit_double_gaussian_baseline(long n, vector< double > &x, vector< double > &y, vector< double > &coeff)
Definition: mg_ctf_fit.cpp:824
Bsimplex::parameters
long parameters()
Definition: simplex.h:65
CTFparam::defocus_average
double defocus_average()
Definition: ctf.h:100
mg_processing.h
Header file for micrograph processing.
CTFparam::baseline
vector< double > & baseline()
Definition: ctf.h:108
rwimg.h
Header file for 2D and 3D image I/O.
ctf_fit_gaussian
double ctf_fit_gaussian(long n, vector< double > &x, vector< double > &y, vector< double > &coeff)
Definition: mg_ctf_fit.cpp:890
CTFparam::show_baseline
void show_baseline()
Definition: ctf.h:244
CTFparam::envelope
vector< double > & envelope()
Definition: ctf.h:115
mg_ctf_fit.h
Header file for CTF (contrast transfer function) functions.
verbose
int verbose
img_ctf_find_defocus
double img_ctf_find_defocus(Bimage *p, long n, CTFparam &em_ctf, double lores, double hires, double def_start, double def_end, double def_inc)
Searches for the defocus based on correlation.
Definition: mg_ctf_fit.cpp:391
VERB_FULL
#define VERB_FULL
Definition: utilities.h:109
Bimage::sizeY
void sizeY(long ny)
Definition: Bimage.h:378
Bsimplex::limits
void limits(long i, double vlo, double vhi)
Definition: simplex.h:75
gaussian_R
double gaussian_R(Bsimplex &simp)
Definition: mg_ctf_fit.cpp:713
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
CTFparam
Definition: ctf.h:26