| Bsoft 2.0.5 Bernard's software package

mg_subtomo.cpp
Go to the documentation of this file.
1
17 #include "Bimage.h"
18 #include "mg_subtomo.h"
19 #include "rwimg.h"
20 #include "mg_processing.h"
21 #include "linked_list.h"
22 #include "utilities.h"
23
24 // Declaration of global variables
25 extern int verbose; // Level of output to the screen
26
27 // It creates two temporary images the size of the input image - usually a tomogram
28 // A rotated template
29 // The cross correlation map
30 Bparticle* img_search_view(Bimage* p, Bimage* ptemp, Bimage* pmask, View view,
31 double hires, double lores, double shiftlimit, double mindist,
32 double threshold, int maxhits, int refinepeaks,
33 fft_plan planf, fft_plan planb)
34 {
35 // View corresponds to a rotation matrix that takes the particle to the standard orientation
36 // need to transpose this matrix to rotate the template from the standard orientation on the particle
37 Matrix3 mat = view.matrix();
38 mat = mat.transpose();
39
40 // Transform the template to the box with size of the reconstruction
41 Bimage* ptemprot = ptemp->rotate(p->size(), mat);
42
43 // Correlate the template and the map
44 Bimage* pcc = ptemprot->cross_correlate(p, hires, lores, pmask, planf, planb);
45
46 delete ptemprot;
47
48 Bparticle* goodpeaks = img_find_refine_peaks(pcc, view, shiftlimit, 0, 0,
49 mindist, threshold, maxhits, refinepeaks);
50
51 delete pcc;
52
53 return goodpeaks;
54 }
55
56 // It creates three temporary images the size of the template image
57 // A cropped input image
58 // An optional real space mask to apply to the cropped input image - deleted before generating more images
59 // A rotated template
60 // The cross correlation map
61 Bparticle* img_refine_view(Bimage* pcrop, Bimage* ptemp, Bimage* pmask, Bimage* pmask2,
62 View view, double hires, double lores, double shiftlimit,
63 double shiftlimitz, double shiftlimitxy, double mindist, int refinepeaks,
64 fft_plan planf, fft_plan planb)
65 {
66 // Vector3<double> scale(1,1,1), trans;
67
68 // View corresponds to a rotation matrix that takes the particle to the standard orientation
69 // need to transpose this matrix to rotate the template from the standard orientation on the particle
70 Matrix3 mat = view.matrix();
71 mat = mat.transpose();
72
73 Bimage* pcropmasked = pcrop->copy();
74
75 // Rotate the real space mask to the current view
76 if ( pmask2 ) {
77 Bimage* pmask2rot = pmask2->rotate(pmask2->size(), mat);
78 pcropmasked->multiply(pmask2rot);
79 delete pmask2rot;
80 }
81
82 // Rotate the template to the current view
83 Bimage* ptemprot = ptemp->rotate(ptemp->size(), mat);
84
85 // Correlate the template and the map
86 Bimage* pcc = ptemprot->cross_correlate(pcropmasked, hires, lores, pmask, planf, planb);
87
88 delete ptemprot;
89 delete pcropmasked;
90
91 Bparticle* peak = NULL;
92 long i(0);
93
94 // If no shift allowed, just return the CCC at the origin
95 if ( shiftlimit == 0 && shiftlimitz == 0 && shiftlimitxy == 0) {
96 peak = particle_add(&peak, 1);
97 peak->view = view;
98 peak->fom[0] = (*pcc)[i];
99 }
100 // Shifts allowed so the hit is looked around origin, with the radius of shiftlimit, or within a cylinder
101 else {
102 peak = img_find_refine_peaks(pcc, view,
103 shiftlimit, shiftlimitz, shiftlimitxy,
104 mindist, -1, -1, refinepeaks);
105 }
106
107 delete pcc;
108
109 return peak;
110 }
111
112 /************************************************************************
113 @brief Searches a 3D density map for a template
114 @author Juha Huiskonen
115 @param *rec reconstruction parameters.
116 @param *p the image.
117 @param *ptemp the template to be searched for.
118 @param *pmask reciprocal space mask for cross-correlation (ignored if NULL).
119 @param *pmask2 real space mask for cross-correlation (ignored if NULL).
120 @param alpha_step angular step size around view vector (radians).
121 @param theta_step angular step size around view vector (radians).
122 @param phi_step angular step size around view vector (radians).
123 @param angle_limit angular limit for refinement in alpha (radians).
124 @param thetaphi_limit angular limit for refinement in theta & phi (radians).
125 @param hires high resolution limit.
126 @param lores low resolution limit.
127 @param shiftlimit maximum shift from the original position (binned units).
128 @param mindist minimun distance for cc peaks (binned units).
129 @param maxhits maximum number of hits
130 @param bin binning for map, template and mask
131 @param *sym symmetry to generate a list of views for search mode
132 @param refinepeaks flag to run several iterations in refine
133 @param ccmax_file file for cross-correlation map (max ccc for each position and rotation of the template)
134 @return double the best correlation coefficient.
135
136 The template is rotated and cross-correlated to find fits above the
137 threshold.
138
139 **/
140 long reconstruction_search_subtomo(Breconstruction* rec,
141 Bimage* p, Bimage* ptemp, Bimage* pmask, Bimage* pmask2,
142 double alpha_step, double theta_step, double phi_step,
143 double alpha_limit, double thetaphi_limit,
144 double hires, double lores, double shiftlimit, double mindist,
145 double threshold, int maxhits, Vector3<long> bin, Bsymmetry* sym,
146 int refinepeaks, Bstring ccmax_file)
147 {
148 if ( !pmask ) { cerr << "Warning: No reciprocal space mask given." << endl; }
149 if ( !pmask2 ) { cerr << "Warning: No real space mask given." << endl; }
150
151 // Search whole rec by default
152 if ( shiftlimit < 0 ) {
153 if ( verbose & VERB_PROCESS )
154 cout << endl << "Shift limit not specified, searching the whole reconstruction." << endl;
155 shiftlimit = p->size().length()/2;
156 }
157
158 // Minimum distance between ccc peaks is the size of the template by default
159 if ( mindist <= 0 ) { mindist = 2*ptemp->maximum_included_radius(); }
160
161 // Clear any previous particle records
162 if ( rec->part ) particle_kill(rec->part);
163 rec->fpart = 0;
164 rec->part = NULL;
165
166 // Origin of the template (already binned units)
167 Vector3<double> origin = ptemp->image->origin();
168
169 // Normalize and mask template
170 if ( verbose & VERB_PROCESS ) { cout << endl << "Normalizing the template." << endl; }
171 ptemp->rescale_to_avg_std(0, 1);
172
173 if ( pmask2 ) {
174 if ( verbose & VERB_PROCESS ) { cout << endl << "Masking the template." << endl; }
175 ptemp->multiply(pmask2);
176 }
177
178 // Normalize map
179 if ( verbose & VERB_PROCESS ) { cout << endl << "Normalizing the map." << endl; }
180 p->rescale_to_avg_std(0, 1);
181
182 // Search mode
183 if ( verbose & VERB_PROCESS ) { cout << endl << "Running in search mode." << endl; }
184 cout << endl;
185
186 // Views to consider in Search
187 View refview;
188 View* allviews = NULL; // all views for search/refinement
189 if ( sym->point < 102 ) {
190 allviews = views_within_limits(refview, theta_step, phi_step, alpha_step, thetaphi_limit, alpha_limit);
191 } else {
192 allviews = asymmetric_unit_views(sym, theta_step, phi_step, alpha_step, 1);
193 }
194
195 long nviews = count_list((char *)allviews);
196
197 // if ( verbose & VERB_PROCESS ) {
198 if ( verbose ) {
199 cout << "Searching for the template in the map:" << endl;
200 cout << "Map: " << p->file_name() << endl;
201 cout << "Template: " << ptemp->file_name() << endl;
202 cout << "Map size: " << p->size() << endl;
203 cout << "Template size: " << ptemp->size() << endl;
204 cout << "Template origin: " << setprecision(4) << origin << endl;
205 cout << "Binning: " << bin << endl;
206 cout << "Search radius: " << shiftlimit << endl;
207 cout << "Minimum separation distance: " << mindist << endl;
208 if ( pmask2)
209 cout << "Real space mask: " << pmask2->file_name() << endl;
210 if ( pmask )
211 cout << "Reciprocal space mask: " << pmask->file_name() << endl;
212 cout << "Alpha step size: " << alpha_step*180.0/M_PI << " degrees" << endl;
213 cout << "Theta step size: " << theta_step*180.0/M_PI << " degrees" << endl;
214 cout << "Phi step size: " << phi_step*180.0/M_PI << " degrees" << endl;
215 cout << "Limit in alpha: " << alpha_limit*180.0/M_PI << " degrees" << endl;
216 if ( sym )
217 cout << "Symmetry: " << sym->label << endl;
218 else
219 cout << "Limit in theta & phi: " << thetaphi_limit*180.0/M_PI << " degrees" << endl;
220 cout << "Number of views: " << nviews << endl;
221 if ( ccmax_file.length() )
222 cout << "Cross correlation map: " << ccmax_file << endl;
223 cout << endl;
224 }
225
226 if ( pmask )
227 pmask->mask_fspace_resize(p->size());
228
229 long i, ipart(0);
230 View* v = NULL;
231 View* view_arr = new View[nviews];
232 for ( i=0, v=allviews; v; v=v->next, i++ ) view_arr[i] = *v;
233
234 Bparticle* part = NULL;
235 Bparticle** part_arr = new Bparticle*[nviews];
236
237 fft_plan planf = p->fft_setup(FFTW_FORWARD, 1);
238 fft_plan planb = p->fft_setup(FFTW_BACKWARD, 1);
239
240 if ( verbose & VERB_RESULT )
241 cout << "#\tViewX\tViewY\tViewZ\tViewA\tNpart" << endl;
242
243 // Loop through all views for the current particle and iteration
244 #ifdef HAVE_GCD
245 dispatch_queue_t myq = dispatch_queue_create(NULL, NULL);
246 dispatch_apply(nviews, dispatch_get_global_queue(0, 0), ^(size_t i){
247 part_arr[i] = img_search_view(p, ptemp, pmask, view_arr[i], hires, lores,
248 shiftlimit, mindist, threshold, maxhits, refinepeaks, planf, planb);
249 long np = count_list((char *) part_arr[i]);
250 dispatch_sync(myq, ^{
251 if ( verbose & VERB_RESULT )
252 cout << i+1 << tab << view_arr[i] << tab << np << endl << flush;
253 });
254 });
255 #else
256 #pragma omp parallel for
257 for ( long i=0; i < nviews; i++ ) {
258 part_arr[i] = img_search_view(p, ptemp, pmask, view_arr[i], hires, lores,
259 shiftlimit, mindist, threshold, maxhits, refinepeaks, planf, planb);
260 long np = count_list((char *) part_arr[i]);
261 #pragma omp critical
262 {
263 if ( verbose & VERB_RESULT )
264 cout << i+1 << tab << view_arr[i] << tab << np << endl << flush;
265 }
266 }
267 #endif
268
269 fft_destroy_plan(planf);
270 fft_destroy_plan(planb);
271
272 if ( verbose )
273 cout << "Transferring the particles found to the reconstruction" << endl;
274 for ( i=0; i < nviews; i++ ) if ( part_arr[i] ) {
275 if ( !rec->part ) rec->part = part = part_arr[i];
276 else part->next = part_arr[i];
277 for ( ; part->next; part = part->next ) ;
278 }
279
280 Vector3<double> translate;
281
282 for ( ipart=0, part = rec->part; part; part = part->next ) {
283 part->id = ++ipart;
284 part->ori = origin * bin;
285 translate = origin - part->loc;
286 translate = vector3_set_PBC(translate, p->size());
287 part->loc = translate * bin;
288 if ( verbose & VERB_FULL )
289 cout << ipart << tab << setprecision(2)
290 << part->loc << tab << setprecision(4) << part->view << tab << part->fom[0] << endl;
291 }
292
293 kill_list((char *) allviews, sizeof(View));
294 delete[] view_arr;
295 delete[] part_arr;
296
297 if ( rec->box_size.volume() < 1 )
298 rec->box_size = ptemp->size() * bin;
299
300 return particle_count(rec->part);
301 }
302
333 long reconstruction_refine_subtomo(Breconstruction* rec,
334 Bimage* p, Bimage* ptemp, Bimage* pmask, Bimage* pmask2,
335 double alpha_step_orig, double theta_step_orig, double phi_step_orig,
336 double alpha_limit_orig, double thetaphi_limit_orig,
337 double hires, double lores, double shiftlimit_orig,
338 double shiftlimitz_orig, double shiftlimitxy_orig, double mindist,
339 Vector3<long> bin, Bsymmetry* sym, int iters, int refinepeaks, Bstring ccmax_file)
340 {
341 if ( !pmask ) { cerr << "Warning: No reciprocal space mask given." << endl; }
342 if ( !pmask2 ) { cerr << "Warning: No real space mask given." << endl; }
343
344 // Refine shifts within 1/2 template by default
345 if ( shiftlimit_orig < 0 ) {
346 if ( verbose & VERB_PROCESS )
347 cout << endl << "Shift limit not specified, using half the size of the template." << endl;
348 shiftlimit_orig = ptemp->maximum_included_radius();
349 }
350
351 if ( mindist <= 0 ) { mindist = 2*ptemp->maximum_included_radius(); }
352
353 // Normalize and mask template
354 if ( verbose & VERB_PROCESS ) { cout << endl << "Normalizing the template." << endl; }
355 ptemp->rescale_to_avg_std(0, 1);
356
357 if ( pmask2 ) {
358 if ( verbose & VERB_PROCESS ) { cout << endl << "Masking the template." << endl; }
359 ptemp->multiply(pmask2);
360 }
361
362 // Normalize map
363 if ( verbose & VERB_PROCESS ) { cout << endl << "Normalizing the map." << endl; }
364 p->rescale_to_avg_std(0, 1);
365
366 // Refine mode
367 if ( verbose & VERB_PROCESS ) { cout << "Running in refine mode" << endl; }
368
369 if ( sym->point > 101 && iters > 1) {
370 iters = 1;
371 cerr << "Warning: Symmetry selected, running only one iteration." << endl;
372 }
373
374 if ( verbose & VERB_RESULT ){ cout << endl << "Padding the template to a larger box." << endl;}
375
376 double maxshift = shiftlimit_orig + shiftlimitz_orig + shiftlimitxy_orig;
377
378 // Origin of the template (already binned units)
379 Vector3<double> origin = ptemp->image->origin();
380
381 Vector3<double> scale(1,1,1);
382 Vector3<double> translate = Vector3<double>(maxshift,maxshift,maxshift);
383 View refview;
384 Matrix3 mat = refview.matrix();
385 Vector3<long> ptempsize = ptemp->size() + Vector3<long>(2*(long)maxshift, 2*(long)maxshift, 2*(long)maxshift);
386 ptemp->resize(ptempsize, translate, FILL_BACKGROUND, 0);
387 ptemp->origin(origin+translate);
388 Vector3<double> neworigin = ptemp->image->origin();
389
390 if ( pmask )
391 pmask->mask_fspace_resize(p->size());
392
393 if ( pmask2 ) {
394 if ( verbose & VERB_RESULT ){ cout << endl << "Padding the real space mask to a larger box." << endl;}
395 pmask2->resize(ptempsize, translate, FILL_BACKGROUND, 0);
396 }
397
398 if ( verbose ) {
399 cout << endl << "Refining the template in the map around the starting view:" << endl;
400 cout << "Map: " << p->file_name() << endl;
401 cout << "Template: " << ptemp->file_name() << endl;
402 cout << "Map size: " << p->size() << endl;
403 cout << "Template size: " << ptemp->size() << endl;
404 cout << "Template origin: " << setprecision(4) << ptemp->image->origin() << endl;
405 cout << "Binning: " << bin << endl;
406 cout << "Maximum translation: " << shiftlimit_orig << " pixels" << endl;
407 if ( shiftlimitz_orig > 0 )
408 cout << "Additional shift along view: " << shiftlimitz_orig << endl;
409 if ( shiftlimitxy_orig > 0 )
410 cout << "Additional shift orthogonal view: " << shiftlimitxy_orig << endl;
411 if ( pmask2)
412 cout << "Real space mask: " << pmask2->file_name() << endl;
413 if ( pmask )
414 cout << "Reciprocal space mask: " << pmask->file_name() << endl;
415 cout << "Alpha step size: " << alpha_step_orig*180.0/M_PI << " degrees" << endl;
416 cout << "Theta step size: " << theta_step_orig*180.0/M_PI << " degrees" << endl;
417 cout << "Phi step size: " << phi_step_orig*180.0/M_PI << " degrees" << endl;
418 cout << "Limit in alpha: " << alpha_limit_orig*180.0/M_PI << " degrees" << endl;
419 if ( sym->point < 102 )
420 cout << "Limit in theta & phi: " << thetaphi_limit_orig*180.0/M_PI << " degrees" << endl;;
421 cout << endl;
422 }
423
424 long iter, nviews, i, ibest(0);
425 long npart = particle_count(rec->part);
426 double shiftlimit, shiftlimitz, shiftlimitxy;
427 double alpha_step,theta_step,phi_step;
428 double alpha_limit, thetaphi_limit;
429 double best_cc;
430 Vector3<double> bestshift;
431 View bestview;
432 View* v = NULL;
433 View* allviews = NULL;
434 Bparticle* part = NULL;
435 Bimage* pcrop = NULL;
436
437 fft_plan planf = fft_setup_plan(ptempsize, FFTW_FORWARD, 1);
438 fft_plan planb = fft_setup_plan(ptempsize, FFTW_BACKWARD, 1);
439
440 for ( part = rec->part; part; part = part->next ) if ( part->sel > 0 ) {
441
442 if ( verbose )
443 cout << "Particle: " << part->id << " of " << npart << endl;
444
445 if ( verbose & VERB_PROCESS ) {
446 cout << "Starting location: " << part->loc << endl;
447 cout << "Starting view: " << part->view << endl;
448 }
449
450
451 // Reset angle step sizes to originals for the current particle (halved after each iteration)
452 alpha_step = alpha_step_orig;
453 theta_step = theta_step_orig;
454 phi_step = phi_step_orig;
455 thetaphi_limit = thetaphi_limit_orig;
456 alpha_limit = alpha_limit_orig;
457 shiftlimit = shiftlimit_orig;
458 shiftlimitxy = shiftlimitxy_orig;
459 shiftlimitz = shiftlimitz_orig;
460
461 // The initially best view is the given view
462 bestview = part->view;
463
464 for ( iter=1; iter <= iters; iter++) {
465
466 // Views around the current best view to consider in refinement
467 if ( sym->point < 102 ) {
468 allviews = views_within_limits(bestview, theta_step, phi_step, alpha_step, thetaphi_limit, alpha_limit);
469 } else {
470 allviews = asymmetric_unit_views(sym, theta_step, phi_step, alpha_step, 1);
471 }
472
473 nviews = count_list((char *)allviews);
474
475 if ( verbose & VERB_PROCESS ) {
476 cout << "Iteration: " << iter << " of " << iters << endl;
477 cout << "Alpha step size: " << alpha_step*180.0/M_PI << " degrees" << endl;
478 cout << "Theta step size: " << theta_step*180.0/M_PI << " degrees" << endl;
479 cout << "Phi step size: " << phi_step*180.0/M_PI << " degrees" << endl;
480 cout << "Limit in alpha: " << alpha_limit*180.0/M_PI << " degrees" << endl;
481 if ( sym->point < 102 )
482 cout << "Limit in theta & phi: " << thetaphi_limit*180.0/M_PI << " degrees" << endl;;
483 cout << "Number of views: " << nviews << endl;
484 cout << endl;
485 }
486
487 // Crop reconstruction to the same size of a box as the template using the refined location
488 if ( verbose & VERB_FULL ){ cout << endl << "Cropping the map." << endl << endl;}
489 translate = -part->loc;
490 if ( bin[0] ) { translate /= bin; }
491 translate = translate + neworigin;
492 mat = refview.matrix();
493 pcrop = p->transform(ptempsize, scale, Vector3<double>(0,0,0), translate, mat, FILL_BACKGROUND, 0);
494
495 // Normalize cropped map
496 pcrop->rescale_to_avg_std(0, 1);
497 pcrop->origin(Vector3<double>(0,0,0));
498
499 // Since we are contracting around the previous best point, the best orientation is always found from the current views
500 best_cc = -1;
501
502 View* view_arr = new View[nviews];
503 for ( i=0, v=allviews; v; v=v->next, i++ ) view_arr[i] = *v;
504
505 Bparticle** part_arr = new Bparticle*[nviews];
506
507 #ifdef HAVE_GCD
508 dispatch_apply(nviews, dispatch_get_global_queue(0, 0), ^(size_t i){
509 part_arr[i] = img_refine_view(pcrop, ptemp, pmask, pmask2, view_arr[i],
510 hires, lores, shiftlimit, shiftlimitz, shiftlimitxy,
511 mindist, refinepeaks, planf, planb);
512 });
513 #else
514 #pragma omp parallel for
515 for ( i=0; i < nviews; i++ ) {
516 part_arr[i] = img_refine_view(pcrop, ptemp, pmask, pmask2, view_arr[i],
517 hires, lores, shiftlimit, shiftlimitz, shiftlimitxy,
518 mindist, refinepeaks, planf, planb);
519 }
520 #endif
521
522 for ( i=0; i < nviews; i++ ) {
523 if ( part_arr[i]->fom[0] > best_cc ) {
524 best_cc = part_arr[i]->fom[0];
525 ibest = i;
526 bestview = part_arr[i]->view;
527 bestshift = part_arr[i]->loc;
528 }
529 particle_kill(part_arr[i]);
530 }
531
532 delete[] view_arr;
533 delete[] part_arr;
534
535 translate = -bestshift;
536
537 // wrap translation vectors (still working with binned units)
538 translate = vector3_origin_to_shift(translate, pcrop->size());
539
540 // Half the angle steps angle limits and shift limits for the next iteration
541 alpha_step /= 2;
542 theta_step /= 2;
543 phi_step /= 2;
544 alpha_limit /= 2;
545 thetaphi_limit /= 2;
546 shiftlimit /= 2;
547 shiftlimitz /= 2;
548 shiftlimitxy /= 2;
549
550 kill_list((char *) allviews, sizeof(View));
551
552 // Take binning into account in the translation
553 if ( bin[0] ) { translate *= bin; }
554
555 // Update refined orientation and origin + fom
556 part->view = bestview;
557 part->loc = part->loc + translate;
558 part->fom[0] = best_cc;
559
560 delete pcrop;
561
562 if ( verbose )
563 cout << " \r" << flush << iter << tab << ibest+1 << tab << part->loc << tab << bestview << tab << best_cc << endl;
564
565 } // for ( iter=1; iter <= iters; iter++)
566
567 // if ( verbose )
568 // cout << endl << "Final:\t" << ibest << tab << part->loc << tab <<
569 // bestview << tab << best_cc << endl;
570
571 } // if ( part->sel > 0 )
572
573 fft_destroy_plan(planf);
574 fft_destroy_plan(planb);
575
576 if ( rec->box_size.volume() < 1 )
577 rec->box_size = ptemp->size() * bin;
578
579 return particle_count(rec->part);
580 }
581
600 Bparticle* img_find_refine_peaks(Bimage* pcc, View view, double shift_limit,
601 double shift_along, double shift_orthogonal, double mindist,
602 double threshold, int maxhits, int refinepeaks)
603 {
604 double peakcc;
605 Bparticle* goodpeaks = NULL;
606 Bparticle* peak = NULL;
607 int hits(0);
608
609 do {
610 // shift vectors are in actual pixel coordinates (no wrapping)
611 peakcc = img_find_peak_subtomo(pcc, view, shift_limit, shift_along, shift_orthogonal);
612
613 if ( refinepeaks ) { pcc->refine_peak(); }
614
615 if ( (peakcc >= threshold) || (threshold < 0) ) {
616
617 hits++;
618
619 peak = particle_add(&goodpeaks, hits);
620 peak->loc = pcc->image->origin();
621 peak->view = view;
622 peak->fom[0] = peakcc;
623
624 if ( verbose && maxhits > 1 )
625 cout << hits << tab << peak->loc << tab << view << tab << peakcc << endl;
626
627 if ( verbose & VERB_PROCESS )
628 cout << "Found a cross-correlation peak:\t" << peak->loc << tab << peakcc << endl;
629
630 // return only the global maximum
631 if (threshold < 0) { break; }
632
633 // Enough particles found
634 if (maxhits > 0 && hits >= maxhits) { break; }
635
636 }
637
638 pcc->shell_wrap(0, pcc->image->origin(), 0, mindist, 0, FILL_USER, 0);
639
640 } while ( peakcc >= threshold );
641
642 //write_img("temp_pcc.spi", pcc);
643
644 if ( hits == 0 ) {
645 if ( verbose & VERB_PROCESS )
646 cout << "No cross-correlation peaks found above the threshold (the maximum was " << peakcc << ")" << endl;
647 }
648
649 return goodpeaks;
650 }
651
667 double img_find_peak_subtomo(Bimage* p, View view, double shift,
668 double shift_along, double shift_orthogonal)
669 {
670 if ( !p->data_pointer() ) return 0;
671
672 if ( shift < 0 ) shift = 1e30;
673
674 long i(0), x, y, z;
675 long xh = p->sizeX()/2, yh = p->sizeY()/2, zh = p->sizeZ()/2;
676 double x2, y2, z2, r2;
677 double value(0), max;
678 double shift2 = shift*shift;
679 Vector3<double> peak;
680 Vector3<double> origin(0,0,0);
681 Vector3<double> point;
682 Vector3<double> endpoint1;
683 Vector3<double> endpoint2;
684 Vector3<double> closestpoint;
685
686 view = view.backward();
687
688 if ( shift_along > 0 ) {
689 endpoint1 = Vector3<double>(view[0] * shift_along, view[1] * shift_along, view[2] * shift_along);
690 endpoint2 = Vector3<double>(-view[0] * shift_along, -view[1] * shift_along, -view[2] * shift_along);
691 }
692
693 max = -1e37;
694 for ( z=0; z<p->sizeZ(); z++ ) {
695 z2 = origin[2] - z;
696 if ( z2 < -zh ) z2 += p->sizeZ();
697 if ( z2 > zh ) z2 -= p->sizeZ();
698
699 for ( y=0; y<p->sizeY(); y++ ) {
700 y2 = origin[1] - y;
701 if ( y2 < -yh ) y2 += p->sizeY();
702 if ( y2 > yh ) y2 -= p->sizeY();
703
704 for ( x=0; x<p->sizeX(); x++, i++ ) {
705 x2 = origin[0] - x;
706 if ( x2 < -xh ) x2 += p->sizeX();
707 if ( x2 > xh ) x2 -= p->sizeX();
708
709 value = (*p)[i];
710
711 if ( shift_along > 0 ) {
712 point = Vector3<double>((double)x2, (double)y2, (double)z2);
713 // squared distance to the closest point on the line segment
714 r2 = closest_point_line_distance2(point, endpoint1, endpoint2);
715 }
716 else if ( shift_orthogonal > 0 ) {
717 point = Vector3<double>((double)x2, (double)y2, (double)z2);
718 // squared distance to the closest point on the disc
719 r2 = closest_point_disc_distance2(point, Vector3<double>(0,0,0), view, shift_orthogonal);
720 }
721 else {
722 // squared distance to the origin
723 r2 = x2*x2 + y2*y2 + z2*z2;
724 }
725 if ( r2 > shift2 ) value = 0;
726 if ( max < value ) {
727 if ( r2 > shift2 ) value = 0;
728 max = value;
729 peak = Vector3<double>(x,y,z);
730 }
731 }
732 }
733 }
734 p->image->origin(peak);
735 p->image->FOM(max);
736 if ( verbose & VERB_FULL )
737 cout << "Peak: " << peak << tab << max << endl;
738
739 return max;
740 }
741
754 Vector3<double> closest_point_line( Vector3<double> p, Vector3<double> v, Vector3<double> w )
755 {
756 double l2, t;
757 Vector3<double> closest_point;
758 Vector3<double> line;
759
760 line = w-v;
761 l2 = line.length2();
762
763 // parametric value of vector to the closest point is t = scalar(p - v, w - v) / l*l
764 t = (p-v).scalar(line) / l2;
765
766 // the closest point is end point v
767 if ( t < 0 ) { closest_point = v; }
768
769 // the closest point is end point w
770 else if ( t > 1 ) { closest_point = w; }
771
772 // the closest point is the projection of p that is v + t*line
773 else { closest_point = Vector3<double>( v[0] + t * line[0],
774 v[1] + t * line[1],
775 v[2] + t * line[2]);
776 }
777 return closest_point;
778 }
779
793 double closest_point_line_distance2( Vector3<double> p, Vector3<double> v, Vector3<double> w )
794 {
795 double l2, t;
796 Vector3<double> closest_point;
797 Vector3<double> line;
798
799 line = w-v;
800 l2 = line.length2();
801
802 // parametric value of vector to the closest point is t = scalar(p - v, w - v) / l*l
803 t = (p-v).scalar(line) / l2;
804
805 // the closest point is end point v
806 if ( t < 0 ) { closest_point = v; }
807
808 // the closest point is end point w
809 else if ( t > 1 ) { closest_point = w; }
810
811 // the closest point is the projection of p that is v + t*line
812 else { closest_point = Vector3<double>( v[0] + t * line[0],
813 v[1] + t * line[1],
814 v[2] + t * line[2]);
815 }
816 return (closest_point-p).length2();
817 }
818
819
834 double closest_point_disc_distance2( Vector3<double> p, Vector3<double> q, View view, double radius )
835 {
836 Vector3<double> pprime; // projection of p on to the plane
837
838 double p_to_pprime2; // squared distance from p' to the original point p
839
840 double pprime_to_q2; // squared distance from p' to the center of the disc q
841 double pprime_to_q; // distance from p' to the center of the disc q
842
843 double pprime_to_c2; // squared distance from p' to the circumference of the disc c
844 double p_to_c2; // squared distance from p to the circumference of the disc c
845
846 double radius2 = radius * radius;
847 double a, c;
848
849 c = q[0]*view[0] + q[1]*view[1] + q[2]*view[2];
850
851 a = (view[0] * p[0] + view[1] * p[1] + view[2] * p[2]) - c;
852 pprime = Vector3<double>(p[0] - a * view[0], p[1] - a * view[1], p[2] - a * view[2]);
853
854 pprime_to_q2 = (pprime-q).length2();
855 p_to_pprime2 = (p-pprime).length2();
856
857 if (pprime_to_q2 > radius2) {
858
859 pprime_to_q = (pprime-q).length();
860 pprime_to_c2 = (pprime_to_q - radius) * (pprime_to_q - radius);
861
862 p_to_c2 = pprime_to_c2 + p_to_pprime2;
863
864 return p_to_c2;
865 }
866 else {
867 return p_to_pprime2;
868 }
869 }
870
906 Sphere locations_fit_sphere(Bparticle* part, int N, double Nstop)
907 {
908 Sphere sphere;
909 long Pnpoints(0);
910 Bparticle* p = NULL;
911
912 double PXsum=0, PXsumsq=0, PXsumcube=0;
913 double PYsum=0, PYsumsq=0, PYsumcube=0;
914 double PZsum=0, PZsumsq=0, PZsumcube=0;
915
916 double PXYsum=0, PXZsum=0, PYZsum=0;
917 double PX2Ysum=0, PX2Zsum=0, PY2Xsum=0, PY2Zsum=0, PZ2Xsum=0, PZ2Ysum=0;
918
919 Pnpoints = count_list((char *)part);
920 double x, y, z;
921
922 for ( p = part; p; p = p-> next ) {
923
924 x = p->loc[0];
925 y = p->loc[1];
926 z = p->loc[2];
927
928 PXsum += x;
929 PXsumsq += x * x;
930 PXsumcube += x * x * x;
931
932 PYsum += y;
933 PYsumsq += y * y;
934 PYsumcube += y * y * y;
935
936 PZsum += z;
937 PZsumsq += z * z;
938 PZsumcube += z * z * z;
939
940 PXYsum += x * y;
941 PXZsum += x * z;
942 PYZsum += y * z;
943
944 PX2Ysum += x * x * y;
945 PX2Zsum += x * x * z;
946 PY2Xsum += y * y * x;
947 PY2Zsum += y * y * z;
948 PZ2Xsum += z * z * x;
949 PZ2Ysum += z * z * y;
950 }
951
952 double Xn = PXsum/Pnpoints; //sum( X[n] )
953 double Xn2 = PXsumsq/Pnpoints; //sum( X[n]^2 )
954 double Xn3 = PXsumcube/Pnpoints; //sum( X[n]^3 )
955 double Yn = PYsum/Pnpoints; //sum( Y[n] )
956 double Yn2 = PYsumsq/Pnpoints; //sum( Y[n]^2 )
957 double Yn3 = PYsumcube/Pnpoints; //sum( Y[n]^3 )
958 double Zn = PZsum/Pnpoints; //sum( Z[n] )
959 double Zn2 = PZsumsq/Pnpoints; //sum( Z[n]^2 )
960 double Zn3 = PZsumcube/Pnpoints; //sum( Z[n]^3 )
961
962 double XY = PXYsum/Pnpoints; //sum( X[n] * Y[n] )
963 double XZ = PXZsum/Pnpoints; //sum( X[n] * Z[n] )
964 double YZ = PYZsum/Pnpoints; //sum( Y[n] * Z[n] )
965 double X2Y = PX2Ysum/Pnpoints; //sum( X[n]^2 * Y[n] )
966 double X2Z = PX2Zsum/Pnpoints; //sum( X[n]^2 * Z[n] )
967 double Y2X = PY2Xsum/Pnpoints; //sum( Y[n]^2 * X[n] )
968 double Y2Z = PY2Zsum/Pnpoints; //sum( Y[n]^2 * Z[n] )
969 double Z2X = PZ2Xsum/Pnpoints; //sum( Z[n]^2 * X[n] )
970 double Z2Y = PZ2Ysum/Pnpoints; //sum( Z[n]^2 * Y[n] )
971
972 //Reduction of multiplications
973 double F0 = Xn2 + Yn2 + Zn2;
974 double F1 = 0.5*F0;
975 double F2 = -8.0*(Xn3 + Y2X + Z2X);
976 double F3 = -8.0*(X2Y + Yn3 + Z2Y);
977 double F4 = -8.0*(X2Z + Y2Z + Zn3);
978
979 //Set initial conditions:
980 double A = Xn;
981 double B = Yn;
982 double C = Zn;
983
984 //First iteration computation:
985 double A2 = A*A;
986 double B2 = B*B;
987 double C2 = C*C;
988 double QS = A2 + B2 + C2;
989 double QB = - 2*(A*Xn + B*Yn + C*Zn);
990
991 //Set initial conditions:
992 double Rsq = F0 + QB + QS;
993
994 //First iteration computation:
995 double Q0 = 0.5*(QS - Rsq);
996 double Q1 = F1 + Q0;
997 double Q2 = 8*( QS - Rsq + QB + F0 );
998 double aA,aB,aC,nA,nB,nC,dA,dB,dC;
999
1000 //Iterate N times, ignore stop condition.
1001 int n(0);
1002 while( n != N ){
1003 n++;
1004
1005 //Compute denominator:
1006 aA = Q2 + 16*(A2 - 2*A*Xn + Xn2);
1007 aB = Q2 + 16*(B2 - 2*B*Yn + Yn2);
1008 aC = Q2 + 16*(C2 - 2*C*Zn + Zn2);
1009 aA = (aA == 0) ? 1.0 : aA;
1010 aB = (aB == 0) ? 1.0 : aB;
1011 aC = (aC == 0) ? 1.0 : aC;
1012
1013
1014 //Compute next iteration
1015 nA = A - ((F2 + 16*( B*XY + C*XZ + Xn*(-A2 - Q0) + A*(Xn2 + Q1 - C*Zn - B*Yn) ) )/aA);
1016 nB = B - ((F3 + 16*( A*XY + C*YZ + Yn*(-B2 - Q0) + B*(Yn2 + Q1 - A*Xn - C*Zn) ) )/aB);
1017 nC = C - ((F4 + 16*( A*XZ + B*YZ + Zn*(-C2 - Q0) + C*(Zn2 + Q1 - A*Xn - B*Yn) ) )/aC);
1018
1019 //Check for stop condition
1020 dA = (nA - A);
1021 dB = (nB - B);
1022 dC = (nC - C);
1023 if( (dA*dA + dB*dB + dC*dC) <= Nstop ){ break; }
1024
1025 //Compute next iteration's values
1026 A = nA;
1027 B = nB;
1028 C = nC;
1029 A2 = A*A;
1030 B2 = B*B;
1031 C2 = C*C;
1032 QS = A2 + B2 + C2;
1033 QB = - 2*(A*Xn + B*Yn + C*Zn);
1034 Rsq = F0 + QB + QS;
1035 Q0 = 0.5*(QS - Rsq);
1036 Q1 = F1 + Q0;
1037 Q2 = 8*( QS - Rsq + QB + F0 );
1038 }
1039
1040 double R = sqrt(Rsq);
1041 sphere.A = A;
1042 sphere.B = B;
1043 sphere.C = C;
1044 sphere.R = R;
1045
1046 return (sphere);
1047 }
1048
1049
Bparticle::id
int id
Definition: mg_processing.h:92
Bimage::refine_peak
int refine_peak()
Refines the position of a peak to sub-voxel resolution.
Definition: Bimage_correlate.cpp:1556
Bimage::shell_wrap
int shell_wrap(long nn, Vector3< double > center, double minrad, double maxrad, double width, int fill_type=0, double fill=0)
Fills a shell within an image with a uniform value with wrapping.
Definition: Bimage_edit.cpp:654
closest_point_disc_distance2
double closest_point_disc_distance2(Vector3< double > p, Vector3< double > q, View view, double radius)
Calculates the squared distance to the closest point on a disc from a given point.
Definition: mg_subtomo.cpp:834
FILL_BACKGROUND
#define FILL_BACKGROUND
Definition: utilities.h:174
Bimage.h
Header file for image class.
views_within_limits
View * views_within_limits(View theview, double theta_step, double phi_step, double alpha_step, double view_angle_limit, double alpha_angle_limit)
Generates a list of views within an angular distance from the input view.
Definition: View.cpp:207
Bparticle::view
View view
Definition: mg_processing.h:101
Vector3::length
double length()
Definition: Vector3.h:222
img_refine_view
Bparticle * img_refine_view(Bimage *pcrop, Bimage *ptemp, Bimage *pmask, Bimage *pmask2, View view, double hires, double lores, double shiftlimit, double shiftlimitz, double shiftlimitxy, double mindist, int refinepeaks, fft_plan planf, fft_plan planb)
Definition: mg_subtomo.cpp:61
Breconstruction::part
Bparticle * part
Definition: mg_processing.h:304
planb
fft_plan planb
Definition: bico.cpp:24
vector3_set_PBC
Vector3< T1 > vector3_set_PBC(Vector3< T1 > coord, Vector3< T2 > box)
Definition: Vector3.h:682
View::next
View * next
Definition: View.h:28
Breconstruction::fpart
Bstring fpart
Definition: mg_processing.h:288
reconstruction_refine_subtomo
long reconstruction_refine_subtomo(Breconstruction *rec, Bimage *p, Bimage *ptemp, Bimage *pmask, Bimage *pmask2, double alpha_step_orig, double theta_step_orig, double phi_step_orig, double alpha_limit_orig, double thetaphi_limit_orig, double hires, double lores, double shiftlimit_orig, double shiftlimitz_orig, double shiftlimitxy_orig, double mindist, Vector3< long > bin, Bsymmetry *sym, int iters, int refinepeaks, Bstring ccmax_file)
Refines the view vectors for particles already in the project.
Definition: mg_subtomo.cpp:333
utilities.h
Header file for general utilities.
Breconstruction
Definition: mg_processing.h:280
planf
fft_plan planf
Definition: bico.cpp:24
kill_list
long kill_list(char *list, unsigned long size)
Frees all the items in a linked list.
Definition: linked_list.cpp:214
Bparticle::fom
double fom[NFOM]
Definition: mg_processing.h:102
Matrix3
Definition: Matrix3.h:17
particle_add
Bparticle * particle_add(Bparticle **part, int pid)
Adds a particle parameter structure to a linked list.
Definition: mg_processing.cpp:527
Bstring::length
long length() const
Definition: Bstring.cpp:263
Bimage::mask_fspace_resize
Vector3< double > mask_fspace_resize(Vector3< long > nusize)
Resizes a reciprocal space mask.
Definition: Bimage_mask.cpp:683
count_list
long count_list(char *list)
Counts the number of items in a linked list.
Definition: linked_list.cpp:235
length2
double length2(vector< T > v)
Definition: Vector3.h:517
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
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
sphere
int sphere(Bimage *p)
Definition: radon_util.cpp:114
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
Breconstruction::box_size
Vector3< long > box_size
Definition: mg_processing.h:296
vector3_origin_to_shift
Vector3< T1 > vector3_origin_to_shift(Vector3< T1 > origin, Vector3< T2 > size)
Definition: Vector3.h:667
img_find_peak_subtomo
double img_find_peak_subtomo(Bimage *p, View view, double shift, double shift_along, double shift_orthogonal)
Finds the peak in an image to the nearest voxel.
Definition: mg_subtomo.cpp:667
locations_fit_sphere
Sphere locations_fit_sphere(Bparticle *part, int N, double Nstop)
Least squares fit a sphere to 3D data (particle locations)
Definition: mg_subtomo.cpp:906
Bimage
General image parameter class.
Definition: Bimage.h:163
scalar
double scalar(vector< T1 > &v1, vector< T2 > &v2)
Definition: Vector3.h:611
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
M_PI
#define M_PI
Definition: utilities.h:59
linked_list.h
Header file for generalized linked list functions.
Bsymmetry::point
int point
Definition: symmetry.h:39
Bimage::maximum_included_radius
double maximum_included_radius()
Returns the radius of the enclosed sphere or circle.
Definition: Bimage.cpp:2036
img_search_view
Bparticle * img_search_view(Bimage *p, Bimage *ptemp, Bimage *pmask, View view, double hires, double lores, double shiftlimit, double mindist, double threshold, int maxhits, int refinepeaks, fft_plan planf, fft_plan planb)
Definition: mg_subtomo.cpp:30
Bimage::cross_correlate
Bimage * cross_correlate(Bimage *p, double hires, double lores, fft_plan planf, fft_plan planb)
Calculates a cross-correlation map by Fast Fourier transformation.
Definition: Bimage_correlate.cpp:363
Bimage::resize
int resize(Vector3< long > nusize, Vector3< long > translate, int fill_type=0, double fill=0)
Resizes without interpolation or rescaling.
Definition: Bimage_resize.cpp:28
fft_plan
fftwf_plan fft_plan
Definition: fft.h:16
Bsub_image::FOM
double FOM()
Definition: Bimage.h:151
length
double length(vector< T > v)
Definition: Vector3.h:528
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
closest_point_line_distance2
double closest_point_line_distance2(Vector3< double > p, Vector3< double > v, Vector3< double > w)
Calculates the squared distance to the closest point on a line segment from a given point.
Definition: mg_subtomo.cpp:793
asymmetric_unit_views
View * asymmetric_unit_views(Bsymmetry *sym, double theta_step, double phi_step, int flag)
Initializes a well-distributed set of views in an asymmetric unit.
Definition: symmetry.cpp:570
View::backward
View backward()
Definition: View.h:115
Bimage::size
Vector3< long > size() const
Definition: Bimage.h:373
FILL_USER
#define FILL_USER
Definition: utilities.h:172
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
Vector3::length2
double length2()
Definition: Vector3.h:221
Bsymmetry::label
Bstring label
Definition: symmetry.h:41
Bsymmetry
Definition: symmetry.h:38
VERB_RESULT
#define VERB_RESULT
Definition: utilities.h:105
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:261
Bparticle
Definition: mg_processing.h:89
Bstring
Definition: Bstring.h:29
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
Bimage::fft_setup
fft_plan fft_setup(fft_direction dir, int opt=0)
Sets up a plan for fast Fourier transforms.
Definition: Bimage_fft.cpp:29
View::matrix
Matrix3 matrix()
Definition: View.h:150
Matrix3::transpose
Matrix3 transpose() const
Definition: Matrix3.h:268
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
View
Definition: View.h:26
Bimage::rotate
int rotate()
Rotates an image using parameters defined in the image in place.
Definition: Bimage_transform.cpp:253
verbose
int verbose
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
reconstruction_search_subtomo
long reconstruction_search_subtomo(Breconstruction *rec, Bimage *p, Bimage *ptemp, Bimage *pmask, Bimage *pmask2, double alpha_step, double theta_step, double phi_step, double alpha_limit, double thetaphi_limit, double hires, double lores, double shiftlimit, double mindist, double threshold, int maxhits, Vector3< long > bin, Bsymmetry *sym, int refinepeaks, Bstring ccmax_file)
Definition: mg_subtomo.cpp:140
mg_processing.h
Header file for micrograph processing.
rwimg.h
Header file for 2D and 3D image I/O.
closest_point_line
Vector3< double > closest_point_line(Vector3< double > p, Vector3< double > v, Vector3< double > w)
Calculates the closest point on a line segment from a given point.
Definition: mg_subtomo.cpp:754
img_find_refine_peaks
Bparticle * img_find_refine_peaks(Bimage *pcc, View view, double shift_limit, double shift_along, double shift_orthogonal, double mindist, double threshold, int maxhits, int refinepeaks)
Finds peaks in an image to the nearest voxel iteratively.
Definition: mg_subtomo.cpp:600
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::sizeY
void sizeY(long ny)
Definition: Bimage.h:378
Sphere
Definition: mg_subtomo.h:20
mg_subtomo.h
Header file for functions finding particles (subtomograms) in a tomogram.
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:563