| Bsoft 2.0.5 Bernard's software package

mg_reconstruct.cpp
Go to the documentation of this file.
1
9 #include "rwimg.h"
10 #include "rwmg.h"
11 #include "mg_processing.h"
12 #include "mg_img_proc.h"
13 #include "mg_particle_select.h"
14 #include "mg_reconstruct.h"
15 #include "mg_ctf.h"
16 #include "Complex.h"
17 #include "symmetry.h"
18 #include "utilities.h"
19
20 #include <sys/stat.h>
21 #include <fcntl.h>
22
23
24 // Declaration of global variables
25 extern int verbose; // Level of output to the screen
26
37 int part_ft_size(int xsize, double scale, int pad_factor)
38 {
39 if ( xsize <= 0 ) {
40 error_show("Error in part_ft_size", __FILE__, __LINE__);
41 cerr << "Size not set!" << endl << endl;
42 return 0;
43 }
44
45 int ft_size(xsize);
46
47 if ( scale > 1 ) ft_size = (int) (xsize*scale);
48
49 if ( pad_factor < 1 ) return ft_size;
50
51 if ( pad_factor > 8 ) pad_factor = 8;
52
53 ft_size = findNextPowerOf((int)(pad_factor*xsize*scale), 2);
54
55 if ( ft_size < xsize )
56 // ft_size = findNextPowerOf(pad_factor*xsize, 2);
57 ft_size = findNextPowerOf(xsize, 2);
58
59 // if ( ft_size < xsize/scale )
60 // ft_size = findNextPowerOf((int)(xsize/scale), 2);
61
62 return ft_size;
63 }
64
99 Bimage* particle_reconstruct(Bparticle* partlist, Bsymmetry* sym, int sym_mode,
100 double hi_res, double scale, Vector3<long> size,
101 int ft_size, fft_plan plan, int interp_type,
102 int ctf_action, double wiener, int twoD_flag,
103 int bootstrap, int first)
104 {
105 random_seed();
106
107 Bmicrograph* mg = partlist->mg;
108 Bparticle* part = partlist;
109
110 Bimage* p;
111 Bimage* prec = new Bimage(Float, TComplex, size, 1);
112 if ( twoD_flag ) prec->sampling(part->pixel_size/scale, part->pixel_size/scale, 1);
113 else prec->sampling(part->pixel_size/scale, part->pixel_size/scale, part->pixel_size/scale);
114 // prec->origin(prec->size()/2);
115
116 if ( hi_res < 2*prec->sampling()[0] ) hi_res = 2*prec->sampling()[0];
117
118 long nsel = particle_count(partlist);
119
120 if ( verbose & VERB_DEBUG )
121 cout << "DEBUG particle_reconstruct: nsel = " << nsel << endl;
122
123 CTFparam em_ctf;
124
125 long nrec(0), img_num;
126 double part_scale(scale), part_weight(1), pad_ratio(1);
127 View view;
128 Bstring partfile;
129
130 for ( part = partlist; part; part = part->next ) {
131 // cout << "Particle: " << part->id << endl;
132 mg = part->mg;
133 if ( mg->ctf ) em_ctf.update(mg->ctf);
134 partfile = mg->fpart;
135 img_num = part->id - 1;
136 if ( partfile.length() < 1 ) {
137 partfile = part->fpart;
138 img_num = 0;
139 }
140 if ( ( p = read_img(partfile, 1, img_num) ) == NULL ) {
141 error_show("particle_reconstruct", __FILE__, __LINE__);
142 return NULL;
143 }
144
145 p->change_type(Float);
146 p->rescale_to_avg_std(0, 1);
147 p->calculate_background();
148 p->sampling(part->pixel_size, part->pixel_size, 1);
149 // cout << "particle sampling = " << p->sampling() << endl;
150
151 // set the origin
152 if ( part->ori[0] <= 0 ) {
153 if ( p->image->origin()[0] > 0 ) part->ori = p->image->origin();
154 else part->ori = prec->image->origin();
155 }
156 part->ori[2] = 0;
157 // p->image->origin(part->ori);
158 p->origin(part->ori);
159
160 // set the view
161 p->view(part->view);
162 if ( sym_mode == 2 ) view = random_symmetric_view(part->view, sym);
163 else view = part->view;
164
165 if ( prec->sizeZ() < 2 ) {
166 if ( p->image->view()[2] >= 0 ) p->image->view(0,0,1,p->image->view().angle());
167 else p->image->view(0,0,-1,p->image->view().angle());
168 }
169
170 // set the scaling
171 if ( part->mag > 0 ) part_scale = scale/part->mag;
172 else part_scale = scale;
173
174 if ( part->def > 0 ) em_ctf.defocus_average(part->def);
175
176 part_weight = 1;
177 if ( bootstrap ) part_weight = part->sel;
178
179 pad_ratio = ft_size*1.0L/p->sizeX();
180
181 if ( pad_ratio > 1 ) {
182 // pad_ratio *= pad_ratio;
183 pad_ratio *= pad_ratio*0.6;
184 // pad_ratio *= pad_ratio*M_PI/4.0;
185 // pad_ratio *= sqrt(pad_ratio);
186 part_weight /= pad_ratio;
187 p->pad(ft_size, FILL_BACKGROUND);
188 // p->pad(ft_size, FILL_AVERAGE, p->average());
189 // p->pad(ft_size, FILL_USER, 0);
190 }
191
192 p->fft(plan, 1);
193 p->phase_shift_to_origin();
194
195 if ( ctf_action ) img_ctf_apply(p, em_ctf, ctf_action, wiener, 0, hi_res);
196
197 if ( sym_mode )
198 prec->fspace_pack_2D(p, view.matrix(), hi_res, 0, part_scale, part_weight, interp_type);
199 else
200 prec->fspace_pack_2D(p, view, sym, hi_res, 0, part_scale, part_weight, interp_type);
201
202 if ( mg->ctf ) em_ctf.defocus_average(mg->ctf->defocus_average());
203
204 delete p;
205
206 nrec++;
207
208 if ( first && ( verbose & ( VERB_TIME | VERB_PROCESS | VERB_RESULT ) ) )
209 cerr << "Complete: " << setprecision(3)
210 << nrec*100.0/nsel << " % \r" << flush;
211 }
212
213 prec->image->FOM(nrec);
214
215 if ( verbose & VERB_FULL )
216 cout << "Particles used: " << nrec << endl << endl;
217
218 return prec;
219 }
220
236 Bparticle* project_reconstruction_partlist(Bproject* project,
237 int num_select, int bootstrap)
238 {
239 Bfield* field = project->field;
240 Bmicrograph* mg = field->mg;
241 Breconstruction* rec = project->rec;
242 Bparticle* part = mg->part;
243 Bparticle* partlist = NULL;
244
245 if ( verbose & VERB_DEBUG )
246 cout << "DEBUG project_reconstruction_partlist: num_select = " << num_select << endl;
247
248 long psel;
249
250 if ( project->select < 1 ) {
251 for ( field = project->field; field; field = field->next ) {
252 for ( mg = field->mg; mg; mg = mg->next ) {
253 for ( part = mg->part; part; part = part->next ) {
254 psel = 0;
255 if ( part->sel ) {
256 if ( bootstrap ) {
257 psel = 1;
258 } else if ( num_select < 0 ) {
259 psel = 1;
260 } else if ( part->sel == num_select ) {
261 psel = 1;
262 }
263 }
264 if ( psel ) // Use only selected images
265 particle_copy(&partlist, part);
266 }
267 }
268 }
269 } else {
270 for ( rec = project->rec; rec; rec = rec->next ) {
271 for ( part = rec->part; part; part = part->next ) {
272 psel = 0;
273 if ( part->sel ) {
274 if ( bootstrap ) {
275 psel = 1;
276 } else if ( num_select < 0 ) {
277 psel = 1;
278 } else if ( part->sel == num_select ) {
279 psel = 1;
280 }
281 }
282 if ( psel ) // Use only selected images
283 particle_copy(&partlist, part);
284 }
285 }
286 }
287
288 return partlist;
289 }
290
315 Bimage* img_reconstruction_sum_weigh(Bimage** pacc, int imap, int nmaps, int maps_per_class, double hi_res)
316 {
317 int iclass = imap/nmaps;
318
319 Bimage* prec = new Bimage(Float, TComplex, pacc[0]->size(), pacc[0]->images());
320 prec->sampling(pacc[0]->sampling());
321 prec->fourier_type(Standard);
322
323 prec->next = new Bimage(Float, TSimple, prec->size(), prec->images());
324 prec->next->next = new Bimage(Float, TSimple, prec->size(), prec->images());
325 prec->next->next->next = new Bimage(Float, TSimple, prec->size(), prec->images());
326 float* fom = (float *) prec->next->data_pointer();
327 float* weight = (float *) prec->next->next->data_pointer();
328 float* weight2 = (float *) prec->next->next->next->data_pointer();
329
330 long i, j, k, nv(0);
331 long ds = (long) prec->size().volume();
332 float* fom_acc;
333 float* w_acc;
334 float* w2_acc;
335
336 long st(0), inc(1);
337 if ( nmaps == 2 ) {
338 st = imap%2;
339 inc = 2;
340 }
341 if ( nmaps == 3 && imap%3 ) {
342 st = imap%3 - 1;
343 inc = 2;
344 }
345
346 if ( verbose & VERB_DEBUG ) {
347 cout << "DEBUG img_reconstruction_sum_weigh: maps_per_class=" << maps_per_class << endl;
348 cout << "DEBUG img_reconstruction_sum_weigh: iclass=" << iclass << endl;
349 cout << "DEBUG img_reconstruction_sum_weigh: st=" << st << endl;
350 cout << "DEBUG img_reconstruction_sum_weigh: inc=" << inc << endl;
351 }
352
353 for ( i=iclass*maps_per_class+st, j=st; j<maps_per_class; i+=inc, j+=inc ) {
354 if ( verbose & VERB_DEBUG )
355 cout << "DEBUG img_reconstruction_sum_weigh: Doing map " << i << endl;
356 fom_acc = (float *) pacc[i]->next->data_pointer();
357 w_acc = (float *) pacc[i]->next->next->data_pointer();
358 w2_acc = (float *) pacc[i]->next->next->next->data_pointer();
359 for ( k=0; k<ds; k++ ) {
360 prec->add(k, pacc[i]->complex(k));
361 fom[k] += fom_acc[k];
362 weight[k] += w_acc[k];
363 weight2[k] += w2_acc[k];
364 }
365 nv++;
366 }
367
368 if ( verbose & VERB_DEBUG )
369 cout << "DEBUG img_reconstruction_sum_weigh: volumes accumulated: " << nv << endl;
370
371 long cov = prec->fspace_reconstruction_weigh();
372
373 double Rf = prec->friedel_check();
374 // if ( Rf > 0.001 ) prec->friedel_apply();
375
376 if ( verbose ) {
377 if ( inc == 1 )
378 cout << "Full reconstruction:" << endl;
379 else
380 cout << "Half reconstruction " << st+1 << ":" << endl;
381 cout << "Friedel symmetry residual: " << Rf << endl;
382 cout << "Coverage: " << cov << " (" << cov*100.0/ds << " %)" << endl << endl;
383 }
384
385 if ( imap%nmaps == 0 )
386 prec->fspace_reconstruction_stats(hi_res);
387
388 prec->fspace_reconstruction_snr();
389
390 if ( verbose & VERB_DEBUG )
391 write_img("weight.map", prec->next->next, 0);
392
393 delete prec->next->next;
394 prec->next->next = NULL;
395
396 prec->phase_shift_to_center();
397 prec->origin(prec->size()/2);
398
399 return prec;
400 }
401
402
403
404 double part_single_reconstruction(Bparticle* part, Vector3<long> size,
405 Bimage* pmask, Bsymmetry* sym, double hi_res, double scale,
406 int ft_size, fft_plan img_plan, fft_plan map_plan, double part_weight,
407 int interp_type, CTFparam* mg_ctf, int ctf_action, double wiener, int flags)
408 {
409 FOMType fom_tag[NFOM] = {FOM, FOM_CV};
410
411 if ( ppx_check(part, fom_tag) ) return part->fom[0];
412
413 double dens(0);
414 Bparticle* partone = NULL;
415 particle_copy(&partone, part);
416
417 Bimage* prec = particle_reconstruct(partone, sym, 0, hi_res, scale, size,
418 ft_size, img_plan, interp_type, ctf_action, wiener, 0, 0, 0);
419
420 long ncov = prec->fspace_reconstruction_weigh();
421 double sf = prec->real_size()[0]/hi_res;
422 double cov = ncov / ((4.0*M_PI/3.0)*sf*sf*sf);
423
424 prec->phase_shift_to_center();
425 prec->origin(prec->size()/2);
426
427 prec->fft(map_plan, 1);
428 prec->complex_to_real();
429
430 prec->statistics();
431
432 // cout << "avg=" << prec->average() << " std=" << prec->standard_deviation() << endl;
433
434 if ( pmask ) dens = prec->relative_density(pmask);
435 else dens = prec->standard_deviation();
436
437 // if ( part->id == 7 ) write_img("prec.pif", prec);
438
439 delete prec;
440
441 part->fom[0] = dens;
442 part->fom[1] = cov;
443
444 if ( flags & WRITE_PPX ) {
445 Bstring ppx_name = ppx_filename(part->mg->id, part->id);
446 write_particle(ppx_name, part, 0, 0, fom_tag);
447 ppx_name = 0;
448 }
449
450 return dens;
451 }
452
489 long project_single_particle_reconstruction(Bproject* project,
490 Bstring& maskfile, Bsymmetry* sym,
491 int num_select, double hi_res, double scale, Vector3<long> size,
492 int pad_factor, int interp_type, int ctf_action, double wiener, int flags)
493 {
494 if ( size.volume() <= 0 )
495 size = project_set_reconstruction_size(project, scale, 0);
496
497 if ( size.volume() <= 0 ) {
498 error_show("Error in project_single_particle_reconstruction", __FILE__, __LINE__);
499 cerr << "No particles to determine the size from!" << endl << endl;
500 return -1;
501 }
502
503 int ft_size = part_ft_size(size[0], scale, pad_factor);
504
505 fft_plan img_plan = fft_setup_plan(ft_size, ft_size, 1, FFTW_FORWARD, 1);
506 fft_plan map_plan = fft_setup_plan(size[0], size[1], size[2], FFTW_BACKWARD, 1);
507
508 long i, j;
509
510 Bfield* field = project->field;
511 Bmicrograph* mg = field->mg;
512 Bparticle* part = mg->part;
513
514 for ( field = project->field; field && part == NULL; field = field->next )
515 for ( mg = field->mg; mg && part == NULL; mg = mg->next )
516 part = mg->part;
517
518 if ( size.volume() <= 0 ) {
519 error_show("Error in project_single_particle_reconstruction", __FILE__, __LINE__);
520 cerr << "No reconstruction size set!" << endl << endl;
521 return -1;
522 }
523
524 Bimage* pmask = NULL;
525
526 if ( hi_res < 2*part->pixel_size/scale ) hi_res = 2*part->pixel_size/scale;
527
528 if ( maskfile.length() )
529 if ( ( pmask = read_img(maskfile, 1, 0) ) == NULL ) {
530 error_show("project_single_particle_reconstruction", __FILE__, __LINE__);
531 return -1;
532 }
533
534 long datasize = (long) size.volume();
535 long maskedsize = datasize;
536
537 if ( pmask ) for ( i=maskedsize=0; i<datasize; i++ ) if ( (*pmask)[i] == 1 ) maskedsize++;
538
539 long nsel = project_count_mg_part_selected(project, num_select);
540
541 if ( verbose & VERB_DEBUG )
542 cout << "DEBUG project_single_particle_reconstruction: num_select = " << num_select << endl;
543
544 if ( verbose ) {
545 cout << "3D reciprocal space reconstruction:" << endl;
546 if ( pmask )
547 cout << "Mask: " << pmask->file_name() << endl;
548 cout << "Map size: " << size << endl;
549 cout << "Resolution limit: " << hi_res << " A" << endl;
550 cout << "Scale: " << scale << endl;
551 cout << "Interpolation type: " << interp_type << endl;
552 cout << "CTF application type: " << ctf_action << endl;
553 cout << "Fourier transform size: " << ft_size << " x " << ft_size << endl;
554 cout << "Analysis volume: " << maskedsize << " (" << maskedsize*100.0/datasize << " %)" << endl;
555 cout << "Number of selected particles: " << nsel << endl << endl;
556 }
557
558 long np(0);
559 double part_weight(1);
560 Bparticle** part_array;
561
562 // Directory for individual particle parameter files
563 if ( flags & WRITE_PPX ) {
564 mkdir("ppx", O_CREAT );
565 chmod("ppx", 0755);
566 }
567
568 for ( field = project->field; field; field = field->next ) {
569 for ( mg = field->mg; mg; mg = mg->next ) {
570 for ( i=0, part = mg->part; part; part = part->next ) if ( part->sel ) {
571 if ( num_select < 0 ) i++;
572 else if ( part->sel == num_select ) i++;
573 }
574 part_array = new Bparticle*[i];
575 for ( i=0, part = mg->part; part; part = part->next ) if ( part->sel ) {
576 if ( num_select < 0 ) part_array[i++] = part;
577 else if ( part->sel == num_select ) part_array[i++] = part;
578 }
579
580 #ifdef HAVE_GCD
581 dispatch_apply(i, dispatch_get_global_queue(0, 0), ^(size_t j){
582 part_array[j]->fom[0] = part_single_reconstruction(part_array[j],
583 size, pmask, sym, hi_res, scale,
584 ft_size, img_plan, map_plan, part_weight,
585 interp_type, mg->ctf, ctf_action, wiener, flags);
586 });
587 #else
588 #pragma omp parallel for
589 for ( j=0; j<i; j++ )
590 part_array[j]->fom[0] = part_single_reconstruction(part_array[j],
591 size, pmask, sym, hi_res, scale,
592 ft_size, img_plan, map_plan, part_weight,
593 interp_type, mg->ctf, ctf_action, wiener, flags);
594 #endif
595
596 np += i;
597 if ( verbose ) {
598 cout << "Micrograph: " << mg->id << endl;
599 cout << "PID\tFOM\tCov" << endl;
600 for ( j=0; j<i; j++ ) cout << part_array[j]->id << tab << part_array[j]->fom[0]
601 << tab << part_array[j]->fom[1] << endl;
602 cout << "Particles processed: " << np << endl;
603 }
604 delete[] part_array;
605 }
606 }
607
608 fft_destroy_plan(img_plan);
609 fft_destroy_plan(map_plan);
610
611 if ( verbose )
612 cout << endl;
613
614 return np;
615 }
616
617
628 Vector3<long> project_set_reconstruction_size(Bproject* project, double scale, int twoD_flag)
629 {
630 if ( verbose & VERB_DEBUG )
631 cout << "DEBUG project_set_reconstruction_size: scale=" << scale << endl;
632
633 Vector3<long> size;
634 Bfield* field = NULL;
635 Bmicrograph* mg = NULL;
636 Bparticle* part = NULL;
637 Bstring partfile;
638
639 for ( field = project->field; field && part == NULL; field = field->next )
640 for ( mg = field->mg; mg && part == NULL; mg = (part)? mg: mg->next )
641 part = mg->part;
642
643 if ( !mg ) {
644 error_show("Error in project_set_reconstruction_size", __FILE__, __LINE__);
645 cerr << "No micrograph with particles!" << endl << endl;
646 return size ;
647 }
648
649 partfile = mg->fpart;
650 if ( !partfile.length() ) partfile = part->fpart;
651
652 if ( !partfile.length() ) {
653 error_show("Error in project_set_reconstruction_size", __FILE__, __LINE__);
654 cerr << "No particle image file name given for micrograph " << mg->id << endl << endl;
655 return size;
656 }
657
658 Bimage* p = read_img(partfile, 0, 0);
659
660 size[0] = (int) (p->sizeX()*scale);
661 if ( size[0] < p->sizeY()/scale ) size[0] = (int) (p->sizeY()*scale);
662 if ( size[0] < p->sizeZ()/scale ) size[0] = (int) (p->sizeZ()*scale);
663 size[2] = size[1] = size[0];
664
665 if ( twoD_flag ) size[2] = 1;
666
667 delete p;
668
669 size = size.max(1);
670
671 if ( verbose & VERB_DEBUG )
672 cout << "DEBUG project_set_reconstruction_size: size=" << size << endl;
673
674 return size;
675 }
676
693 int project_configure_for_reconstruction(Bproject* project, Bstring classes, long& nmaps, long& nthreads)
694 {
695 if ( !classes.length() ) classes = "selected";
696 classes = classes.lower();
697 if ( nmaps < 1 ) nmaps = 1;
698 if ( nmaps > 3 ) nmaps = 3;
699 if ( nthreads < 1 ) nthreads = 1;
700 if ( nmaps&2 && nthreads%2 ) nthreads++;
701
702 long i, msel(1), nsel(0), nclass(0);
703 Bfield* field;
704 Bmicrograph* mg;
705 Breconstruction* rec;
706 Bparticle* part;
707
708 if ( classes[0] == 'a' ) {
709 part_reset_selection(project);
710 } else if ( classes[0] == 's' ) {
711 part_consolidate_selection(project, 1);
712 } else {
713 if ( project->select ) {
714 for ( rec = project->rec; rec; rec = rec->next )
715 for ( part = rec->part; part; part = part->next )
716 if ( msel < part->sel ) msel = part->sel;
717 } else {
718 for ( field = project->field; field; field = field->next )
719 for ( mg = field->mg; mg; mg = mg->next )
720 for ( part = mg->part; part; part = part->next )
721 if ( msel < part->sel ) msel = part->sel;
722 }
723 if ( verbose )
724 cout << "Maximum selection number: " << msel << endl;
725 }
726
727 msel++;
728 int* sel = new int[msel];
729 int* cnt = new int[msel];
730 int* num = new int[msel];
731 for ( i=0; i<msel; i++ ) sel[i] = cnt[i] = num[i] = 0;
732 if ( classes[0] == 'a' || classes[0] == 's' ) {
733 sel[1] = 1;
734 nclass = 1;
735 } else {
736 select_numbers(classes, msel, sel);
737 for ( i=1; i<msel; i++ ) if ( sel[i] ) sel[i] = ++nclass;
738 }
739
740 // if ( verbose & VERB_FULL ) {
741 if ( verbose ) {
742 cout << "Selection:" << endl << "Class\tNumber" << endl;
743 for ( i=0; i<msel; i++ ) cout << i << tab << sel[i] << endl;
744 }
745
746 // Set up the total number of threads
747 int maps_per_class = nthreads;
748 if ( verbose ) {
749 cout << "Classes: " << classes << " (" << nclass << ")" << endl;
750 cout << "Maps per class: ";
751 if ( nmaps == 1 ) cout << "Full set map" << endl;
752 if ( nmaps == 2 ) cout << "Two half set maps" << endl;
753 if ( nmaps == 3 ) cout << "Full set map and two half set maps" << endl;
754 cout << "Threads per class: " << nthreads << endl;
755 cout << "Total number of threads: " << nclass*nthreads << endl << endl;
756 }
757
758 if ( project->select ) {
759 for ( rec = project->rec; rec; rec = rec->next )
760 for ( part = rec->part; part; part = part->next ) {
761 i = part->sel;
762 if ( i>0 && i<msel && sel[i] ) {
763 num[i]++;
764 cnt[i]++;
765 part->sel = (sel[i] - 1)*maps_per_class + cnt[i];
766 if ( cnt[i] >= maps_per_class ) cnt[i] = 0;
767 nsel++;
768 } else {
769 part->sel = 0;
770 num[0]++;
771 }
772 }
773 } else {
774 for ( field = project->field; field; field = field->next )
775 for ( mg = field->mg; mg; mg = mg->next )
776 for ( part = mg->part; part; part = part->next ) {
777 i = part->sel;
778 // cout << mg->id << tab << part->id << tab << part->sel << endl;
779 if ( i>0 && i<msel && sel[i] ) {
780 num[i]++;
781 cnt[i]++;
782 part->sel = (sel[i] - 1)*maps_per_class + cnt[i];
783 // cout << sel[i] << tab << cnt[i] << tab << part->sel << endl;
784 if ( cnt[i] >= maps_per_class ) cnt[i] = 0;
785 nsel++;
786 } else {
787 part->sel = 0;
788 num[0]++;
789 }
790 }
791 }
792
793 if ( verbose ) {
794 cout << "Particles selected:" << endl;
795 cout << "Class\tNumber" << endl;
796 for ( i=0; i<msel; i++ ) if ( sel[i] )
797 cout << i << tab << num[i] << endl;
798 cout << endl;
799 }
800
801 delete[] sel;
802 delete[] cnt;
803 delete[] num;
804
805 return nclass;
806 }
807
822 Bimage* project_reconstruct_2D(Bproject* project, int transform_output)
823 {
824 long n, i, j, k, npart;
825
826 Bfield* field = project->field;
827 Bmicrograph* mg = field->mg;
828 Bparticle* part = mg->part;
829
830 Bimage* p = read_img(mg->fpart, 0, 0);
831
832 Vector3<long> size(p->size());
833 double px(part->pixel_size), hires(2*px);
834
835 delete p;
836
837 // Determine the number of reconstructions to generate
838 long nmap(0);
839 for ( field=project->field; field; field=field->next )
840 for ( mg=field->mg; mg; mg=mg->next )
841 for ( part=mg->part; part; part=part->next )
842 if ( part->sel > nmap ) nmap = part->sel;
843
844 if ( nmap < 1 ) return NULL;
845
846 Bimage* prec = new Bimage(Float, TSimple, size, nmap);
847 prec->origin(prec->size()/2);
848 prec->sampling(px, px, 1);
849
850 Bstring filename;
851
852 int* num = new int[nmap];
853 float* fom = new float[nmap];
854 for ( i=0; i<nmap; i++ ) {
855 num[i] = 0;
856 fom[i] = 0;
857 }
858
859 if ( verbose & VERB_RESULT ) {
860 cout << "2D real space reconstruction:" << endl;
861 cout << "Map size: " << prec->size() << endl;
862 cout << "Map origin: " << prec->image->origin() << endl;
863 cout << "Number of maps: " << prec->images() << endl << endl;
864 }
865
866 Vector3<double> origin, translate;
867 Vector3<double> scale(1,1,1);
868 Vector3<double> axis(0,0,1);
869 Matrix3 mat(1);
870 Euler euler;
871
872 Bimage* proj = NULL;
873
874 for ( field=project->field; field; field=field->next ) {
875 for ( mg=field->mg; mg; mg=mg->next ) {
876 npart = micrograph_count_particles(mg);
877 if ( verbose )
878 cout << "Micrograph: " << mg->id << " with " << npart << " particles" << endl;
879 if ( npart ) {
880 if ( transform_output ) {
881 proj = new Bimage(Float, TSimple, size, npart);
882 proj->sampling(px, px, 1);
883 }
884 for ( part=mg->part; part; part=part->next ) {
885 j = part->id - 1;
886 n = part->sel - 1;
887 // p = read_img(mg->fpart, 1, j);
888 p = particle_read_img(part, 1);
889 p->change_type(Float);
890 p->rescale_to_avg_std(0, 1);
891 p->shift_background(0);
892 p->sampling(px, px, 1);
893 if ( mg->ctf ) img_ctf_apply(p, *(mg->ctf), 1, 0.2, 0, hires);
894 if ( n < 0 ) {
895 translate = prec->image->origin() - part->ori;
896 } else {
897 translate = prec->image[n].origin() - part->ori;
898 }
899 origin = part->ori;
900 euler = Euler(part->view);
901 mat = Matrix3(axis, euler.psi());
902 // mat = Matrix3(axis, part->view.angle());
903 p->transform(scale, origin, translate, mat, FILL_BACKGROUND, 0);
904 if ( part->sel ) {
905 num[n]++;
906 fom[n] += part->fom[0];
907 prec->add(n, p);
908 }
909 if ( transform_output ) {
910 proj->image[j].view(0,0,1,0);
911 proj->replace(j, p);
912 }
913 delete p;
914 }
915 if ( transform_output ) {
916 proj->origin(prec->image->origin());
917 filename = mg->fpart.pre_rev('.') + "_proj.spi";
918 if ( verbose & VERB_RESULT )
919 cout << "Writing projections file: " << filename << endl;
920 write_img(filename, proj, 0);
921 delete proj;
922 }
923 }
924 }
925 }
926
927 npart = project_count_mg_particles(project);
928
929 // Normalize the new reconstructions
930 for ( i=n=0; n<prec->images(); n++ ) {
931 if ( num[n] ) fom[n] /= num[n];
932 prec->image[n].FOM(num[n]);
933 for ( k=0; k<prec->image_size(); i++, k++ )
934 if ( num[n] ) prec->set(i, (*prec)[i] / num[n]);
935 }
936
937 prec->statistics();
938
939 if ( verbose & VERB_RESULT ) {
940 cout << "Particles used in reconstruction:" << endl;
941 cout << "Map\tNumber\t%\tFOM" << endl;
942 for ( n=0; n<nmap; n++ ) {
943 cout << n+1 << tab << num[n] << tab <<
944 num[n]*100.0/npart << tab << fom[n] << endl;
945 }
946 cout << endl;
947 }
948
949 delete[] num;
950 delete[] fom;
951
952 return prec;
953 }
954
955 Bparticle* img_reconstruct_2D(long i, Bproject* project, Bimage* prec,
956 double hires, fft_plan planf, fft_plan planb)
957 {
958 long n(0);
959 Bfield* field = project->field;
960 Bmicrograph* mg = field->mg;
961 Bparticle* part = mg->part;
962 Bimage* p = NULL;
963
964 double f(0);
965 Vector3<double> origin, translate;
966 Vector3<double> scale(1,1,1);
967 Vector3<double> axis(0,0,1);
968 Matrix3 mat(1);
969 Euler euler;
970
971 // cout << "Map: " << i+1 << endl;
972
973 for ( field = project->field; field; field = field->next ) {
974 for ( mg = field->mg; mg; mg = mg->next ) {
975 for ( part = mg->part; part; part = part->next ) if ( part->sel == i+1 ) {
976 // p = read_img(mg->fpart, 1, part->id - 1);
977 p = particle_read_img(part, 1);
978 if ( p ) {
979 p->change_type(Float);
980 p->rescale_to_avg_std(0, 1);
981 p->shift_background(0);
982 p->sampling(part->pixel_size, part->pixel_size, 1);
983 if ( mg->ctf ) img_ctf_apply(p, *(mg->ctf), 1, 0.2, 0, hires, planf, planb);
984 translate = prec->image[i].origin() - part->ori;
985 origin = part->ori;
986 euler = Euler(part->view);
987 mat = Matrix3(axis, euler.psi());
988 // mat = Matrix3(axis, part->view.angle());
989 p->transform(scale, origin, translate, mat, FILL_BACKGROUND, 0);
990 n++;
991 f += part->fom[0];
992 prec->add(i, p);
993 delete p;
994 }
995 }
996 }
997 }
998
999 if ( n ) {
1000 f /= n;
1001 prec->multiply(i, 1.0L/n);
1002 }
1003
1004 prec->image[i].FOM(f);
1005 prec->image[i].select(n);
1006
1007 Bparticle* part_avg = new Bparticle;
1008 memset(part_avg, 0, sizeof(Bparticle));
1009 part_avg->id = i+1;
1010 part_avg->mag = 1;
1011
1012 part_avg->ori = prec->image[i].origin();
1013 part_avg->fom[0] = f;
1014 part_avg->sel = n;
1015
1016 return part_avg;
1017 }
1018
1019 Bparticle* img_reconstruct_2D_fspace(long i, Bproject* project, Bimage* prec,
1020 double hires, fft_plan planf, fft_plan planb)
1021 {
1022 long maxrad = ( hires > 0 )? prec->real_size()[0]/hires: prec->sizeX()/2;
1023 if ( maxrad > prec->sizeX()/2 ) maxrad = prec->sizeX()/2;
1024
1025 long j, n(0);
1026 Bfield* field = project->field;
1027 Bmicrograph* mg = field->mg;
1028 Bparticle* part = mg->part;
1029 Bimage* p = NULL;
1030 Bimage* psum = new Bimage(Float, TComplex, prec->size(), 1);
1031 Bimage* pssq = new Bimage(Float, TSimple, prec->size(), 1);
1032 psum->origin(prec->image->origin());
1033 pssq->origin(prec->image->origin());
1034 psum->sampling(prec->sampling());
1035 pssq->sampling(prec->sampling());
1036
1037 double f(0), pwr, t(0.5);
1038 Vector3<double> origin, translate;
1039 Vector3<double> scale(1,1,1);
1040 Vector3<double> axis(0,0,1);
1041 Matrix3 mat(1);
1042 Euler euler;
1043
1044 long nmg = project_count_mg_selected(project), m(0);
1045
1046 // cout << "Map: " << i+1 << endl;
1047
1048 for ( field = project->field; field; field = field->next ) {
1049 for ( mg = field->mg; mg; mg = mg->next ) if ( mg->select ) {
1050 m++;
1051 // if ( mg->ctf ) cout << "CTF pointer: " << mg->ctf << endl << endl << endl;
1052 if ( verbose && i < 1 ) {
1053 cout << mg->id;
1054 if ( mg->ctf ) cout << tab << mg->ctf->defocus_average();
1055 cout << tab << m*100.0/nmg << "%" << endl;
1056 }
1057 for ( part = mg->part; part; part = part->next ) if ( part->sel == i+1 ) {
1058 // cout << "Reading particle " << part->id << endl;
1059 p = particle_read_img(part, 1);
1060 // cout << "Particle read " << p->file_name() << endl;
1061 if ( p ) {
1062 p->change_type(Float);
1063 p->rescale_to_avg_std(0, 1);
1064 p->shift_background(0);
1065 p->sampling(part->pixel_size, part->pixel_size, 1);
1066 if ( mg->ctf )
1067 img_ctf_apply(p, *(mg->ctf), 1, 0.2, 0, hires, planf, planb);
1068 translate = prec->image[i].origin() - part->ori;
1069 origin = part->ori;
1070 euler = Euler(part->view);
1071 mat = Matrix3(axis, euler.psi());
1072 p->transform(scale, origin, translate, mat, FILL_BACKGROUND, 0);
1073 n++;
1074 f += part->fom[0];
1075 p->fft(planf);
1076 psum->add(p);
1077 p->complex_to_intensities();
1078 if ( verbose )
1079 cout << "Particle " << part->id << endl;
1080 pssq->add(p);
1081 // cout << "data size = " << p->data_size() << endl;
1082 delete p;
1083 }
1084 // if ( verbose )
1085 // cout << "Particle " << part->id << " done " << endl;
1086 }
1087 }
1088 }
1089
1090 if ( n ) {
1091 f /= n;
1092 for ( j=0; j<psum->image_size(); ++j ) {
1093 pwr = psum->complex(j).power();
1094 psum->set(j, psum->complex(j)/n);
1095 pssq->set(j, (pwr - (*pssq)[j])/((*pssq)[j] - pwr/n));
1096 }
1097 psum->fft_back(planb);
1098 pssq->origin(Vector3<double>(0,0,0));
1099 Bimage* pr = pssq->radial(0, pssq->sizeX()/2, 1, 1);
1100 if ( verbose ) {
1101 cout << "Radius\tSSNR" << endl;
1102 for ( j=0; j<maxrad; ++j )
1103 cout << j << tab << (*pr)[j] << endl;
1104 cout << endl;
1105 }
1106 for ( j=1; j<maxrad; ++j )
1107 if ( (*pr)[j] < t ) break;
1108 f = prec->real_size()[0]/j;
1109 if ( verbose )
1110 cout << j << tab << f << tab << (*pr)[j] << endl << endl;
1111 delete pr;
1112 prec->replace(i, psum);
1113 prec->image[i].FOM(f);
1114 prec->image[i].select(n);
1115 }
1116
1117 delete psum;
1118 delete pssq;
1119
1120 Bparticle* part_avg = new Bparticle;
1121 memset(part_avg, 0, sizeof(Bparticle));
1122 part_avg->id = i+1;
1123 part_avg->mag = 1;
1124
1125 part_avg->ori = prec->image[i].origin();
1126 part_avg->fom[0] = f;
1127 part_avg->sel = n;
1128
1129 return part_avg;
1130 }
1131
1132 Bimage* project_reconstruct_2D_fast(Bproject* project)
1133 {
1134 long i;
1135
1136 Bfield* field = project->field;
1137 Bmicrograph* mg = field->mg;
1138 Bparticle* part = mg->part;
1139
1140 Bimage* p = particle_read_img(mg->part, 0);
1141
1142 Vector3<long> size(p->size());
1143 double px(part->pixel_size), hires(2*px);
1144
1145 delete p;
1146
1147 // Determine the number of reconstructions to generate
1148 long nmap(0);
1149 for ( field=project->field; field; field=field->next )
1150 for ( mg=field->mg; mg; mg=mg->next )
1151 for ( part=mg->part; part; part=part->next )
1152 if ( part->sel > nmap ) nmap = part->sel;
1153
1154 if ( nmap < 1 ) return NULL;
1155
1156 Bparticle** part_arr = new Bparticle*[nmap];
1157
1158 Bimage* prec = new Bimage(Float, TSimple, size, nmap);
1159 prec->origin(prec->size()/2);
1160 prec->sampling(px, px, 1);
1161
1162 if ( verbose & VERB_RESULT ) {
1163 cout << "2D frequency space averaging:" << endl;
1164 cout << "Size: " << prec->size() << endl;
1165 cout << "Origin: " << prec->image->origin() << endl;
1166 cout << "Sampling: " << prec->sampling() << " A" << endl;
1167 cout << "Resolution limit: " << hires << " A" << endl;
1168 cout << "Number of averages: " << prec->images() << endl << endl;
1169 }
1170
1171 fft_plan planf = fft_setup_plan(size, FFTW_FORWARD, 1);
1172 fft_plan planb = fft_setup_plan(size, FFTW_BACKWARD, 1);
1173
1174 #ifdef HAVE_GCD
1175 dispatch_apply(nmap, dispatch_get_global_queue(0, 0), ^(size_t i){
1176 part_arr[i] = img_reconstruct_2D_fspace(i, project, prec, hires, planf, planb);
1177 if ( verbose )
1178 cout << i+1 << tab << part_arr[i]->sel << tab << part_arr[i]->fom[0] << endl;
1179 });
1180 #else
1181 #pragma omp parallel for
1182 for ( i=0; i<nmap; i++ ) {
1183
1184 part_arr[i] = img_reconstruct_2D_fspace(i, project, prec, hires, planf, planb);
1185 if ( verbose )
1186 cout << i+1 << tab << part_arr[i]->sel << tab << part_arr[i]->fom[0] << endl;
1187 }
1188 #endif
1189
1190 fft_destroy_plan(planf);
1191 fft_destroy_plan(planb);
1192
1193 if ( verbose & VERB_DEBUG )
1194 cout << "done" << endl;
1195
1196 prec->statistics();
1197
1198 for ( i=0; i<nmap-1; i++ ) part_arr[i]->next = part_arr[i+1];
1199 project->class_avg = part_arr[0];
1200 part_arr[i]->next = NULL;
1201
1202 project_show_class_averages(project);
1203 /*
1204 long npart = project_count_mg_particles(project);
1205
1206 if ( verbose & VERB_RESULT ) {
1207 cout << "Particles used in reconstruction:" << endl;
1208 cout << "Map\tNumber\t%\tFOM" << endl;
1209 for ( part = project->class_avg; part; part = part->next ) {
1210 cout << part->id << tab << part->sel << tab <<
1211 part->sel*100.0/npart << tab <<
1212 part->fom[0] << endl;
1213 }
1214 cout << endl;
1215 }
1216 */
1217 return prec;
1218 }
1219
1220
1235 Bimage* project_reconstruct_3D(Bproject* project, long selnum, int calcfom, Vector3<long> size)
1236 {
1237 int n(0), img_num;
1238 Breconstruction* rec = project->rec;
1239 Bparticle* part;
1240 Bimage* p = NULL;
1241 Bimage* pmap = NULL;;
1242
1243 if ( rec->part ) {
1244 if ( rec->part->fpart.length() ) p = read_img(rec->part->fpart, 0, 0);
1245 else if ( rec->fpart.length() ) p = read_img(rec->fpart, 0, 0);
1246 else pmap = read_img(rec->frec, 1, 0);
1247 } else p = read_img(rec->frec, 0, 0);
1248
1249 if ( !p && !pmap ) {
1250 error_show("project_reconstruct_3D", __FILE__, __LINE__);
1251 return NULL;
1252 }
1253
1254 if ( p ) {
1255 size = {p->sizeX(), p->sizeY(), p->sizeZ()};
1256 delete p;
1257 }
1258
1259 if ( size.volume() <= 0 ) {
1260 cerr << "Error: The particle box size must be specified!" << endl << endl;
1261 return NULL;
1262 }
1263
1264 Bimage* prec = new Bimage(Float, TSimple, size, 1);
1265 prec->sampling(rec->voxel_size, rec->voxel_size, rec->voxel_size);
1266 prec->origin(prec->default_origin());
1267 float* fom = NULL;
1268 if ( calcfom ) {
1269 prec->next = new Bimage(Float, TSimple, size, 1);
1270 fom = (float *) prec->next->data_pointer();
1271 }
1272
1273 long i;
1274 Bstring filename;
1275 Vector3<double> start;
1276 double std_sum(0);
1277
1278 if ( verbose ) {
1279 cout << "Calculating an average reconstruction" << endl;
1280 cout << "Size: " << size << endl;
1281 }
1282
1283 if ( rec->part ) {
1284 for ( rec = project->rec; rec; rec = rec->next ) {
1285 filename = rec->fpart;
1286 for ( part = rec->part; part; part = part->next )
1287 if ( ( selnum < 0 && part->sel ) || ( part->sel == selnum ) ) {
1288 img_num = part->id - 1;
1289 if ( part->fpart.length() ) {
1290 filename = part->fpart;
1291 img_num = 0;
1292 }
1293 if ( filename.length() ) {
1294 if ( ( p = read_img(filename, 1, img_num) ) == NULL ) {
1295 error_show("project_reconstruct_3D", __FILE__, __LINE__);
1296 return NULL;
1297 }
1298 if ( verbose )
1299 cout << "Adding particle: " << part->id << " (" << filename << ":" << img_num << ")" << endl;
1300 } else {
1301 start = part->loc - part->ori;
1302 p = pmap->extract(0, start, size);
1303 if ( verbose )
1304 cout << "Adding particle: " << part->id << endl;
1305 }
1306 // p->image->origin(part->ori);
1307 p->origin(part->ori);
1308 p->calculate_background();
1309 std_sum += p->standard_deviation();
1310 prec->rotate_and_add(p, part->ori, part->view);
1311 delete p;
1312 n++;
1313 }
1314 }
1315 } else {
1316 for ( rec = project->rec; rec; rec = rec->next )
1317 if ( ( selnum < 0 && rec->select ) || ( rec->select == selnum ) ) {
1318 if ( verbose )
1319 cout << "Adding reconstruction: " << rec->frec << endl;
1320 if ( ( p = read_img(rec->frec, 1, 0) ) == NULL ) {
1321 error_show("project_reconstruct_3D", __FILE__, __LINE__);
1322 return NULL;
1323 }
1324 // p->image->origin(rec->origin);
1325 p->origin(rec->origin);
1326 p->calculate_background();
1327 std_sum += p->standard_deviation();
1328 prec->rotate_and_add(p, rec->origin, rec->view);
1329 delete p;
1330 n++;
1331 }
1332 }
1333
1334 if ( pmap ) delete pmap;
1335
1336 if ( verbose )
1337 cout << "Number of particles: " << n << endl;
1338
1339 if ( n ) {
1340 for ( i=0; i<prec->data_size(); i++ ) {
1341 prec->set(i, (*prec)[i] / n);
1342 if ( fom ) {
1343 fom[i] = fom[i]/n - (*prec)[i]*(*prec)[i];
1344 if ( fom[i] < 0 ) fom[i] = 0;
1345 if ( calcfom > 1 ) fom[i] = sqrt(fom[i]);
1346 }
1347 }
1348 std_sum /= n;
1349 }
1350
1351 prec->statistics();
1352 prec->calculate_background();
1353
1354 if ( verbose )
1355 cout << "Signal enhancement: " <<
1356 (sqrt(n)*prec->standard_deviation()/std_sum - 1)/(sqrt(n) - 1) << endl << endl;
1357
1358 if ( verbose & VERB_DEBUG )
1359 cout << "DEBUG project_reconstruct_3D: done!" << endl;
1360
1361 return prec;
1362 }
1363
1378 Bimage* project_reconstruct_3D(Bproject* project, long selnum, Vector3<long> size, double resolution)
1379 {
1380 long n(0), img_num;
1381 Breconstruction* rec = project->rec;
1382 Bparticle* part;
1383 Bimage* p = NULL;
1384 Bimage* pmap = NULL;;
1385
1386 if ( rec->part ) {
1387 if ( rec->part->fpart.length() ) p = read_img(rec->part->fpart, 0, 0);
1388 else if ( rec->fpart.length() ) p = read_img(rec->fpart, 0, 0);
1389 else pmap = read_img(rec->frec, 1, 0);
1390 } else p = read_img(rec->frec, 0, 0);
1391
1392 if ( !p && !pmap ) {
1393 error_show("project_reconstruct_3D", __FILE__, __LINE__);
1394 return NULL;
1395 }
1396
1397 if ( p ) {
1398 size = {p->sizeX(), p->sizeY(), p->sizeZ()};
1399 delete p;
1400 }
1401
1402 if ( size.volume() <= 0 ) {
1403 cerr << "Error: The particle box size must be specified!" << endl << endl;
1404 return NULL;
1405 }
1406
1407 Bimage* prec = new Bimage(Float, TComplex, size, 1);
1408 prec->fourier_type(Standard);
1409 prec->sampling(rec->voxel_size, rec->voxel_size, rec->voxel_size);
1410 prec->origin(prec->default_origin());
1411 prec->next = new Bimage(Float, TSimple, size, 1);
1412
1413 double threshold;
1414 Bstring filename;
1415 Vector3<double> start;
1416
1417 if ( verbose ) {
1418 cout << "Calculating an average reconstruction" << endl;
1419 cout << "Size: " << size << endl;
1420 cout << "Resolution: " << resolution << endl;
1421 }
1422
1423 if ( rec->part ) {
1424 for ( rec = project->rec; rec; rec = rec->next ) {
1425 filename = rec->fpart;
1426 for ( part = rec->part; part; part = part->next )
1427 if ( ( selnum < 0 && part->sel ) || ( part->sel == selnum ) ) {
1428 img_num = part->id - 1;
1429 if ( part->fpart.length() ) {
1430 filename = part->fpart;
1431 img_num = 0;
1432 }
1433 if ( filename.length() ) {
1434 if ( ( p = read_img(filename, 1, img_num) ) == NULL ) {
1435 error_show("project_reconstruct_3D", __FILE__, __LINE__);
1436 return NULL;
1437 }
1438 if ( verbose )
1439 cout << "Adding particle: " << part->id << " (" << filename << ":" << img_num << ")" << endl;
1440 } else {
1441 start = part->loc - part->ori;
1442 p = pmap->extract(0, start, size);
1443 if ( verbose )
1444 cout << "Adding particle: " << part->id << endl;
1445 }
1446 threshold = p->standard_deviation()/1000;
1447 p->origin(part->ori);
1448 p->calculate_background();
1449 p->rotate(prec->image->origin() - part->ori, part->view);
1450 p->origin(prec->image->origin());
1451 p->fft();
1452 p->phase_shift_to_origin();
1453 // prec->add(p);
1454 prec->fspace_pack_3D(p, resolution, threshold);
1455 delete p;
1456 n++;
1457 }
1458 }
1459 } else {
1460 for ( rec = project->rec; rec; rec = rec->next )
1461 if ( ( selnum < 0 && rec->select ) || ( rec->select == selnum ) ) {
1462 if ( verbose )
1463 cout << "Adding reconstruction: " << rec->frec << endl;
1464 if ( ( p = read_img(rec->frec, 1, 0) ) == NULL ) {
1465 error_show("project_reconstruct_3D", __FILE__, __LINE__);
1466 return NULL;
1467 }
1468 threshold = p->standard_deviation()/1000;
1469 p->origin(rec->origin);
1470 p->calculate_background();
1471 p->rotate(prec->image->origin() - rec->origin, rec->view);
1472 p->fft();
1473 p->phase_shift_to_origin();
1474 // prec->add(p);
1475 prec->fspace_pack_3D(p, resolution, threshold);
1476 delete p;
1477 n++;
1478 }
1479 }
1480
1481 if ( pmap ) delete pmap;
1482
1483 if ( verbose ) {
1484 cout << "Number of particles: " << n << endl;
1485 cout << "Rescaling average" << endl << endl;
1486 }
1487
1488 prec->fspace_reconstruction_weigh();
1489
1490 prec->fspace_reconstruction_stats(resolution);
1491
1492 prec->phase_shift_to_center();
1493 prec->origin(prec->default_origin());
1494
1495 prec->fft_back();
1496
1497 prec->statistics();
1498 prec->calculate_background();
1499
1500 if ( verbose & VERB_DEBUG )
1501 cout << "DEBUG project_reconstruct_3D: done!" << endl;
1502
1503 return prec;
1504 }
1505
1527 Bimage* project_back_projection(Bproject* project, long num_select,
1528 Vector3<long> map_size, Vector3<double> sam, double scale,
1529 double resolution, fft_plan planf, fft_plan planb)
1530 {
1531 Bfield* field = NULL;
1532 Bmicrograph* mg = NULL;
1533 Bparticle* part = NULL;
1534 Bimage* p = NULL;
1535
1536 if ( map_size.volume() <= 0 ) {
1537 error_show("Error in project_back_projection", __FILE__, __LINE__);
1538 cerr << "No reconstruction size set!" << endl << endl;
1539 return NULL;
1540 }
1541
1542 for ( field = project->field; field && part == NULL; field = field->next )
1543 for ( mg = field->mg; mg && part == NULL; mg = mg->next )
1544 if ( ( part = mg->part ) ) break;
1545
1546 if ( !mg || !part ) {
1547 cerr << "Error: No particles found!" << endl;
1548 return NULL;
1549 }
1550
1551 // Initialize the new 3D volume
1552 Bimage* pmap = new Bimage(Float, TSimple, map_size, 1);
1553
1554 if ( sam.volume() > 0 ) pmap->sampling(sam);
1555 else if ( mg ) pmap->sampling(part->pixel_size/scale, part->pixel_size/scale, part->pixel_size/scale);
1556
1557 pmap->origin(pmap->default_origin());
1558
1559 pmap->check();
1560
1561 long nsel = project_count_mg_part_selected(project, num_select);
1562 long psel, nrec(0);
1563
1564 if ( verbose & VERB_FULL ) {
1565 cout << "3D backprojection:" << endl;
1566 cout << "Map size: " << pmap->size() << endl;
1567 cout << "Resolution: " << resolution << " A" << endl;
1568 cout << "Scale: " << scale << endl;
1569 cout << "Sampling: " << pmap->sampling() << endl;
1570 cout << "Number of selected particles: " << nsel << endl << endl;
1571 }
1572
1573 // Do the back projection
1574 for ( field = project->field; field; field = field->next ) {
1575 for ( mg = field->mg; mg; mg = mg->next ) {
1576 for ( part = mg->part; part; part = part->next ) {
1577 psel = 0;
1578 if ( part->sel ) {
1579 if ( num_select < 0 ) {
1580 psel = 1;
1581 } else if ( part->sel == num_select ) {
1582 psel = 1;
1583 }
1584 }
1585 if ( psel ) { // Use only selected images
1586 p = particle_read_img(part, 1);
1587 // if ( ( p = read_img(mg->fpart, 1, part->id-1) ) == NULL ) {
1588 if ( !p ) {
1589 error_show("project_back_projection", __FILE__, __LINE__);
1590 return NULL;
1591 }
1592
1593 p->sampling(part->pixel_size, part->pixel_size, 1);
1594
1595 if ( part->ori[0] <= 0 ) {
1596 if ( p->image->origin()[0] > 0 ) part->ori[0] = p->image->origin()[0];
1597 else part->ori[0] = pmap->image->origin()[0];
1598 }
1599
1600 if ( part->ori[1] <= 0 ) {
1601 if ( p->image->origin()[1] > 0 ) part->ori[1] = p->image->origin()[1];
1602 else part->ori[1] = pmap->image->origin()[1];
1603 }
1604
1605 part->ori[2] = 0;
1606
1607 p->origin(part->ori);
1608
1609 p->image->view(part->view);
1610
1611 p->image->magnification(part->mag / scale);
1612
1613 pmap->back_project(p, resolution, 0, planf, planb);
1614
1615 delete p;
1616
1617 nrec++;
1618
1619 if ( verbose & ( VERB_TIME | VERB_PROCESS | VERB_RESULT ) )
1620 cout << "Complete: " << nrec*100.0/nsel << "%\r" << flush;
1621 }
1622 }
1623 }
1624 }
1625
1626 if ( verbose ) {
1627 cout << endl << "Particles used: " << nrec << endl << endl;
1628 }
1629
1630 return pmap;
1631 }
1632
1642 Bimage* img_backprojection_accumulate(Bimage** pacc, int imap,
1643 int nmaps, int nthreads)
1644 {
1645 if ( verbose & VERB_DEBUG )
1646 cout << "DEBUG img_backprojection_accumulate:" << endl;
1647
1648 int maps_per_class = nthreads;
1649 int iclass = imap/nmaps;
1650
1651 Bimage* prec = pacc[0]->copy_header();
1652 prec->data_alloc();
1653
1654 long i, j, k;
1655 long datasize = (long) prec->size().volume();
1656
1657 long st(0), inc(1);
1658 if ( nmaps == 2 ) {
1659 st = imap%2;
1660 inc = 2;
1661 }
1662 if ( nmaps == 3 && imap%3 ) {
1663 st = imap%3 - 1;
1664 inc = 2;
1665 }
1666
1667 if ( verbose & VERB_DEBUG ) {
1668 cout << "DEBUG img_backprojection_weigh: nmaps=" << nmaps << " imap=" << imap << endl;
1669 cout << "DEBUG img_backprojection_weigh: maps_per_class=" << maps_per_class << " iclass=" << iclass << endl;
1670 cout << "DEBUG img_backprojection_weigh: st=" << st << " inc=" << inc << endl;
1671 }
1672
1673 for ( i=iclass*maps_per_class+st, j=st; j<maps_per_class; i+=inc, j+=inc ) {
1674 // cout << "Doing map " << i << endl;
1675 for ( k=0; k<datasize; k++ )
1676 prec->add(k, (*pacc[i])[k]);
1677 }
1678
1679 prec->statistics();
1680 prec->calculate_background();
1681
1682 if ( verbose & VERB_DEBUG )
1683 cout << "DEBUG img_backprojection_weigh: Accumulation done" << endl;
1684
1685 return prec;
1686 }
1687
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bparticle::id
int id
Definition: mg_processing.h:92
rwmg.h
Header file for reading and writing micrograph parameters.
Bimage::fspace_reconstruction_stats
int fspace_reconstruction_stats(double resolution)
Calculates Fourier shell statistics.
Definition: Bimage_reconstruct.cpp:451
Bimage::replace
int replace(Bimage *img)
Replaces the data with that from the given image.
Definition: Bimage.cpp:2828
Bparticle::pixel_size
double pixel_size
Definition: mg_processing.h:98
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:37
Bimage::copy_header
Bimage * copy_header()
Definition: Bimage.h:650
Bproject::rec
Breconstruction * rec
Definition: mg_processing.h:344
Bparticle::mag
double mag
Definition: mg_processing.h:94
FILL_BACKGROUND
#define FILL_BACKGROUND
Definition: utilities.h:174
Bsub_image::view
void view(double x, double y, double z, double a)
Definition: Bimage.h:143
random_seed
long random_seed()
Gets a random seed and sets the flag.
Definition: random_numbers.cpp:41
Euler
Definition: Euler.h:28
Bparticle::view
View view
Definition: mg_processing.h:101
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
project_set_reconstruction_size
Vector3< long > project_set_reconstruction_size(Bproject *project, double scale, int twoD_flag)
Sets the reconstruction size for reconstruction from 2D particle images.
Definition: mg_reconstruct.cpp:628
Breconstruction::part
Bparticle * part
Definition: mg_processing.h:304
planb
fft_plan planb
Definition: bico.cpp:24
project_reconstruct_3D
Bimage * project_reconstruct_3D(Bproject *project, long selnum, int calcfom, Vector3< long > size)
Transforms 3D maps and calculates an average.
Definition: mg_reconstruct.cpp:1235
Bimage::add
void add(long j, double v)
Definition: Bimage.h:308
Breconstruction::fpart
Bstring fpart
Definition: mg_processing.h:288
verbose
int verbose
mg_particle_select.h
Select particles.
Bmicrograph::id
Bstring id
Definition: mg_processing.h:202
project_configure_for_reconstruction
int project_configure_for_reconstruction(Bproject *project, Bstring classes, long &nmaps, long &nthreads)
Sets up the particle selection for reconstruction.
Definition: mg_reconstruct.cpp:693
Bimage::image_size
long image_size()
Definition: Bimage.h:267
symmetry.h
Header file for general symmetry functions.
Bimage::fft
int fft()
Definition: Bimage.h:822
Bimage::fft_back
int fft_back()
Definition: Bimage.h:823
utilities.h
Header file for general utilities.
particle_copy
Bparticle * particle_copy(Bparticle **partlist, Bparticle *part)
Adds one particle onto a list of particle parameters.
Definition: mg_processing.cpp:1409
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
Breconstruction
Definition: mg_processing.h:280
planf
fft_plan planf
Definition: bico.cpp:24
img_reconstruct_2D_fspace
Bparticle * img_reconstruct_2D_fspace(long i, Bproject *project, Bimage *prec, double hires, fft_plan planf, fft_plan planb)
Definition: mg_reconstruct.cpp:1019
mg_img_proc.h
Header file for image processing from micrograph structures.
project_reconstruction_partlist
Bparticle * project_reconstruction_partlist(Bproject *project, int num_select, int bootstrap)
List of particle images for reciprocal space reconstruction.
Definition: mg_reconstruct.cpp:236
part_single_reconstruction
double part_single_reconstruction(Bparticle *part, Vector3< long > size, Bimage *pmask, Bsymmetry *sym, double hi_res, double scale, int ft_size, fft_plan img_plan, fft_plan map_plan, double part_weight, int interp_type, CTFparam *mg_ctf, int ctf_action, double wiener, int flags)
Definition: mg_reconstruct.cpp:404
CTFparam::update
int update(CTFparam *ctf)
Definition: ctf.h:77
project_count_mg_part_selected
long project_count_mg_part_selected(Bproject *project)
Counts the number of particles in a project.
Definition: mg_processing.cpp:833
Bparticle::fom
double fom[NFOM]
Definition: mg_processing.h:102
Complex.h
Class for complex numbers.
WRITE_PPX
#define WRITE_PPX
Definition: mg_processing.h:26
Matrix3
Definition: Matrix3.h:17
Bstring::length
long length() const
Definition: Bstring.cpp:263
project
Bproject * project
Definition: bshow.cpp:31
project_count_mg_particles
long project_count_mg_particles(Bproject *project)
Counts all the particles in the project structure.
Definition: mg_processing.cpp:811
particle_count
long particle_count(Bparticle *part)
Counts the number of particles in a linked list.
Definition: mg_processing.cpp:1151
Bimage::complex
Complex< double > complex(long j)
Returns a complex value at the given index.
Definition: Bimage.cpp:1005
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bimage::check
void check()
Checks an image for reasonable properties.
Definition: Bimage.cpp:389
Bimage::file_name
void file_name(string s)
Definition: Bimage.h:230
Bimage::multiply
void multiply(long j, Complex< double > cv)
Definition: Bimage.h:312
mg_ctf.h
Functions for CTF (contrast transfer function) processing.
TComplex
Definition: Bimage.h:59
Bimage::shift_background
int shift_background(double bkg)
Sets the background for each sub-image to a given value.
Definition: Bimage_background.cpp:351
read_img
Bimage * read_img(char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:76
Breconstruction::origin
Vector3< double > origin
Definition: mg_processing.h:293
ppx_filename
Bstring ppx_filename(Bstring &mg_id, int part_id)
Definition: rwmg.cpp:412
Bfield::next
Bfield * next
Definition: mg_processing.h:258
particle_read_img
Bimage * particle_read_img(Bparticle *part, int readflag)
Reads a particle image file.
Definition: mg_img_proc.cpp:463
Bmicrograph::part
Bparticle * part
Definition: mg_processing.h:239
TSimple
Definition: Bimage.h:58
Float
Definition: utilities.h:157
FOM_CV
Definition: mg_processing.h:42
Vector3::max
Type max()
Definition: Vector3.h:175
Bimage
General image parameter class.
Definition: Bimage.h:163
Bmicrograph::fpart
Bstring fpart
Definition: mg_processing.h:207
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:487
Bimage::data_alloc
unsigned char * data_alloc()
Definition: Bimage.h:256
Bimage::fspace_pack_3D
int fspace_pack_3D(Bimage *p, double hi_res=0, double threshold=0)
Packs a 3D Fourier transform into a 3D reciprocal space volume.
Definition: Bimage_reconstruct.cpp:309
Bparticle::sel
long sel
Definition: mg_processing.h:103
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
Bfield
Definition: mg_processing.h:257
M_PI
#define M_PI
Definition: utilities.h:59
Bimage::fspace_pack_2D
int fspace_pack_2D(Bimage *p, Matrix3 mat, double hi_res=0, double lo_res=0, double scale=1, double part_weight=1, int interp_type=0)
Packs a 2D Fourier transform into a 3D reciprocal space volume.
Definition: Bimage_reconstruct.cpp:109
Bmicrograph::ctf
CTFparam * ctf
Definition: mg_processing.h:238
Bimage::extract
Bimage * extract(long nn)
Extracts one sub-image into new image structure.
Definition: Bimage_extract.cpp:21
Bparticle::mg
Bmicrograph * mg
Definition: mg_processing.h:104
Euler::psi
double psi()
Definition: Euler.h:56
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:382
select_numbers
int select_numbers(Bstring &string, int n, int *numsel)
Converts a string with a selection specification into an integer array.
Definition: utilities.cpp:328
NFOM
#define NFOM
Definition: mg_processing.h:16
Bimage::statistics
long statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
ppx_check
int ppx_check(Bparticle *part, FOMType fom_tag[NFOM])
Definition: rwmg.cpp:418
Bimage::rotate_and_add
int rotate_and_add(Bimage *p, Vector3< double > origin, View view)
Rotates an image to a specified view and adds it to another image.
Definition: Bimage_transform.cpp:510
Bmicrograph::select
long select
Definition: mg_processing.h:203
write_particle
int write_particle(Bstring &filename, Bparticle *part, int euler_flag, int omega_flag, FOMType fom_tag[NFOM])
Definition: rwmg.cpp:403
project_reconstruct_2D
Bimage * project_reconstruct_2D(Bproject *project, int transform_output)
Creates a 2D reconstruction from the images in a multi-image file.
Definition: mg_reconstruct.cpp:822
Bproject::field
Bfield * field
Definition: mg_processing.h:343
VERB_TIME
#define VERB_TIME
Definition: utilities.h:110
part_consolidate_selection
long part_consolidate_selection(Bproject *project, int number)
Consolidates selected particles under one selection number.
Definition: mg_particle_select.cpp:284
fft_plan
fftwf_plan fft_plan
Definition: fft.h:16
Standard
Definition: Bimage.h:41
Bsub_image::FOM
double FOM()
Definition: Bimage.h:151
img_ctf_apply
int img_ctf_apply(Bimage *p, CTFparam em_ctf, int action, double wiener, double lores, double hires)
Applies or corrects for the contrast transfer function (CTF).
Definition: mg_ctf.cpp:238
Bimage::rescale_to_avg_std
int rescale_to_avg_std(double nuavg, double nustd)
Rescales the image data to a given average and standard deviation.
Definition: Bimage_rescale.cpp:163
img_backprojection_accumulate
Bimage * img_backprojection_accumulate(Bimage **pacc, int imap, int nmaps, int nthreads)
Accumulates multiple backprojections.
Definition: mg_reconstruct.cpp:1642
Bimage::phase_shift_to_origin
int phase_shift_to_origin()
Phase shifts a set of reflections to the image origin.
Definition: Bimage_complex.cpp:327
Bimage::fspace_reconstruction_snr
long fspace_reconstruction_snr()
Calculates the SNR map.
Definition: Bimage_reconstruct.cpp:529
Bmicrograph
Definition: mg_processing.h:200
Bimage::complex_to_intensities
void complex_to_intensities()
The intensities from a complex image is written to a simple image.
Definition: Bimage_complex.cpp:92
write_img
int write_img(const char *filename, Bimage *p, int compression)
General driver function to write multiple image formats.
Definition: rwimg.cpp:280
Bproject::class_avg
Bparticle * class_avg
Definition: mg_processing.h:345
Bimage::size
Vector3< long > size() const
Definition: Bimage.h:373
Bimage::calculate_background
int calculate_background(long nn, int flag)
Calculates the background for one sub-image.
Definition: Bimage_background.cpp:27
Bparticle::fpart
Bstring fpart
Definition: mg_processing.h:91
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:127
random_symmetric_view
View random_symmetric_view(View &asu_view, Bsymmetry *sym)
Returns a randomly picked symmetry view.
Definition: symmetry.cpp:1011
Bparticle::ori
Vector3< double > ori
Definition: mg_processing.h:100
mg_ctf
int mg_ctf(Bmicrograph *mg, Bimage *pmg, int action, double lores, double hires, double wiener, Vector3< long > tile_size, DataType datatype, Bstring &newname, Bstring &label, int flags)
Definition: mg_ctf.cpp:971
part_reset_selection
long part_reset_selection(Bproject *project)
Resets selection to all particles.
Definition: mg_particle_select.cpp:131
Bimage::fspace_reconstruction_weigh
long fspace_reconstruction_weigh()
Weighs a reconstruction.
Definition: Bimage_reconstruct.cpp:412
micrograph_count_particles
long micrograph_count_particles(Bmicrograph *mg)
Counts all the particles in the micrograph structure.
Definition: mg_processing.cpp:1132
Bimage::standard_deviation
double standard_deviation()
Definition: Bimage.h:537
Bimage::view
void view(double vx, double vy, double vz, double va)
Definition: Bimage.h:589
Bfield::mg
Bmicrograph * mg
Definition: mg_processing.h:264
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
FOM
Definition: mg_processing.h:40
project_count_mg_selected
long project_count_mg_selected(Bproject *project)
Counts all the selected micrographs in the project structure.
Definition: mg_processing.cpp:763
Bimage::relative_density
double relative_density(Bimage *pmask)
Calculates the relative density in a region defined by a mask.
Definition: Bimage.cpp:3069
Bimage::next
Bimage * next
Definition: Bimage.h:165
VERB_RESULT
#define VERB_RESULT
Definition: utilities.h:105
Bimage::complex_to_real
void complex_to_real()
The real part of a complex image is written to a simple image.
Definition: Bimage_complex.cpp:50
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:261
Bparticle
Definition: mg_processing.h:89
Bstring
Definition: Bstring.h:29
Bimage::pad
int pad(long sz, int fill_type=0, double fill=0)
Pads an image to a new size with a given fill value.
Definition: Bimage_resize.cpp:351
Bimage::sizeX
void sizeX(long nx)
Definition: Bimage.h:377
View::matrix
Matrix3 matrix()
Definition: View.h:150
img_reconstruct_2D
Bparticle * img_reconstruct_2D(long i, Bproject *project, Bimage *prec, double hires, fft_plan planf, fft_plan planb)
Definition: mg_reconstruct.cpp:955
project_single_particle_reconstruction
long project_single_particle_reconstruction(Bproject *project, Bstring &maskfile, Bsymmetry *sym, int num_select, double hi_res, double scale, Vector3< long > size, int pad_factor, int interp_type, int ctf_action, double wiener, int flags)
Reciprocal space reconstruction from the images in a multi-image file.
Definition: mg_reconstruct.cpp:489
Bimage::default_origin
Vector3< double > default_origin()
Definition: Bimage.h:585
Bproject::select
int select
Definition: mg_processing.h:339
FOMType
FOMType
Definition: mg_processing.h:38
Breconstruction::select
long select
Definition: mg_processing.h:283
Bimage::sizeZ
void sizeZ(long nz)
Definition: Bimage.h:379
Vector3< long >
Bparticle::loc
Vector3< double > loc
Definition: mg_processing.h:99
fft_destroy_plan
int fft_destroy_plan(fft_plan plan)
Deallocates a plan for fast Fourier transforms.
Definition: fft.cpp:87
Bstring::lower
Bstring lower()
Definition: Bstring.cpp:308
View
Definition: View.h:26
Bsub_image::magnification
double magnification()
Definition: Bimage.h:149
Bimage::rotate
int rotate()
Rotates an image using parameters defined in the image in place.
Definition: Bimage_transform.cpp:253
fft_setup_plan
fft_plan fft_setup_plan(long x, long y, long z, fft_direction dir, int opt)
Sets up a plan for fast Fourier transforms.
Definition: fft.cpp:31
Bimage::friedel_check
double friedel_check()
Checks Friedel symmetry.
Definition: Bimage_fspace.cpp:1649
CTFparam::defocus_average
double defocus_average()
Definition: ctf.h:100
Bparticle::def
double def
Definition: mg_processing.h:95
mg_processing.h
Header file for micrograph processing.
Breconstruction::frec
Bstring frec
Definition: mg_processing.h:287
Breconstruction::voxel_size
double voxel_size
Definition: mg_processing.h:292
rwimg.h
Header file for 2D and 3D image I/O.
project_back_projection
Bimage * project_back_projection(Bproject *project, long num_select, Vector3< long > map_size, Vector3< double > sam, double scale, double resolution, fft_plan planf, fft_plan planb)
Back projects a set of 2D images into a 3D volume.
Definition: mg_reconstruct.cpp:1527
Bimage::images
long images()
Definition: Bimage.h:491
Bstring::pre_rev
Bstring pre_rev(char c)
Definition: Bstring.cpp:413
mg_reconstruct.h
Functions for reconstruction.
findNextPowerOf
int findNextPowerOf(int startNumber, int powerOf)
Finds the next greatest number that is a power of a given number.
Definition: utilities.cpp:433
img_reconstruction_sum_weigh
Bimage * img_reconstruction_sum_weigh(Bimage **pacc, int imap, int nmaps, int maps_per_class, double hi_res)
Combines and weighs a map from several partial maps and weight sets.
Definition: mg_reconstruct.cpp:315
Vector3::volume
double volume()
Definition: Vector3.h:235
Bparticle::next
Bparticle * next
Definition: mg_processing.h:90
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::sizeY
void sizeY(long ny)
Definition: Bimage.h:378
Bsub_image::select
long select()
Definition: Bimage.h:153
project_show_class_averages
long project_show_class_averages(Bproject *project)
Shows the class averages in a project.
Definition: mg_processing.cpp:2645
Breconstruction::view
View view
Definition: mg_processing.h:295
Breconstruction::next
Breconstruction * next
Definition: mg_processing.h:281
Bimage::data_size
long data_size()
Definition: Bimage.h:255
Bimage::fourier_type
FourierType fourier_type()
Definition: Bimage.h:367
error_show
int error_show(string message, string file, int line)
Displays the error with file and line reference.
Definition: utilities.cpp:755
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
particle_reconstruct
Bimage * particle_reconstruct(Bparticle *partlist, Bsymmetry *sym, int sym_mode, double hi_res, double scale, Vector3< long > size, int ft_size, fft_plan plan, int interp_type, int ctf_action, double wiener, int twoD_flag, int bootstrap, int first)
Reciprocal space reconstruction from 2D particle images.
Definition: mg_reconstruct.cpp:99
Bproject
Definition: mg_processing.h:333
project_reconstruct_2D_fast
Bimage * project_reconstruct_2D_fast(Bproject *project)
Definition: mg_reconstruct.cpp:1132
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:563
CTFparam
Definition: ctf.h:26
Bimage::back_project
int back_project(Bimage *p, double resolution, double axis, fft_plan planf, fft_plan planb)
Definition: Bimage_project.cpp:437
Bmicrograph::next
Bmicrograph * next
Definition: mg_processing.h:201