| Bsoft 2.0.5 Bernard's software package

mg_tomo_rec.cpp
Go to the documentation of this file.
1
9 #include "mg_tomo_rec.h"
10 #include "mg_reconstruct.h"
11 #include "mg_tomography.h"
12 #include "mg_ctf.h"
13 #include "Complex.h"
14 #include "linked_list.h"
15 #include "utilities.h"
16 #include "timer.h"
17
18 #include <fstream>
19
20 #include <sys/stat.h>
21
22 // Declaration of global variables
23 extern int verbose; // Level of output to the screen
24
25 // Internal function prototypes
26 int img_backtransform_z_lines(fstream* ftemp, Bimage* p);
27 int img_write_data_block_with_type(fstream* ftemp, Bimage* p,
28 double avg, double std, double cutmin, double cutmax);
29
30 Bimage* mg_tomo_rec_prepare(Bmicrograph* mg, int ft_size, long thickness,
31 double edge_width, double marker_radius,
32 int fill_type, double fill,
33 int action, double wiener, Vector3<long> tile_size, fft_plan plan)
34 {
35 if ( verbose & VERB_PROCESS )
36 cout << "Reading image " << mg->img_num << " (micrograph " << mg->id << ")" << endl;
37
38 Bimage* p = mg_erase_markers(mg, marker_radius);
39
40 if ( !p ) {
41 error_show("mg_tomo_rec_prepare", __FILE__, __LINE__);
42 return NULL;
43 }
44
45 p->statistics();
46 p->rescale_to_avg_std(0,1);
47
48 // Vector3<long> tile_size(128,128,1);
49 // Vector3<long> tile_size(64,64,1);
50 if ( action ) {
51 if ( verbose & VERB_PROCESS )
52 cout << "Correcting for the CTF" << endl;
53 if ( !mg->ctf ) {
54 cerr << "Error: The CTF parameters are not specified! Abort!" << endl;
55 bexit(-1);
56 }
57 img_ttf_apply(p, *(mg->ctf), action, wiener,
58 tile_size, mg->tilt_angle, mg->tilt_axis, 0, 0);
59 }
60
61 if ( edge_width )
62 micrograph_clear_extraneous_areas(mg, p, thickness, edge_width);
63
64 // p->calculate_background();
65 // p->statistics();
66 // p->rescale_to_avg_std(0,1);
67
68 // p->pad(ft_size, fill_type, fill);
69 p->pad(ft_size);
70
71 p->fft(plan, 1);
72
73 p->phase_shift_to_origin();
74
75 return p;
76 }
77
78
113 Bimage* project_tomo_reconstruct(Bproject* project, double hi_res,
114 double scale, Vector3<long> size, int interp_type, int pad_factor,
115 double edge_width, double marker_radius,
116 int fill_type, double fill, int action, double wiener)
117 {
118 double ti = timer_start();
119
120 int nmg = project_count_mg_selected(project);
121 Bfield* field;
122 Bmicrograph* mg = NULL;
123
124 if ( nmg < 1 ) {
125 cerr << "Error: No micrographs selected!" << endl;
126 return NULL;
127 }
128
129 for ( field = project->field; field; field = field->next ) {
130 for ( mg = field->mg; mg; mg = mg->next ) if ( mg->select )
131 if ( mg->fmg.length() ) break;
132 if ( mg ) break;
133 }
134
135 if ( !mg ) {
136 cerr << "No selected micrograph found!" << endl << endl;
137 return NULL;
138 }
139
140 if ( !mg->fmg.length() ) {
141 cerr << "No file name for micrograph " << mg->id << endl << endl;
142 return NULL;
143 }
144
145 Bimage* p = read_img(mg->fmg, 0, mg->img_num);
146
147 if ( size.volume() < 1 )
148 size = Vector3<long>(p->sizeX()*scale, p->sizeY()*scale, p->sizeX()*scale/10);
149
150 int ft_size = part_ft_size(p->sizeX(), scale, pad_factor);
151 double thickness(size[2]/scale);
152
153 delete p;
154
155 if ( hi_res < 2*mg->pixel_size/scale ) hi_res = 2*mg->pixel_size/scale;
156 double rec_scale = 2*mg->pixel_size/(scale*hi_res);
157 if ( rec_scale > 1 ) rec_scale = 1;
158 double voxel_size(mg->pixel_size/(scale*rec_scale));
159 Vector3<long> rec_size = size*rec_scale;
160 long ds = rec_size.volume();
161
162 long memreq1 = 2*size.volume()*sizeof(float);
163 long memreq2 = (ft_size*ft_size + 5*rec_size.volume())*sizeof(float);
164
165 // if ( verbose & VERB_PROCESS ) {
166 if ( verbose ) {
167 cout << "3D reciprocal space reconstruction:" << endl;
168 cout << "Reconstruction size: " << size << endl;
169 cout << "Scale: " << scale << endl;
170 cout << "Integration size: " << rec_size << endl;
171 cout << "Integration scale: " << rec_scale << endl;
172 cout << "Voxel size: " << voxel_size << " A" << endl;
173 cout << "Resolution: " << hi_res << " A" << endl;
174 cout << "Interpolation type: " << interp_type << endl;
175 cout << "Fourier transform size: " << ft_size << " x " << ft_size << endl;
176 cout << "Padding factor: " << pad_factor << endl;
177 cout << "Edge smooting width: " << edge_width << endl;
178 if ( marker_radius )
179 cout << "Erase markers using radius: " << marker_radius << endl;
180 if ( action )
181 cout << "CTF correction: " << action << " (wiener=" << wiener << ")" << endl;
182 cout << endl;
183 }
184
185 if ( memreq1 > memreq2) memory_check(memreq1);
186 else memory_check(memreq2);
187
188 Vector3<long> tile_size(128,128,1);
189 fft_plan plan = fft_setup_plan(ft_size, ft_size, 1, FFTW_FORWARD, 0);
190
191 // Header structure for the final reconstruction
192 Bimage* prec = new Bimage(Float, TComplex, rec_size, 1);
193 prec->fourier_type(Standard);
194 prec->sampling(voxel_size, voxel_size, voxel_size);
195 prec->next = new Bimage(Float, TSimple, prec->size(), prec->images());
196 prec->next->next = new Bimage(Float, TSimple, prec->size(), prec->images());
197 prec->next->next->next = new Bimage(Float, TSimple, prec->size(), prec->images());
198 float* fom = (float *) prec->next->data_pointer();
199 float* weight = (float *) prec->next->next->data_pointer();
200 // float* weight2 = (float *) prec->next->next->next->data_pointer();
201
202 // double pad_ratio(p->sizeX()*scale/prec->sizeX());
203 double pad_ratio(ft_size*1.0/prec->sizeX());
204 // pad_ratio *= pad_ratio*0.6;
205
206 if ( verbose )
207 cout << "Transforming and packing " << nmg << " micrographs:" << endl;
208
209 for ( field = project->field; field; field = field->next ) {
210 for ( mg = field->mg; mg; mg = mg->next ) if ( mg->select ) {
211 p = mg_tomo_rec_prepare(mg, ft_size, thickness, edge_width,
212 marker_radius, fill_type, fill, action, wiener, tile_size, plan);
213 if ( p ) {
214 if ( verbose )
215 cout << "Packing " << p->file_name() << " (" << mg->img_num << ")" << endl;
216 prec->fspace_pack_2D(p, mg->matrix, hi_res, 0, rec_scale*scale, 1/pad_ratio, interp_type);
217 delete p;
218 }
219 }
220 }
221
222 fft_destroy_plan(plan);
223
224 timer_report(ti);
225
226 if ( verbose )
227 cout << "Weighing reconstruction" << endl;
228
229 #ifdef HAVE_GCD
230 dispatch_apply(ds, dispatch_get_global_queue(0, 0), ^(size_t i){
231 if ( weight[i] > SMALLFLOAT ) {
232 prec->set(i, prec->complex(i) / weight[i]);
233 fom[i] /= weight[i];
234 } else fom[i] = 0;
235 });
236 #else
237 #pragma omp parallel for
238 for ( long i=0; i<ds; i++ ) {
239 if ( weight[i] > SMALLFLOAT ) {
240 prec->set(i, prec->complex(i) / weight[i]);
241 fom[i] /= weight[i];
242 } else fom[i] = 0;
243 }
244 #endif
245
246 long cov(0);
247 for ( long i=0; i<ds; i++ ) if ( weight[i] > SMALLFLOAT ) cov++;
248
249 // prec->fspace_reconstruction_stats(hi_res);
250
251 prec->image->origin(prec->size()/2);
252 prec->phase_shift_to_origin();
253 prec->image->origin(prec->size()/2);
254
255 if ( verbose & VERB_RESULT )
256 cout << "Coverage: " << cov << " (" << cov*100.0/ds << " %)" << endl << endl;
257
258 delete prec->next;
259 prec->next = NULL;
260
261 timer_report(ti);
262
263 return prec;
264 }
265
299 Bimage* project_fourier_reconstruction_slab(Bproject* project, double hi_res,
300 double scale, Vector3<long> size, int slab_start, int slab_end,
301 double marker_radius, int fill_type, double fill, int action, double wiener)
302 {
303 double ti;
304 // if ( verbose & VERB_TIME )
305 ti = timer_start();
306
307 long i;
308
309 Bfield* field = project->field;
310 Bmicrograph* mg = NULL;
311 Bimage* p = NULL;
312
313 long nmg = project_count_mg_selected(project);
314 long nfld = count_list((char *) project->field);
315 long nrec(0);
316
317 if ( nmg < 1 ) {
318 cerr << "Error: No micrographs selected!" << endl;
319 return NULL;
320 }
321
322 for ( field = project->field; field; field = field->next ) {
323 for ( mg = field->mg; mg; mg = mg->next ) if ( mg->select ) {
324 // if ( mg->fft.length() ) break;
325 if ( mg->fmg.length() ) break;
326 }
327 if ( mg ) break;
328 }
329
330 if ( !mg ) {
331 cerr << "No selected micrograph with a micrograph file found!" << endl << endl;
332 return NULL;
333 }
334
335 if ( !mg->fmg.length() ) {
336 cerr << "No file name for micrograph " << mg->id << endl << endl;
337 return NULL;
338 }
339
340 if ( mg->matrix.determinant() < 0.9 )
341 project_mg_tilt_to_matrix(project);
342
343 if ( mg->fmg.length() )
344 p = read_img(mg->fmg, 0, 0);
345 else {
346 error_show("Error in project_fourier_reconstruction_slab ", __FILE__, __LINE__);
347 cerr << "No micrograph image or transform file name given for micrograph " << mg->id << endl << endl;
348 return NULL;
349 }
350
351 if ( size.volume() < 1 )
352 size = {long(p->sizeX()*scale), long(p->sizeY()*scale), long(p->sizeX()*scale/10)};
353
354 /* if ( size.volume() <= 0 ) {
355 size[0] = (int) (p->sizeX()*scale);
356 if ( size[0] < p->sizeY()*scale ) size[0] = (int) (p->sizeY()*scale);
357 if ( size[0] < p->sizeZ()*scale ) size[0] = (int) (p->sizeZ()*scale);
358 size[2] = size[1] = size[0];
359 }
360 */
361 if ( slab_start >= size[2] ) {
362 cerr << "Error: Slab " << slab_start << " - " << slab_end << " is outside the volume limits!" << endl;
363 return NULL;
364 }
365
366 if ( slab_start < 0 ) slab_start = 0;
367 if ( slab_end < 0 || slab_end >= size[2] ) slab_end = size[2] - 1;
368 if ( slab_end < slab_start ) slab_end = slab_start;
369
370 long slab_thickness = slab_end - slab_start + 1;
371
372 int pad = 2;
373 long ft_size = findNextPowerOf((int)(pad*size[0]), 2);
374 if ( ft_size < p->sizeX() ) ft_size = p->sizeX();
375
376 delete p;
377
378 // Header structure for the final reconstruction
379 Bimage* prec = new Bimage(Float, TComplex, size[0], size[1], slab_thickness, 1);
380 prec->sampling(mg->pixel_size/scale, mg->pixel_size/scale, mg->pixel_size/scale);
381 prec->origin(prec->sizeX()/2, prec->sizeY()/2, size[2]/2);
382 if ( hi_res < 2*prec->sampling()[0] ) hi_res = 2*prec->sampling()[0];
383 prec->next = new Bimage(Float, TSimple, prec->size(), prec->images());
384 float* fom = (float *) prec->next->data_pointer();
385
386 long ds = prec->sizeX()*prec->sizeY()*prec->sizeZ();
387 float* weight = new float[ds];
388 float* weight2 = new float[ds];
389
390 // if ( verbose & VERB_PROCESS ) {
391 if ( verbose ) {
392 cout << "3D reciprocal space reconstruction on disk:" << endl;
393 cout << "Map size: " << prec->sizeX() << " " << prec->sizeY() << " " << size[2] << endl;
394 cout << "Scale: " << scale << endl;
395 cout << "Fourier transform size: " << ft_size << " x " << ft_size << endl;
396 cout << "Slab: " << slab_start << " - " << slab_end << endl << endl;
397 }
398
399
400 Vector3<long> tile_size(128,128,1);
401 fft_plan plan = fft_setup_plan(ft_size, ft_size, 1, FFTW_FORWARD, 0);
402
403 for ( field = project->field; field; field = field->next ) {
404 for ( mg = field->mg; mg; mg = mg->next ) if ( mg->select ) {
405 p = mg_tomo_rec_prepare(mg, ft_size, size[2], 5.0,
406 marker_radius, fill_type, fill, action, wiener, tile_size, plan);
407 if ( !p ) {
408 error_show("project_fourier_reconstruction_slab", __FILE__, __LINE__);
409 return NULL;
410 }
411
412 img_pack_2D_in_recip_space_slab(p, prec, size[2], slab_start, weight, weight2,
413 hi_res, mg->matrix, scale);
414
415 delete p;
416
417 nrec++;
418
419 if ( verbose & ( VERB_TIME | VERB_PROCESS ) ) {
420 cout << "Complete: "
421 << setprecision(3) << nrec*100.0/(nfld*nmg) << " %\r";
422 cout.flush();
423 }
424 }
425 }
426
427 fft_destroy_plan(plan);
428
429 if ( nrec < 1 ) {
430 delete prec;
431 error_show("Error in project_fourier_reconstruction_slab: No micrographs used in this reconstruction!", __FILE__, __LINE__);
432 return NULL;
433 }
434
435 if ( verbose & VERB_TIME )
436 timer_report(ti);
437
438 if ( verbose )
439 cout << "Weighing reconstruction." << endl;
440
441 long cov(0);
442
443 #ifdef HAVE_GCD
444 dispatch_apply(ds, dispatch_get_global_queue(0, 0), ^(size_t i){
445 if ( weight[i] > SMALLFLOAT ) {
446 prec->set(i, prec->complex(i) / weight[i]);
447 weight2[i] = weight[i]*weight[i] - weight2[i]; // Unbiased weighting
448 if ( weight2[i] > 0.001 ) {
449 double rd2 = (prec->complex(i)).power();
450 fom[i] = (fom[i] - weight[i]*rd2)/weight2[i]; // Noise variance estimator with noise reduction
451 fom[i] = rd2/fom[i] - 1; // SNR
452 } else fom[i] = 0;
453 }
454 });
455 #else
456 #pragma omp parallel for
457 for ( i=0; i<ds; i++ ) {
458 if ( weight[i] > SMALLFLOAT ) {
459 prec->set(i, prec->complex(i) / weight[i]);
460 weight2[i] = weight[i]*weight[i] - weight2[i]; // Unbiased weighting
461 if ( weight2[i] > 0.001 ) {
462 double rd2 = (prec->complex(i)).power();
463 fom[i] = (fom[i] - weight[i]*rd2)/weight2[i]; // Noise variance estimator with noise reduction
464 fom[i] = rd2/fom[i] - 1; // SNR
465 } else fom[i] = 0;
466 }
467 }
468 #endif
469
470 for ( i=0; i<ds; i++ ) if ( weight[i] > SMALLFLOAT ) cov++;
471
472 delete[] weight;
473 delete[] weight2;
474
475 img_phase_shift_slab_to_origin(prec, size[2], slab_start);
476
477 long vol = ds;
478
479 if ( verbose & VERB_RESULT ) {
480 cout << "Coverage:" << endl;
481 cout << "Total number of voxels: " << vol << endl;
482 cout << "Total coverage: " << cov << endl;
483 cout << "Percentage coverage: " << cov*100.0/vol << " %" << endl;
484 }
485
486 // if ( verbose & VERB_TIME )
487 timer_report(ti);
488
489 return prec;
490 }
491
492
493
518 long particle_tomo_reconstruct(Bproject* project, Bparticle* recpart,
519 Vector3<long> recsize, double resolution, int interp_type,
520 long ft_size, double scale, fft_plan planp, fft_plan planr,
521 int ctf_action, double wiener, Bsymmetry* sym,
522 Bstring& partbase, Bstring& partpath, Bstring& partext)
523 {
524 Bstring filename("part");
525
526 // Setting the base file name
527 if ( partbase.length() ) filename = partbase + Bstring(recpart->id, "_part%03d.");
528 else if ( recpart->fpart.length() ) filename = recpart->fpart.pre_rev('.') + "_r.";
529 // else filename = rec->frec.pre_rev('.') + Bstring(recpart->id, "_part%03d.");
530
531 // Setting the extension
532 if ( partext.length() ) filename += partext;
533 else if ( recpart->fpart.length() ) filename += recpart->fpart.post_rev('.');
534 // else filename += rec->frec.post_rev('.');
535
536 // Setting the path
537 if ( partpath.length() ) {
538 if ( filename.contains("/") ) filename = filename.post_rev('/');
539 filename = partpath + filename;
540 }
541
542 if ( verbose & VERB_FULL )
543 cout << "Reconstructing particle " << recpart->id << endl;
544
545 Bfield* field;
546 Bmicrograph* mg;
547 Bparticle* part;
548 Bparticle* partlist = NULL;
549
550 for ( field = project->field; field; field = field->next ) if ( field->select ) {
551 for ( mg = field->mg; mg; mg = mg->next ) if ( mg->select ) {
552 for ( part = mg->part; part; part = part->next )
553 if ( recpart->id == part->id ) break;
554 if ( part ) {
555 particle_copy(&partlist, part);
556 }
557 }
558 }
559
560 Bimage* prec = particle_reconstruct(partlist, sym, 0,
561 resolution, scale, recsize, ft_size, planp,
562 interp_type, ctf_action, wiener, 0, 0, 0);
563
564 long nr = prec->image->FOM();
565
566 prec->fspace_reconstruction_weigh();
567
568 prec->phase_shift_to_center();
569 prec->origin(prec->size()/2);
570 prec->fft_back(planr);
571 prec->statistics();
572 prec->correct_background();
573 // prec->change_type(newdatatype);
574 write_img(filename, prec, 0);
575 recpart->fpart = filename;
576 recpart->view = View(0,0,1,0);
577 recpart->ori = prec->image->origin();
578
579 delete prec;
580 particle_kill(partlist);
581
582 return nr;
583 }
584
604 long project_tomo_reconstruct_particles(Bproject* project,
605 double resolution, int interp_type, int pad_factor,
606 int ctf_action, double wiener, Bsymmetry* sym,
607 Bstring& partbase, Bstring& partpath, Bstring& partext)
608 {
609 if ( !partpath.empty() ) {
610 if ( partpath[-1] != '/' ) partpath += "/";
611 mkdir(partpath.c_str(), (mode_t)0755);
612 }
613
614 if ( partext.length() < 1 ) partext = "pif";
615
616
617 Bfield* field;
618 Bmicrograph* mg = NULL;
619 Breconstruction* rec = NULL;
620 Bparticle* partlist = NULL;
621 Bparticle* part = NULL;
622
623 for ( rec = project->rec; rec; rec = rec->next )
624 if ( rec->part ) {
625 partlist = rec->part;
626 break;
627 }
628
629 if ( !partlist ) {
630 cerr << "No particle list found!" << endl << endl;
631 return -1;
632 }
633
634 for ( field = project->field; field; field = field->next ) {
635 for ( mg = field->mg; mg; mg = mg->next )
636 if ( mg ) break;
637 if ( mg ) break;
638 }
639
640 if ( !mg ) {
641 cerr << "No micrographs found!" << endl << endl;
642 return -1;
643 }
644
645 if ( !mg->part ) {
646 cerr << "No micrograph particles found!" << endl << endl;
647 return -1;
648 }
649
650 // Vector3<long> boxsize(mg->box_size);
651
652 rec->box_size = mg->box_size.max(mg->box_size[0]);
653 // Vector3<long> recsize(boxsize);
654 // recsize[2] = recsize[1] = recsize[0];
655
656 rec->voxel_size = mg->pixel_size;
657
658 double scale(rec->box_size[0]*1.0/mg->box_size[0]);
659
660 long ft_size = part_ft_size(mg->box_size[0], scale, pad_factor);
661
662 fft_plan planp = fft_setup_plan(ft_size, ft_size, 1, FFTW_FORWARD, 1);
663 fft_plan planr = fft_setup_plan(rec->box_size, FFTW_BACKWARD, 1);
664
665 if ( verbose ) {
666 cout << "Calculating individual particle reconstructions:" << endl;
667 cout << "Reconstruction: " << rec->id << endl;
668 cout << "Particle size: " << mg->box_size << endl;
669 cout << "Reconstruction size: " << rec->box_size << endl;
670 cout << "Fourier transform size: " << ft_size << " x " << ft_size << endl;
671 cout << "Padding factor: " << pad_factor << endl;
672 cout << "Reconstruction resolution: " << resolution << " A" << endl;
673 cout << "CTF application type: " << ctf_action << endl;
674 cout << endl;
675 }
676
677 long i, npart = particle_count(partlist);
678
679 Bparticle** partarr = new Bparticle*[npart];
680
681 for ( i=0, part = partlist; part; part = part->next, i++ ) partarr[i] = part;
682
683 if ( verbose & VERB_RESULT )
684 cout << "Part\t#" << endl;
685
686 #ifdef HAVE_GCD
687 dispatch_queue_t myq = dispatch_queue_create(NULL, NULL);
688 dispatch_apply(npart, dispatch_get_global_queue(0, 0), ^(size_t i){
689 long nr = particle_tomo_reconstruct(project, partarr[i], rec->box_size,
690 resolution, interp_type, ft_size, scale, planp, planr,
691 ctf_action, wiener, sym, partbase, partpath, partext);
692 dispatch_sync(myq, ^{
693 if ( verbose & VERB_RESULT )
694 cout << partarr[i]->id << tab << fixed << nr << endl << flush;
695 });
696 });
697 #else
698 #pragma omp parallel for
699 for ( i=0; i<npart; i++ ) {
700 long nr = particle_tomo_reconstruct(project, partarr[i], rec->box_size,
701 resolution, interp_type, ft_size, scale, planp, planr,
702 ctf_action, wiener, sym, partbase, partpath, partext);
703 #pragma omp critical
704 {
705 if ( verbose & VERB_RESULT ) {
706 cout << partarr[i]->id << tab << fixed << nr << endl << flush;
707 }
708 }
709 }
710 #endif
711
712 delete[] partarr;
713
714 fft_destroy_plan(planp);
715 fft_destroy_plan(planr);
716
717 return 0;
718 }
719
720
731 int img_backtransform_slices(Bimage* p)
732 {
733 double ti;
734 // if ( verbose & VERB_TIME )
735 ti = timer_start();
736
737 long i, j, z;
738 long slice_size = p->sizeX()*p->sizeY()*p->channels();
739 Vector3<double> extorigin;
740 Vector3<long> extsize(p->sizeX(), p->sizeY(), 1);
741 Bimage* ps = NULL;
742
743 if ( verbose )
744 cout << "Backtransforming reconstruction slices." << endl << endl;
745
746 for ( z=0; z<p->sizeZ(); z++ ) {
747 if ( verbose & VERB_FULL )
748 cout << "Shifting and backtransforming slice " << z << endl;
749 extorigin[2] = z;
750 ps = p->extract(0, extorigin, extsize);
751 ps->fft(FFTW_BACKWARD, 1);
752 for ( i=z*slice_size, j=0; j<slice_size; i++, j++ ) p->set(i, (*ps)[j]);
753 delete ps;
754 }
755
756 // if ( verbose & VERB_TIME )
757 timer_report(ti);
758
759 return 0;
760 }
761
782 long img_pack_2D_in_recip_space_slab(Bimage* p, Bimage* prec,
783 long zsize, long slab_start, float* weight, float* weight2,
784 double hi_res, Matrix3 mat, double scale)
785 {
786 if ( !p->data_pointer() ) return 0;
787
788 if ( hi_res < 2*prec->sampling()[0] ) hi_res = 2*prec->sampling()[0];
789
790 long i, j, x, y;
791 long ix, iy, iz, izs, zs;
792 double w, d2;
793 Vector3<double> m, d, iv;
794
795 int pad = 2;
796 long ft_size = p->sizeX();
797 Bimage* pt;
798
799 // Do transformation if not already done
800 if ( p->compound_type() == TSimple ) {
801 ft_size = findNextPowerOf((int)(pad*prec->sizeX()), 2);
802 if ( ft_size < p->sizeX() ) ft_size = p->sizeX();
803 pt = p->pad_copy(ft_size, FILL_AVERAGE, p->average());
804 pt->fft();
805 pt->phase_shift_to_origin();
806 } else pt = p->copy();
807
808 Vector3<double> vscale(prec->sizeX(), prec->sizeY(), zsize);
809 vscale /= scale*ft_size;
810 // mat = mat.transpose(); Handedness
811 mat = vscale * mat; // Matrix includes scaling going from image to map
812
813 if ( verbose )
814 cout << "Packing " << p->file_name() << endl;
815
816 if ( verbose & VERB_FULL ) {
817 cout << "Resolution limit: " << hi_res << " A" << endl;
818 cout << "Slab start: " << slab_start << endl;
819 cout << "Fourier transform size: " << ft_size << endl;
820 cout << "Transformation matrix:" << endl;
821 cout << mat << endl;
822 cout << endl;
823 }
824
825 float* fom = (float *) prec->next->data_pointer();
826
827 double max_rad = pt->sampling()[0]/hi_res;
828 if ( max_rad > 0.5 ) max_rad = 0.5;
829 max_rad *= pt->sizeX();
830 double max_rad_sq = max_rad*max_rad; // Maximum radius squared on ft scale
831 double xmin = floor(-max_rad);
832 double xmax = -xmin;
833 double ymin = floor(-max_rad);
834 double ymax = -ymin;
835
836 // cout << "sam=" << pt->sampling()[0] << " hi_res=" << hi_res << " max_rad=" << max_rad << endl;
837
838 for ( iv[1]=ymin; iv[1]<=ymax; iv[1]+=1 ) {
839 y = (long) iv[1];
840 if ( y < 0 ) y += (long)p->sizeY();
841 for ( iv[0]=xmin; iv[0]<=xmax; iv[0]+=1 ) {
842 x = (long) iv[0];
843 if ( x < 0 ) x += (long)p->sizeX();
844 d2 = iv.length2();
845 if ( d2 < max_rad_sq ) { // Nearest neighbour
846 m = mat * iv;
847 iz = izs = (long) floor(m[2] + 0.5); // Nearest neighbour
848 if ( izs < 0 ) izs += zsize;
849 zs = izs - slab_start;
850 if ( zs >= 0 && zs < prec->sizeZ() ) {
851 ix = (long) floor(m[0] + 0.5);
852 iy = (long) floor(m[1] + 0.5);
853 d[0] = ix - m[0];
854 d[1] = iy - m[1];
855 d[2] = iz - m[2];
856 // d /= vscale;
857 w = 1 - d.length();
858 if ( w > 1e-6 ) {
859 if ( ix < 0 ) ix += prec->sizeX();
860 if ( iy < 0 ) iy += prec->sizeY();
861 i = y*pt->sizeX() + x;
862 j = (zs*prec->sizeY() + iy)*prec->sizeX() + ix;
863 // prec->set(j, prec->complex(j) + pt->complex(i) * w);
864 prec->add(j, pt->complex(i) * w);
865 fom[j] += w*(pt->complex(i)).power();
866 weight[j] += w;
867 weight2[j] += w*w;
868 }
869 }
870 }
871 }
872 }
873
874 delete pt;
875
876 return 0;
877 }
878
891 int img_phase_shift_slab_to_origin(Bimage* p, int zsize, int slab_start)
892 {
893 if ( p->compound_type() != TComplex ) return -1;
894
895 long i, x, y, z, zs;
896 long h, k, l;
897 double skl, sl, phi;
898 Vector3<double> shift((p->sizeX()/2)*1.0/p->sizeX(), (p->sizeY()/2)*1.0/p->sizeY(), (zsize/2)*1.0/zsize);
899 Vector3<double> half((p->sizeX() - 1)/2, (p->sizeY() - 1)/2, (zsize - 1)/2);
900 Complex<double> temp;
901
902 if ( verbose & VERB_PROCESS )
903 cout << "Translate slice within unit cell to phase origin by " << shift << endl << endl;
904
905 for ( i=zs=0, z=slab_start; zs<p->sizeZ(); zs++, z++ ) {
906 l = z;
907 if ( l > half[2] ) l -= zsize;
908 sl = l*shift[2];
909 for ( y=0; y<p->sizeY(); y++ ) {
910 k = y;
911 if ( k > half[1] ) k -= p->sizeY();
912 skl = sl + k*shift[1];
913 for ( x=0; x<p->sizeX(); x++, i++ ) {
914 h = x;
915 if ( h > half[0] ) h -= p->sizeX();
916 phi = MIN2PI*(h*shift[0] + skl);
917 temp = Complex<double>(cos(phi), sin(phi));
918 p->set(i, (p->complex(i))*temp);
919 }
920 }
921 }
922
923 return 0;
924 }
925
937 int img_clear_extraneous_areas(Bimage* p, double tilt_axis, double tilt_angle, long thickness)
938 {
939 if ( p->sizeZ() > 1 ) return -1;
940 if ( p->images() > 1 ) return -1;
941
942 long i, x, y, c;
943
944 p->calculate_background();
945
946 if ( verbose & VERB_FULL )
947 cout << "Clearing extraneous areas from micrograph " << p->file_name() << endl;
948
949 Vector3<double> v(-sin(tilt_axis), cos(tilt_axis), 0);
950 double a, b, d = 1e30;
951 if ( v[0] && d > fabs(p->sizeX()*0.5/v[0]) ) d = fabs(p->sizeX()*0.5/v[0]);
952 if ( v[1] && d > fabs(p->sizeY()*0.5/v[1]) ) d = fabs(p->sizeY()*0.5/v[1]);
953
954 a = d*cos(tilt_angle) + fabs(0.5*thickness*sin(tilt_angle));
955
956 for ( i=y=0; y<p->sizeY(); y++ ) {
957 for ( x=0; x<p->sizeX(); x++ ) {
958 b = fabs(v[0]*(x - p->image->origin()[0]) + v[1]*(y - p->image->origin()[1]));
959 for ( c=0; c<p->channels(); c++, i++ )
960 if ( b > a ) p->set(i, p->background(long(0)));
961 }
962 }
963
964 return 0;
965 }
966
986 int mg_fft_write(Bproject* project, Vector3<int> size, double scale, int pad_factor,
987 Bstring& label, DataType datatype, double marker_radius, int fill_type, double fill)
988 {
989 if ( pad_factor < 0 ) pad_factor = 0; // 0 indicates using original size
990 if ( pad_factor > 8 ) pad_factor = 8;
991
992 if ( datatype < Short ) datatype = Float;
993
994 int n, nsel(0);
995
996 Bfield* field = project->field;
997 Bmicrograph* mg = field->mg;
998 Bmarker* mark = NULL;
999 Bimage* p = read_img(mg->fmg, 0, 0);
1000
1001 if ( !mg->fmg.length() ) {
1002 error_show("Error in mg_fft_write", __FILE__, __LINE__);
1003 cerr << "No micrograph image file name given for micrograph " << mg->id << endl << endl;
1004 return -1;
1005 }
1006
1007 if ( size[2] < 1 ) size[2] = p->sizeX();
1008 if ( size.volume() < 1 ) size = Vector3<int>(p->size());
1009 if ( size[2] > p->sizeX() ) size[2] = p->sizeX();
1010 if ( size[2] > p->sizeY() ) size[2] = p->sizeY();
1011
1012 long ft_size = findNextPowerOf((int)(pad_factor*size[0]*scale), 2);
1013 if ( ft_size < p->sizeX() ) ft_size = p->sizeX();
1014 if ( ft_size < p->sizeY() ) ft_size = p->sizeY();
1015
1016 delete p;
1017
1018 if ( verbose & VERB_PROCESS ) {
1019 cout << "Transforming micrographs:" << endl;
1020 cout << "Reconstruction size: " << size << endl;
1021 cout << "Reconstruction scale: " << scale << endl;
1022 cout << "Fourier transform size: " << ft_size << " x " << ft_size << endl << endl;
1023 }
1024
1025 for ( n=0, mg=field->mg; mg; mg=mg->next, n++ ) if ( mg->select ) {
1026 if ( verbose )
1027 cout << "Reading image " << mg->img_num << " (micrograph " << mg->id << ")" << endl;
1028 if ( ( p = read_img(mg->fmg, 1, mg->img_num) ) == NULL ) {
1029 error_show("mg_fft_write", __FILE__, __LINE__);
1030 return -1;
1031 }
1032
1033 p->image->origin(mg->origin);
1034
1035 p->calculate_background();
1036 if ( size[2] < p->sizeX() && size[2] < p->sizeY() )
1037 img_clear_extraneous_areas(p, mg->tilt_axis, mg->tilt_angle, size[2]);
1038
1039 if ( marker_radius > 0 ) {
1040 if ( marker_radius < mg->mark_radius ) marker_radius = 1.5*mg->mark_radius;
1041 p->statistics();
1042 for ( mark = mg->mark; mark; mark = mark->next )
1043 p->sphere(mark->loc, marker_radius, 2, fill_type, fill);
1044 }
1045
1046 p->pad(ft_size, fill_type, fill);
1047
1048 p->fft();
1049
1050 p->phase_shift_to_origin();
1051
1052 p->change_type(datatype);
1053 p->label(label.str());
1054
1055 mg->fft = mg->fmg;
1056 if ( mg->fft.contains("/") ) mg->fft = mg->fft.post_rev('/');
1057 mg->fft = mg->fft.pre_rev('.') + "_ft" + Bstring(n, "%04d") + ".sup";
1058 write_img(mg->fft, p, 0);
1059 // mg->img_num = 0;
1060
1061 delete p;
1062
1063 nsel++;
1064 }
1065
1066 return nsel;
1067 }
1068
1082 Bimage* img_extract_ytile(Bstring* file_list, int ystart, int ysize)
1083 {
1084 Bimage* p = NULL;
1085 Bimage* pmap = NULL;
1086 int err(0);
1087 long i(0), j(0), y, z, yt, zt;
1088 Bstring* thisfile = NULL;
1089
1090 if ( verbose )
1091
1092 // First read the file headers to identify problems
1093 for ( thisfile = file_list; thisfile; thisfile = thisfile->next ) {
1094 p = read_img(*thisfile, 0, -1);
1095 if ( p != NULL ) {
1096 if ( verbose & VERB_DEBUG )
1097 cout << p->file_name() << ": " <<
1098 p->sizeX() << " " << p->sizeY() << " " << p->sizeZ() << " " << p->images() << " " << p->channels() << endl;
1099 if ( p->images() > 1 ) {
1100 cerr << p->file_name() << " must be a single image file!" << endl;
1101 err += -1;
1102 }
1103 if ( i == 0 ) {
1104 pmap = p;
1105 } else {
1106 // err += img_compatibility(pmap, p);
1107 if ( !p->compatible(pmap) ) err += -1;
1108 delete p;
1109 }
1110 i += p->sizeZ();
1111 } else err += -1;
1112 }
1113
1114 if ( err < 0 || i == 0 ) {
1115 cerr << "Files not concatenated! Number of errors: " << -err << endl;
1116 return NULL;
1117 }
1118
1119 pmap->sizeZ(i); // Only z-slabs!
1120
1121 // Bstring filename = p->file_name().pre_rev('.') + ".tiles";
1122 Bstring filename("y.tiles");
1123 ofstream fd(filename.c_str());
1124 if ( fd.fail() ) {
1125 cerr << "Error: Tile parameter file %s not opened" << filename << endl;
1126 return NULL;
1127 }
1128 fd << pmap->sizeX() << " " << pmap->sizeY() << " " << pmap->sizeZ() << endl;
1129 fd << "0 0 0" << endl;
1130 y = ystart%ysize;
1131 if ( y ) fd << "0 0 0" << endl;;
1132 for ( ; y<pmap->sizeY(); y+=ysize ) fd << "0 " << y << " 0" << endl;
1133 fd.close();
1134
1135 long elementsize = pmap->channels()*pmap->data_type_size();
1136 long linesize = elementsize*pmap->sizeX();
1137
1138 if ( ystart + ysize > pmap->sizeY() ) ysize = pmap->sizeY() - ystart;
1139
1140 pmap->sizeY(ysize);
1141 pmap->data_alloc();
1142 unsigned char* tile = pmap->data_pointer();
1143 unsigned char* data;
1144
1145 if ( verbose ) {
1146 cout << "Extracting y tile from " << ystart << " to " << ystart+ysize-1 << endl;
1147 cout << "Tile size: " << pmap->size() << endl;
1148 cout << "Tile parameter file: " << filename << endl;
1149 }
1150
1151 for ( zt=0, thisfile = file_list; thisfile; thisfile = thisfile->next ) {
1152 p = read_img(*thisfile, 1, 0);
1153 data = p->data_pointer();
1154 for ( z=0; z<p->sizeZ() && zt<pmap->sizeZ(); z++, zt++ ) {
1155 for ( y=ystart, yt=0; y<p->sizeY() && yt<pmap->sizeY(); y++, yt++ ) {
1156 i = (z*p->sizeY() + y)*linesize;
1157 j = (zt*pmap->sizeY() + yt)*linesize;
1158 memcpy(tile+j, data+i, linesize);
1159 }
1160 }
1161 delete p;
1162 }
1163
1164 return pmap;
1165 }
1166
1184 Bimage* img_backtransform_z_on_disk(Bstring* file_list, Bstring& recfile,
1185 DataType datatype, Bstring& label, double avg, double std, double cutmin, double cutmax)
1186 {
1187 Bimage* p = NULL;
1188 Bimage* pmap = NULL;
1189 int err(0);
1190 long i(0), j(0);
1191 Bstring* thisfile = NULL;
1192 Bstring tempfile("temp.raw");
1193
1194 // First read the file headers to identify problems
1195 for ( thisfile = file_list; thisfile; thisfile = thisfile->next ) {
1196 p = read_img(*thisfile, 0, -1);
1197 if ( p != NULL ) {
1198 if ( verbose & VERB_DEBUG )
1199 cout << p->file_name() << ": " <<
1200 p->sizeX() << " " << p->sizeY() << " " << p->sizeZ() << " " << p->images() << " " << p->channels() << endl;
1201 if ( p->images() > 1 ) {
1202 cerr << p->file_name() << " must be a single image file!" << endl;
1203 err += -1;
1204 }
1205 if ( i == 0 ) {
1206 pmap = p;
1207 } else {
1208 // err += img_compatibility(pmap, p);
1209 if ( !p->compatible(pmap) ) err += -1;
1210 delete p;
1211 }
1212 i += p->sizeZ();
1213 j++;
1214 } else err += -1;
1215 }
1216
1217 if ( err < 0 || j == 0 ) {
1218 cerr << "Files not concatenated! Number of errors: " << -err << endl;
1219 return NULL;
1220 }
1221
1222 pmap->sizeZ(i);
1223
1224 fstream* ftemp = new fstream(tempfile.c_str());
1225 if ( ftemp->fail() ) {
1226 cerr << "Error: " << tempfile << " not opened!" << endl << endl;
1227 return NULL;
1228 }
1229
1230 long elementsize = pmap->channels()*pmap->data_type_size();
1231 long datasize(0);
1232
1233 for ( thisfile = file_list; thisfile; thisfile = thisfile->next ) {
1234 p = read_img(*thisfile, 1, -1);
1235 if ( !p ) {
1236 cerr << "Error: Image " << *thisfile << " not read!" << endl;
1237 bexit(-1);
1238 } else {
1239 datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
1240 ftemp->write((char *)p->data_pointer(), elementsize*datasize);
1241 }
1242 delete p;
1243 }
1244
1245 img_backtransform_z_lines(ftemp, pmap);
1246
1247 // Write the final real space map header
1248 pmap->label(label.str());
1249 pmap->file_name(recfile.str());
1250 if ( datatype == Unknown_Type ) pmap->data_type(Float);
1251 else pmap->data_type(datatype);
1252
1253 img_write_data_block_with_type(ftemp, pmap, avg, std, cutmin, cutmax);
1254
1255 ftemp->close();
1256 delete ftemp;
1257
1258 remove(tempfile.c_str());
1259
1260 return pmap;
1261 }
1262
1263 int img_backtransform_one_y_plane(Bimage* p, fft_plan plan, int y)
1264 {
1265 long i, x, z;
1266 long slice_size = p->sizeX()*p->sizeY();
1267 long zsize = p->sizeZ()*sizeof(Complex<float>);
1268 Complex<float>* zline = new Complex<float>[zsize];
1269
1270 if ( verbose & VERB_PROCESS )
1271 if ( y%10 == 0 ) cout << "Backtransforming z lines for y=" << y << endl;
1272 for ( x=0; x<p->sizeX(); x++ ) {
1273 for ( z=0, i=y*p->sizeX() + x; z<p->sizeZ(); z++, i+=slice_size ) zline[z] = p->complex(i);
1274 fftw(plan, zline);
1275 for ( z=0, i=y*p->sizeX() + x; z<p->sizeZ(); z++, i+=slice_size ) p->set(i, zline[z]);
1276 }
1277
1278 delete[] zline;
1279
1280 return 0;
1281 }
1282
1283 int img_backtransform_one_y_plane(fstream* ftemp, Bimage* p, fft_plan plan,
1284 int y, Complex<float>* zline, Complex<float>* cfdata)
1285 {
1286 long i, x, z, offset;
1287 long cfsize = sizeof(Complex<float>);
1288 long planesize = p->sizeX()*p->sizeZ();
1289 double v;
1290
1291 if ( verbose & VERB_PROCESS )
1292 if ( y%10 == 0 ) cout << "Backtransforming z lines for y=" << y << endl;
1293 for ( z=0; z<p->sizeZ(); z++ ) {
1294 offset = (z*p->sizeY() + y)*p->sizeX()*cfsize;
1295 // fseek(ftemp, offset, SEEK_SET);
1296 // fread(&cfdata[z*p->sizeX()], cfsize, p->sizeX(), ftemp);
1297 ftemp->seekg(offset, ios::beg);
1298 ftemp->read((char *)&cfdata[z*p->sizeX()], cfsize*p->sizeX());
1299 }
1300 for ( x=0; x<p->sizeX(); x++ ) {
1301 for ( z=0; z<p->sizeZ(); z++ ) zline[z] = cfdata[z*p->sizeX() + x];
1302 fftw(plan, zline);
1303 for ( z=0; z<p->sizeZ(); z++ ) cfdata[z*p->sizeX() + x] = zline[z];
1304 }
1305 for ( z=0; z<p->sizeZ(); z++ ) {
1306 offset = (z*p->sizeY() + y)*p->sizeX()*cfsize;
1307 // fseek(ftemp, offset, SEEK_SET);
1308 // fwrite(&cfdata[z*p->sizeX()], cfsize, p->sizeX(), ftemp);
1309 ftemp->seekg(offset, ios::beg);
1310 ftemp->write((char *)&cfdata[z*p->sizeX()], cfsize*p->sizeX());
1311 }
1312
1313 for ( i=0; i<planesize; i++ ) {
1314 v = cfdata[i].real();
1315 if ( p->minimum() > v ) p->minimum(v);
1316 if ( p->maximum() < v ) p->maximum(v);
1317 p->average(p->average() + v);
1318 p->standard_deviation(p->standard_deviation() + v*v);
1319 }
1320
1321 return 0;
1322 }
1323
1334 int img_backtransform_z_lines(Bimage* p)
1335 {
1336 fft_plan plan = fft_setup_plan(p->sizeZ(), 1, 1, FFTW_FORWARD, 1);
1337
1338 #ifdef HAVE_GCD
1339 dispatch_apply(p->sizeY(), dispatch_get_global_queue(0, 0), ^(size_t y){
1340 img_backtransform_one_y_plane(p, plan, y);
1341 });
1342 #else
1343 #pragma omp parallel for
1344 for ( long y=0; y<p->sizeY(); y++ )
1345 img_backtransform_one_y_plane(p, plan, y);
1346 #endif
1347
1348 fft_destroy_plan(plan);
1349
1350 p->complex_to_real();
1351 p->statistics();
1352
1353 if ( verbose ) {
1354 cout << "Reconstruction statistics:" << endl;
1355 cout << "Min and max: " << p->minimum() << " " << p->maximum() << endl;
1356 cout << "Avg and std: " << p->average() << " " << p->standard_deviation() << endl << endl;
1357 }
1358
1359 return 0;
1360 }
1361
1362 int img_backtransform_z_lines(fstream* ftemp, Bimage* p)
1363 {
1364 int y;
1365 long datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
1366
1367 fft_plan plan = fft_setup_plan(p->sizeZ(), 1, 1, FFTW_FORWARD, 1);
1368 Complex<float>* zline = new Complex<float>[p->sizeZ()];
1369 Complex<float>* cfdata = new Complex<float>[p->sizeX()*p->sizeZ()];
1370
1371 p->minimum(1e37);
1372 p->maximum(-1e37);
1373 p->average(0);
1374 p->standard_deviation(0);
1375
1376 for ( y=0; y<p->sizeY(); y++ )
1377 img_backtransform_one_y_plane(ftemp, p, plan, y, zline, cfdata);
1378
1379 fft_destroy_plan(plan);
1380 delete[] zline;
1381 delete[] cfdata;
1382
1383 p->average(p->average() / datasize);
1384 p->standard_deviation(p->standard_deviation()/datasize - p->average()*p->average());
1385 if ( p->standard_deviation() > 0 ) p->standard_deviation(sqrt(p->standard_deviation()));
1386 else p->standard_deviation(0);
1387
1388 if ( verbose ) {
1389 cout << "Reconstruction statistics:" << endl;
1390 cout << "Min and max: " << p->minimum() << " " << p->maximum() << endl;
1391 cout << "Avg and std: " << p->average() << " " << p->standard_deviation() << endl << endl;
1392 }
1393
1394 return 0;
1395 }
1396
1397
1407 long gettypesize(DataType type)
1408 {
1409 long size;
1410
1411 switch ( type ) {
1412 case Bit:
1413 case UCharacter: case SCharacter: size = sizeof(char); break;
1414 case UShort: case Short: size = sizeof(short); break;
1415 case UInteger: case Integer: size = sizeof(int); break;
1416 case ULong: case Long: size = sizeof(long); break;
1417 case Float: size = sizeof(float); break;
1418 case Double: size = sizeof(double); break;
1419 default: size = 0;
1420 }
1421
1422 return size;
1423 }
1424
1425
1437 int set_value_with_datatype(char* ptr, double value, DataType datatype)
1438 {
1439 int typesize = gettypesize(datatype);
1440 if ( typesize < 1 ) return -1;
1441
1442 switch ( datatype ) {
1443 case UCharacter: *ptr = (unsigned char) value; break;
1444 case SCharacter: {
1445 signed char cval = (signed char) value;
1446 memcpy(ptr, &cval, typesize); break;
1447 }
1448 case UShort: {
1449 unsigned short uval = (unsigned short) value;
1450 memcpy(ptr, &uval, typesize); break;
1451 }
1452 case Short: {
1453 short sval = (short) value;
1454 memcpy(ptr, &sval, typesize); break;
1455 }
1456 case UInteger: {
1457 unsigned int ival = (unsigned int) value;
1458 memcpy(ptr, &ival, typesize); break;
1459 }
1460 case Integer: {
1461 int ival = (int) value;
1462 memcpy(ptr, &ival, typesize); break;
1463 }
1464 case ULong: {
1465 long ival = (long) value;
1466 memcpy(ptr, &ival, typesize); break;
1467 }
1468 case Long: {
1469 long ival = (long) value;
1470 memcpy(ptr, &ival, typesize); break;
1471 }
1472 case Float: {
1473 float fval = (float) value;
1474 memcpy(ptr, &fval, typesize); break;
1475 }
1476 case Double: {
1477 double dval = (double) value;
1478 memcpy(ptr, &dval, typesize); break;
1479 }
1480 default: ;
1481 }
1482
1483 return 0;
1484 }
1485
1486 /*
1487 @brief Rescales and writes a raw disk-based data block to a specific data type.
1488 @param fstream* ftemp file pointer to the complex raw data block.
1489 @param *p image header information.
1490 @return int 0.
1491
1492 Each slice is read from the raw data block, rescaled, and written
1493 into the new file.
1494 Limitation: This function can only be used for an image file format
1495 with a contiguous data block (CCP4, MRC, PIF, etc.).
1496
1497 **/
1498 int img_write_data_block_with_type(fstream* ftemp, Bimage* p,
1499 double avg, double std, double cutmin, double cutmax)
1500 {
1501
1502 long i, z, offset;
1503 long elementsize = p->data_type_size();
1504 long cfsize = sizeof(Complex<float>);
1505 long slicesize = p->sizeX()*p->sizeY();
1506 double scale = 1;
1507 double shift(0);
1508
1509 switch ( p->data_type() ) {
1510 case UCharacter: scale = 255/(p->maximum() - p->minimum());
1511 shift = -p->minimum()*scale; break;
1512 case SCharacter: scale = 255/(p->maximum() - p->minimum());
1513 shift = -128 - p->minimum()*scale; break;
1514 case UShort: scale = USHRT_MAX/(p->maximum() - p->minimum());
1515 shift = -p->minimum()*scale; break;
1516 case Short: scale = SHRT_MAX/(p->maximum() - p->minimum()); break;
1517 case Integer: scale = 2e9/(p->maximum() - p->minimum()); break;
1518 case Float:
1519 case Double: scale = 1; break;
1520 default: ;
1521 }
1522
1523 if ( std ) {
1524 scale = std/p->standard_deviation();
1525 shift = avg - p->average()*scale;
1526 }
1527
1528 p->minimum(scale*p->minimum() + shift);
1529 p->maximum(scale*p->maximum() + shift);
1530 p->average(scale*p->average() + shift);
1531 p->standard_deviation(p->standard_deviation() * scale);
1532
1533 if ( cutmin >= cutmax ) {
1534 cutmin = p->minimum();
1535 cutmax = p->maximum();
1536 }
1537
1538 p->minimum(p->data_type_min());
1539 p->maximum(p->data_type_max());
1540
1541 if ( cutmin < p->minimum() ) cutmin = p->minimum();
1542 if ( cutmax > p->maximum() ) cutmax = p->maximum();
1543
1544 p->minimum(cutmin);
1545 p->maximum(cutmax);
1546
1547 p->fourier_type(NoTransform);
1548
1549 write_img(p->file_name(), p, 0);
1550
1551 double d;
1552 char* data = new char[slicesize*elementsize];
1553 Complex<float>* cfdata = new Complex<float>[slicesize];
1554
1555 fstream fmap(p->file_name().c_str());
1556 if ( fmap.fail() ) return -1;
1557
1558 for ( z=0; z<p->sizeZ(); z++ ) {
1559 offset = z*slicesize*cfsize;
1560 ftemp->seekg(offset, ios::beg);
1561 ftemp->read((char *)cfdata, cfsize*slicesize);
1562 for ( i=0; i<slicesize; i++ ) {
1563 d = cfdata[i].real()*scale + shift;
1564 if ( d < cutmin ) d = cutmin;
1565 if ( d > cutmax ) d = cutmax;
1566 set_value_with_datatype(data+i*elementsize, d, p->data_type());
1567 }
1568 offset = p->data_offset() + z*slicesize*elementsize;
1569 fmap.seekg(offset, ios::beg);
1570 fmap.write((char *)data, elementsize*slicesize);
1571 }
1572
1573 fmap.close();
1574
1575 delete[] data;
1576 delete[] cfdata;
1577
1578 return 0;
1579 }
1580
1594 Bimage* project_missing_mask(Bproject* project, Vector3<long> size,
1595 Vector3<double> origin, double hi_res, double scale)
1596 {
1597 Bfield* field = project->field;
1598 Bmicrograph* mg = field->mg;
1599
1600 if ( mg->matrix.determinant() < 0.9 )
1601 project_mg_tilt_to_matrix(project);
1602
1603 // Image to pack
1604 Bimage* pimg = new Bimage(UCharacter, TSimple, size[0], size[1], 1, 1);
1605 pimg->fill(1);
1606
1607 // Mask
1608 Bimage* pmask = new Bimage(UCharacter, TSimple, size[0], size[1], size[2], 1);
1609 pmask->sampling(mg->pixel_size/scale, mg->pixel_size/scale, mg->pixel_size/scale);
1610 if ( hi_res < 2*pmask->sampling()[0] ) hi_res = 2*pmask->sampling()[0];
1611
1612 // if ( verbose & VERB_PROCESS ) {
1613 if ( verbose ) {
1614 cout << "Generating a 3D reciprocal space mask from a tilt series:" << endl;
1615 cout << "Mask size: " << pmask->sizeX() << " " << pmask->sizeY() << " " << size[2] << endl;
1616 cout << "Origin: " << origin << endl;
1617 cout << "Resolution limit: " << hi_res << " A" << endl;
1618 cout << "Scale: " << scale << endl;
1619 }
1620
1621 for ( mg=field->mg; mg; mg=mg->next ) if ( mg->select ) {
1622
1623 pmask->mask_pack_plane(mg->matrix, hi_res, scale);
1624
1625 }
1626
1627 delete pimg;
1628
1629 Vector3<long> shift((long) -(origin[0]+0.5), (long) -(origin[1]+0.5), (long) -(origin[2]+0.5));
1630 pmask->shift_wrap(shift);
1631
1632 pmask->statistics();
1633
1634 return pmask;
1635 }
1636
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bimage::mask_pack_plane
long mask_pack_plane(Matrix3 mat, double hi_res, double scale)
Packs a 2D mask into a 3D reciprocal space volume.
Definition: Bimage_mask.cpp:1247
Bparticle::id
int id
Definition: mg_processing.h:92
Bimage::compatible
bool compatible(Bimage *p)
Check if this image has the same number of channels and data type as another.
Definition: Bimage.cpp:623
Matrix3::determinant
double determinant()
Definition: Matrix3.h:260
Bproject::rec
Breconstruction * rec
Definition: mg_processing.h:344
Bfield::select
long select
Definition: mg_processing.h:262
DataType
DataType
Base data type specifier.
Definition: utilities.h:146
Bparticle::view
View view
Definition: mg_processing.h:101
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
Vector3::length
double length()
Definition: Vector3.h:222
img_clear_extraneous_areas
int img_clear_extraneous_areas(Bimage *p, double tilt_axis, double tilt_angle, long thickness)
Clears areas from a micrograph not used in a reconstruction.
Definition: mg_tomo_rec.cpp:937
Breconstruction::part
Bparticle * part
Definition: mg_processing.h:304
Bimage::add
void add(long j, double v)
Definition: Bimage.h:308
project_tomo_reconstruct
Bimage * project_tomo_reconstruct(Bproject *project, double hi_res, double scale, Vector3< long > size, int interp_type, int pad_factor, double edge_width, double marker_radius, int fill_type, double fill, int action, double wiener)
Reciprocal space reconstruction from the images in a multi-image file.
Definition: mg_tomo_rec.cpp:113
Bmicrograph::id
Bstring id
Definition: mg_processing.h:202
Bmicrograph::img_num
int img_num
Definition: mg_processing.h:211
SMALLFLOAT
#define SMALLFLOAT
Definition: utilities.h:45
img_backtransform_slices
int img_backtransform_slices(Bimage *p)
Backtransforms 2D slices in a 3D volume.
Definition: mg_tomo_rec.cpp:731
Bimage::data_type_size
long data_type_size() const
Returns the size of the datatype in bytes.
Definition: Bimage.cpp:1585
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.
Bimage::shift_wrap
int shift_wrap(Vector3< double > vec)
Shifts an image.
Definition: Bimage_transform.cpp:643
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
img_phase_shift_slab_to_origin
int img_phase_shift_slab_to_origin(Bimage *p, int zsize, int slab_start)
Phase shifts a set of reflections to the image origin.
Definition: mg_tomo_rec.cpp:891
Bimage::compound_type
CompoundType compound_type()
Definition: Bimage.h:351
mg_tomo_rec_prepare
Bimage * mg_tomo_rec_prepare(Bmicrograph *mg, int ft_size, long thickness, double edge_width, double marker_radius, int fill_type, double fill, int action, double wiener, Vector3< long > tile_size, fft_plan plan)
Definition: mg_tomo_rec.cpp:30
Integer
Definition: utilities.h:154
Complex.h
Class for complex numbers.
Bmarker
Definition: marker.h:21
Matrix3
Definition: Matrix3.h:17
FILL_AVERAGE
#define FILL_AVERAGE
Definition: utilities.h:173
Bstring::length
long length() const
Definition: Bstring.cpp:263
Bmicrograph::pixel_size
double pixel_size
Definition: mg_processing.h:214
project
Bproject * project
Definition: bshow.cpp:31
count_list
long count_list(char *list)
Counts the number of items in a linked list.
Definition: linked_list.cpp:235
particle_count
long particle_count(Bparticle *part)
Counts the number of particles in a linked list.
Definition: mg_processing.cpp:1151
particle_kill
int particle_kill(Bparticle *part)
Frees a list of particles.
Definition: mg_processing.cpp:1323
Bimage::complex
Complex< double > complex(long j)
Returns a complex value at the given index.
Definition: Bimage.cpp:1005
SCharacter
Definition: utilities.h:150
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bimage::file_name
void file_name(string s)
Definition: Bimage.h:230
project_missing_mask
Bimage * project_missing_mask(Bproject *project, Vector3< long > size, Vector3< double > origin, double hi_res, double scale)
Creates a reciprocal space mask from the tilt series orientations.
Definition: mg_tomo_rec.cpp:1594
mg_ctf.h
Functions for CTF (contrast transfer function) processing.
Long
Definition: utilities.h:156
TComplex
Definition: Bimage.h:59
Bmicrograph::tilt_angle
double tilt_angle
Definition: mg_processing.h:217
Breconstruction::box_size
Vector3< long > box_size
Definition: mg_processing.h:296
read_img
Bimage * read_img(char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:76
img_write_data_block_with_type
int img_write_data_block_with_type(fstream *ftemp, Bimage *p, double avg, double std, double cutmin, double cutmax)
Definition: mg_tomo_rec.cpp:1498
Bfield::next
Bfield * next
Definition: mg_processing.h:258
Bmicrograph::part
Bparticle * part
Definition: mg_processing.h:239
TSimple
Definition: Bimage.h:58
timer.h
Utilities for timing functions.
Bimage::data_type_max
double data_type_max()
Get the maximum of a datatype.
Definition: Bimage.cpp:1641
Float
Definition: utilities.h:157
Vector3::max
Type max()
Definition: Vector3.h:175
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
Bmicrograph::matrix
Matrix3 matrix
Definition: mg_processing.h:222
Bimage
General image parameter class.
Definition: Bimage.h:163
UInteger
Definition: utilities.h:153
Bmicrograph::tilt_axis
double tilt_axis
Definition: mg_processing.h:216
Bimage::data_alloc
unsigned char * data_alloc()
Definition: Bimage.h:256
verbose
int verbose
Bstring::contains
bool contains(const Bstring &s)
Definition: Bstring.cpp:584
Bfield
Definition: mg_processing.h:257
linked_list.h
Header file for generalized linked list functions.
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
img_backtransform_one_y_plane
int img_backtransform_one_y_plane(Bimage *p, fft_plan plan, int y)
Definition: mg_tomo_rec.cpp:1263
Bimage::correct_background
int correct_background(long nn, int flag)
Corrects the background for one sub-image.
Definition: Bimage_background.cpp:202
Bimage::maximum
double maximum()
Definition: Bimage.h:535
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
Double
Definition: utilities.h:158
Bimage::statistics
long statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
Bstring::next
Bstring * next
Definition: Bstring.h:31
Bmicrograph::select
long select
Definition: mg_processing.h:203
Bmicrograph::mark_radius
double mark_radius
Definition: mg_processing.h:235
Bimage::sphere
int sphere(Vector3< double > center, double radius, double width=0, int fill_type=0, double fill=0)
Fills a sphere within an image with a uniform value.
Definition: Bimage_edit.cpp:438
Bimage::label
void label(string s)
Definition: Bimage.h:235
Bproject::field
Bfield * field
Definition: mg_processing.h:343
VERB_TIME
#define VERB_TIME
Definition: utilities.h:110
img_pack_2D_in_recip_space_slab
long img_pack_2D_in_recip_space_slab(Bimage *p, Bimage *prec, long zsize, long slab_start, float *weight, float *weight2, double hi_res, Matrix3 mat, double scale)
Packs a 2D Fourier transform into a 3D reciprocal space volume.
Definition: mg_tomo_rec.cpp:782
ULong
Definition: utilities.h:155
fft_plan
fftwf_plan fft_plan
Definition: fft.h:16
Standard
Definition: Bimage.h:41
Bsub_image::FOM
double FOM()
Definition: Bimage.h:151
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
project_mg_tilt_to_matrix
int project_mg_tilt_to_matrix(Bproject *project)
Sets the matrix from the tilt and axis angles for each micrograph.
Definition: mg_tomography.cpp:1960
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
Bmicrograph
Definition: mg_processing.h:200
mg_tomography.h
Header file for single particle image processing in Bsoft.
project_tomo_reconstruct_particles
long project_tomo_reconstruct_particles(Bproject *project, double resolution, int interp_type, int pad_factor, int ctf_action, double wiener, Bsymmetry *sym, Bstring &partbase, Bstring &partpath, Bstring &partext)
Reconstructs particles from a tilt series.
Definition: mg_tomo_rec.cpp:604
Bmicrograph::origin
Vector3< double > origin
Definition: mg_processing.h:220
write_img
int write_img(const char *filename, Bimage *p, int compression)
General driver function to write multiple image formats.
Definition: rwimg.cpp:280
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
Bimage::data_offset
long data_offset()
Definition: Bimage.h:265
Bparticle::fpart
Bstring fpart
Definition: mg_processing.h:91
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:127
Bparticle::ori
Vector3< double > ori
Definition: mg_processing.h:100
Bimage::channels
long channels()
Definition: Bimage.h:371
Vector3::length2
double length2()
Definition: Vector3.h:221
Bimage::fspace_reconstruction_weigh
long fspace_reconstruction_weigh()
Weighs a reconstruction.
Definition: Bimage_reconstruct.cpp:412
Bstring::c_str
const char * c_str()
Definition: Bstring.h:70
Bmicrograph::mark
Bmarker * mark
Definition: mg_processing.h:242
memory_check
int memory_check(long mem_required)
Checking if there is enough memory, abort if not.
Definition: utilities.cpp:248
Bmarker::next
Bmarker * next
Definition: marker.h:22
Bimage::standard_deviation
double standard_deviation()
Definition: Bimage.h:537
Bstring::post_rev
Bstring post_rev(char c)
Definition: Bstring.cpp:428
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
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::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
mg_erase_markers
Bimage * mg_erase_markers(Bmicrograph *mg, double marker_radius)
Erases or paints markers in micrographs.
Definition: mg_tomography.cpp:1038
Complex
Definition: Complex.h:23
MIN2PI
#define MIN2PI
Definition: utilities.h:71
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:261
mg_fft_write
int mg_fft_write(Bproject *project, Vector3< int > size, double scale, int pad_factor, Bstring &label, DataType datatype, double marker_radius, int fill_type, double fill)
Fourier transform micrographs and write to disk.
Definition: mg_tomo_rec.cpp:986
Bparticle
Definition: mg_processing.h:89
UCharacter
Definition: utilities.h:149
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::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
Bmicrograph::fft
Bstring fft
Definition: mg_processing.h:209
Bit
Definition: utilities.h:148
Bmicrograph::box_size
Vector3< long > box_size
Definition: mg_processing.h:230
gettypesize
long gettypesize(DataType type)
Get the size of a datatype.
Definition: mg_tomo_rec.cpp:1407
Bimage::sizeZ
void sizeZ(long nz)
Definition: Bimage.h:379
Vector3< long >
Bmicrograph::fmg
Bstring fmg
Definition: mg_processing.h:205
fft_destroy_plan
int fft_destroy_plan(fft_plan plan)
Deallocates a plan for fast Fourier transforms.
Definition: fft.cpp:87
timer_report
double timer_report(double lasttime)
Reports the time elapsed since a given time.
Definition: timer.cpp:67
mg_tomo_rec.h
Functions to do a tomographic reconstruction.
View
Definition: View.h:26
Bmarker::loc
Vector3< float > loc
Definition: marker.h:25
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
particle_tomo_reconstruct
long particle_tomo_reconstruct(Bproject *project, Bparticle *recpart, Vector3< long > recsize, double resolution, int interp_type, long ft_size, double scale, fft_plan planp, fft_plan planr, int ctf_action, double wiener, Bsymmetry *sym, Bstring &partbase, Bstring &partpath, Bstring &partext)
Reconstructs individual particles from a tilt series.
Definition: mg_tomo_rec.cpp:518
micrograph_clear_extraneous_areas
int micrograph_clear_extraneous_areas(Bmicrograph *mg, Bimage *p, long thickness, double width)
Clears extraneous areas from a micrograph.
Definition: mg_tomography.cpp:2015
fftw
int fftw(fft_plan plan, Complex< float > *a)
Fast Fourier transforms a data array.
Definition: fft.cpp:106
Bimage::average
double average(long cc, double xf, double yf, double zf, long nn, double iscale)
Averages in 3D when scaling is less than 1.
Definition: Bimage.cpp:1349
project_fourier_reconstruction_slab
Bimage * project_fourier_reconstruction_slab(Bproject *project, double hi_res, double scale, Vector3< long > size, int slab_start, int slab_end, double marker_radius, int fill_type, double fill, int action, double wiener)
Reciprocal space reconstruction from the images in a multi-image file.
Definition: mg_tomo_rec.cpp:299
Short
Definition: utilities.h:152
img_ttf_apply
int img_ttf_apply(Bimage *p, CTFparam ctf, int action, double wiener, Vector3< long > tile_size, double tilt, double axis, double res_lo, double res_hi)
Applies or corrects for the tilted contrast transfer function (TTF).
Definition: mg_ctf.cpp:388
Breconstruction::voxel_size
double voxel_size
Definition: mg_processing.h:292
Unknown_Type
Definition: utilities.h:147
set_value_with_datatype
int set_value_with_datatype(char *ptr, double value, DataType datatype)
Set a pointer to a value with a given data type.
Definition: mg_tomo_rec.cpp:1437
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=0, int ctf_action=0, double wiener=0.2, int twoD_flag=0, int bootstrap=0, int first=0)
Reciprocal space reconstruction from 2D particle images.
Definition: mg_reconstruct.cpp:99
Complex::real
Type real()
Definition: Complex.h:101
UShort
Definition: utilities.h:151
img_backtransform_z_lines
int img_backtransform_z_lines(fstream *ftemp, Bimage *p)
Definition: mg_tomo_rec.cpp:1362
Bimage::images
long images()
Definition: Bimage.h:491
NoTransform
Definition: Bimage.h:40
Bimage::fill
void fill(double v)
Definition: Bimage.h:698
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
Bstring::empty
bool empty()
Definition: Bstring.h:71
img_backtransform_z_on_disk
Bimage * img_backtransform_z_on_disk(Bstring *file_list, Bstring &recfile, DataType datatype, Bstring &label, double avg, double std, double cutmin, double cutmax)
The lines along the z-dimensions of a disk-based block is Fourier back-transformed.
Definition: mg_tomo_rec.cpp:1184
Vector3::volume
double volume()
Definition: Vector3.h:235
Bparticle::next
Bparticle * next
Definition: mg_processing.h:90
VERB_FULL
#define VERB_FULL
Definition: utilities.h:109
Bimage::background
double background(long nn)
Definition: Bimage.h:542
Bimage::sizeY
void sizeY(long ny)
Definition: Bimage.h:378
Bimage::data_type
DataType data_type()
Definition: Bimage.h:349
Bstring::str
string str()
Definition: Bstring.h:42
Bimage::pad_copy
Bimage * pad_copy(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:392
Bimage::minimum
double minimum()
Definition: Bimage.h:534
bexit
int bexit(int value)
Exit function for cleanup and debugging.
Definition: utilities.cpp:273
Breconstruction::next
Breconstruction * next
Definition: mg_processing.h:281
img_extract_ytile
Bimage * img_extract_ytile(Bstring *file_list, int ystart, int ysize)
Extracts a tile from the image with limits in y.
Definition: mg_tomo_rec.cpp:1082
Bimage::data_type_min
double data_type_min()
Get the minimum of a datatype.
Definition: Bimage.cpp:1611
timer_start
double timer_start()
Starts timer and prints the time.
Definition: timer.cpp:52
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
Bproject
Definition: mg_processing.h:333
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:563
Breconstruction::id
Bstring id
Definition: mg_processing.h:282
Bmicrograph::next
Bmicrograph * next
Definition: mg_processing.h:201