| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
img_find.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10 #include "img_find.h"
11 #include "matrix_linear.h"
12 #include "linked_list.h"
13 #include "utilities.h"
14
15 // Declaration of global variables
16 extern int verbose; // Level of output to the screen
17
18 // Internal function prototype
19 Vector3<double> img_find_density_for_view(Bimage* p, Bimage* ptemp, View view,
20 double hires, double lores, double search_radius, Bimage* pmask,
21 double& cc, fft_plan planf, fft_plan planb);
22 double img_fcc_for_view(Bimage* p, Bimage* ptemp, View view,
23 FSI_Kernel* kernel, double hires, double lores, Bimage* pmask);
24 double* distances_from_view(View bestview, int nviews, View* view_arr);
25 int gaussian_fit(int n, double* d, double* cc);
26
44 double img_find_density(Bimage* p, Bimage* ptemp, View* view,
45 double hires, double lores, double search_radius,
46 Bimage* pmask, View* currview, Vector3<float>* currshift)
47 {
48 int n, nviews, ibest(0);
49 double best(-1e37);
50 View bestview;
51 View* v;
52
53 for ( nviews=0, v=view; v; v=v->next ) nviews++;
54
55 View* view_arr = new View[nviews];
56 double* cc = new double[nviews];
57 Vector3<double>* translate = new Vector3<double>[nviews];
58
59 for ( n=0, v=view; v; v=v->next, n++ ) view_arr[n] = *v;
60
61 if ( search_radius < 0 ) search_radius = ptemp->sizeX()/4;
62
63 if ( !p ) return best;
64
65 p->change_type(Float);
66 ptemp->change_type(Float);
67 p->rescale_to_avg_std(0, 1);
68 ptemp->rescale_to_avg_std(0, 1);
69 p->calculate_background();
70 ptemp->calculate_background();
71
72 Vector3<float> origin(ptemp->image->origin());
73
74 if ( origin.length() == 0 ) {
75 origin = ptemp->size()/2;
76 ptemp->origin(origin);
77 }
78
79 if ( verbose ) {
80 cout << "Finding a template in a map:" << endl;
81 cout << "Template: " << ptemp->file_name() << endl;
82 cout << "Map: " << p->file_name() << endl;
83 cout << "Template origin: " << ptemp->image->origin() << endl;
84 cout << "Map origin: " << p->image->origin() << endl;
85 cout << "Number of views: " << nviews << endl;
86 cout << "Resolution range: ";
87 if ( lores <= 0 ) cout << "inf";
88 else cout << lores;
89 cout << " - " << hires << " A" << endl;
90 cout << "Shift search radius: " << search_radius << " pixels" << endl;
91 }
92
93 fft_plan planf = fft_setup_plan(ptemp->size(), FFTW_FORWARD, 1);
94 fft_plan planb = fft_setup_plan(ptemp->size(), FFTW_BACKWARD, 1);
95
96 #ifdef HAVE_GCD
97 dispatch_apply(nviews, dispatch_get_global_queue(0, 0), ^(size_t k){
98 translate[k] = img_find_density_for_view(p, ptemp, view_arr[k], hires, lores,
99 search_radius, pmask, cc[k], planf, planb);
100 });
101 #else
102 #pragma omp parallel for
103 for ( n=0; n<nviews; n++ ) {
104 translate[n] = img_find_density_for_view(p, ptemp, view_arr[n], hires, lores,
105 search_radius, pmask, cc[n], planf, planb);
106 }
107 #endif
108
109 if ( verbose & VERB_RESULT )
110 cout << "View\ttx\tty\ttz\tvx\tvy\tvz\tva\tCC" << endl;
111 for ( n=0; n<nviews; n++ ) {
112 if ( best < cc[n] ) {
113 best = cc[n];
114 ibest = n;
115 }
116 if ( verbose & VERB_RESULT )
117 cout << n << tab << setprecision(2) << translate[n] << tab
118 << setprecision(4) << view_arr[n] << tab << cc[n] << endl;
119 }
120
121 bestview = view_arr[ibest];
122
123 fft_destroy_plan(planf);
124 fft_destroy_plan(planb);
125
126 p->image->origin(ptemp->image->origin() + translate[ibest]);
127 p->view(bestview);
128 p->image->FOM(best);
129
130 if ( verbose )
131 cout << "Best view:\t" << ibest << tab << setprecision(2) << translate[ibest] << tab
132 << setprecision(4) << bestview << tab << best << endl;
133
134 double* d = distances_from_view(bestview, nviews, view_arr);
135
136 gaussian_fit(nviews, d, cc);
137
138 delete[] cc;
139 delete[] d;
140 delete[] view_arr;
141
142 *currview = bestview;
143 *currshift = translate[ibest];
144
145 delete[] translate;
146
147 return best;
148 }
149
150 /*
151 @brief Searches a 2D/3D density map for a template using a specific view.
152 @param *p the image.
153 @param *ptemp the template to be searched for.
154 @param view view.
155 @param hires high resolution limit.
156 @param lores low resolution limit.
157 @param search_radius radius for shift search.
158 @param *pmask mask for cross-correlation (ignored if NULL).
159 @param &cc the best correlation coefficient
160 @param planf FFT forward plan.
161 @param planb FFT backward plan.
162 @return Vector3<double> best shift to impose on the image.
163
164 The template is rotated to the view and cross-correlated to find
165 a set of high-scoring fits.
166 The views must be calculated externally to allow for custom sets.
167 **/
168 Vector3<double> img_find_density_for_view(Bimage* p, Bimage* ptemp, View view,
169 double hires, double lores, double search_radius, Bimage* pmask,
170 double& cc, fft_plan planf, fft_plan planb)
171 {
172 Matrix3 mat = view.matrix();
173 mat = mat.transpose();
174
175 Bimage* prot = ptemp->rotate(ptemp->size(), mat);
176
177 prot->view(view);
178
179 Bimage* pcc = p->cross_correlate(prot, hires, lores, pmask, planf, planb);
180
181 pcc->find_peak(search_radius, 0);
182
183 // if ( verbose & VERB_DEBUG )
184 // cout << "DEBUG img_find_density_for_view: found origin = " << pcc->image->origin() << endl;
185
186 pcc->refine_peak();
187
188 // if ( verbose & VERB_DEBUG )
189 // cout << "DEBUG img_find_density_for_view: refined origin = " << pcc->image->origin() << endl;
190
191 Vector3<double> shift = -pcc->image->origin();
192 cc = pcc->image->FOM();
193
194 delete prot;
195 delete pcc;
196
197 return shift;
198 }
199
217 double img_fcc_search(Bimage* p, Bimage* ptemp, View* view,
218 FSI_Kernel* kernel, double hires, double lores, Bimage* pmask)
219 {
220 if ( !p ) return -1e37;
221
222 int n, nviews, ibest;
223 double best(-1e37);
224 View bestview;
225 View* v;
226
227 for ( nviews=0, v=view; v; v=v->next ) nviews++;
228
229 View* view_arr = new View[nviews];
230 double* cc = new double[nviews];
231
232 for ( n=0, v=view; v; v=v->next, n++ ) view_arr[n] = *v;
233
234 if ( verbose & VERB_PROCESS )
235 cout << "Number of views: " << nviews << endl;
236
237 #ifdef HAVE_GCD
238 dispatch_apply(nviews, dispatch_get_global_queue(0, 0), ^(size_t k){
239 cc[k] = img_fcc_for_view(p, ptemp, view_arr[k], kernel, hires, lores, pmask);
240 });
241 #else
242 #pragma omp parallel for
243 for ( n=0; n<nviews; n++ )
244 cc[n] = img_fcc_for_view(p, ptemp, view_arr[n], kernel, hires, lores, pmask);
245 #endif
246
247 double ccmin(1), ccmax(-1), ccavg(0), ccstd(0);
248
249 for ( n=ibest=0; n<nviews; n++ ) {
250 if ( best < cc[n] ) {
251 best = cc[n];
252 ibest = n;
253 }
254 if ( ccmin > cc[n] ) ccmin = cc[n];
255 if ( ccmax < cc[n] ) ccmax = cc[n];
256 ccavg += cc[n];
257 ccstd += cc[n]*cc[n];
258 }
259
260 ccavg /= n;
261 ccstd = ccstd/n - ccavg*ccavg;
262 if ( ccstd > 0 ) ccstd = sqrt(ccstd);
263 else ccstd = 0;
264
265 if ( verbose & VERB_PROCESS )
266 cout << "Min, max, avg, std: " << ccmin << " " << ccmax << " " << ccavg << " " << ccstd << endl;
267
268 p->view(view_arr[ibest]);
269 p->image->FOM(best);
270
271 delete[] view_arr;
272 delete[] cc;
273
274 return best;
275 }
276
277 /*
278 @brief Searches a 2D/3D density map for a template using a specific view.
279 @param *p the Fourier transformed image.
280 @param *ptemp the Fourier transformed template to be searched for.
281 @param view view.
282 @param *cc interpolation kernel.
283 @param hires high resolution limit.
284 @param lores low resolution limit.
285 @param *pmask mask for cross-correlation (ignored if NULL).
286 @return double correlation coefficient.
287
288 The template is rotated to the view and cross-correlated to find
289 a set of high-scoring fits.
290 The views must be calculated externally to allow for custom sets.
291 **/
292 double img_fcc_for_view(Bimage* p, Bimage* ptemp, View view,
293 FSI_Kernel* kernel, double hires, double lores, Bimage* pmask)
294 {
295 Matrix3 mat = view.matrix();
296 // mat = mat.transpose();
297
298 long i, n(0);
299 double minrad = (lores>0)? ptemp->real_size().x()/lores: 0;
300 double maxrad = (hires>0)? ptemp->real_size().x()/hires: ptemp->sizeX()/2;
301 if ( maxrad > ptemp->sizeX()/2 ) maxrad = ptemp->sizeX()/2;
302
303 // cout << "minrad=" << minrad << " maxrad=" << maxrad << endl;
304
305 Complex<double> v1, v2, cv;
306 Vector3<double> c, cr;
307 Vector3<int> min = Vector3<int>((int) (-maxrad - 0.5), (int) (-maxrad - 0.5), (int) (-maxrad - 0.5));
308 Vector3<int> max = Vector3<int>((int) (maxrad + 0.5), (int) (maxrad + 0.5), (int) (maxrad + 0.5));
309 Vector3<int> ci;
310 double d, pwr1(0), pwr2(0), cc(0);
311
312 // cout << "min=" << min << " max=" << max << endl;
313
314 for ( c[2]=min.z(); c.z()<=max.z(); c[2]+=1 ) {
315 for ( c[1]=min.y(); c.y()<=max.y(); c[1]+=1 ) {
316 for ( c[0]=min.x(); c.x()<=max.x(); c[0]+=1 ) {
317 d = c.length();
318 if ( d >= minrad && d <= maxrad ) {
319 ci = c;
320 if ( ci.x() < 0 ) ci[0] += p->sizeX();
321 if ( ci.y() < 0 ) ci[1] += p->sizeY();
322 if ( ci.z() < 0 ) ci[2] += p->sizeZ();
323 i = (ci.z()*p->sizeY() + ci.y())*p->sizeX() + ci.x();
324 if ( !pmask || ( pmask && (*pmask)[i] ) ) {
325 v1 = p->complex(i);
326 cr = mat * c;
327 v2 = ptemp->fspace_interpolate(0, cr, kernel);
328 pwr1 += v1.power();
329 pwr2 += v2.power();
330 cv += v1*v2.conj();
331 n++;
332 }
333 }
334 }
335 }
336 }
337
338 d = pwr1*pwr2;
339 if ( d > 0 ) cc = cv.amp()/sqrt(d);
340
341 if ( verbose & VERB_FULL )
342 cout << view << tab << n << tab << cc << endl;
343
344 return cc;
345 }
346
347 /*
348 @brief Searches a 2D/3D density map for a template using a specific view.
349 @param *p the Fourier transformed image.
350 @param *ptemp the Fourier transformed template to be searched for.
351 @param view view.
352 @param *cc interpolation kernel.
353 @param hires high resolution limit.
354 @param lores low resolution limit.
355 @param searchrad correlation map search radius.
356 @param *pmask mask for cross-correlation (ignored if NULL).
357 @return double correlation coeficient.
358
359 The template is rotated to the view and cross-correlated to find
360 a set of high-scoring fits.
361 The views must be calculated externally to allow for custom sets.
362 The shift is encoded in the image origin.
363 **/
364 double img_cc_for_view(Bimage* p, Bimage* ptemp, View view,
365 FSI_Kernel* kernel, double hires, double lores, double searchrad,
366 Bimage* pmask)
367 {
368 Matrix3 mat = view.matrix();
369 // mat = mat.transpose();
370
371 long i;
372 double minrad = (lores>0)? ptemp->real_size().x()/lores: 0;
373 double maxrad = ptemp->real_size().x()/hires;
374 if ( maxrad > ptemp->sizeX()/2 ) maxrad = ptemp->sizeX()/2;
375
376 Complex<double> v1, v2;
377 Vector3<double> c, cr;
378 Vector3<int> min = Vector3<int>((int) (-maxrad - 0.5), (int) (-maxrad - 0.5), (int) (-maxrad - 0.5));
379 Vector3<int> max = Vector3<int>((int) (maxrad + 0.5), (int) (maxrad + 0.5), (int) (maxrad + 0.5));
380 Vector3<int> ci;
381 double d, pwr1(0), pwr2(0);
382
383 Bimage* pcc = new Bimage(Float, TComplex, ptemp->sizeX(),
384 ptemp->sizeY(), ptemp->sizeZ(), 1);
385
386 for ( c[2]=min.z(); c.z()<=max.z(); c[2]+=1 ) {
387 for ( c[1]=min.y(); c.y()<=max.y(); c[1]+=1 ) {
388 for ( c[0]=min.x(); c.x()<=max.x(); c[0]+=1 ) {
389 d = c.length();
390 if ( d >= minrad && d <= maxrad ) {
391 ci = c;
392 if ( ci.x() < 0 ) ci[0] += p->sizeX();
393 if ( ci.y() < 0 ) ci[1] += p->sizeY();
394 if ( ci.z() < 0 ) ci[2] += p->sizeZ();
395 i = (ci.z()*p->sizeY() + ci.y())*p->sizeX() + ci.x();
396 if ( !pmask || ( pmask && (*pmask)[i] ) ) {
397 v1 = p->complex(i);
398 cr = mat * c;
399 v2 = ptemp->fspace_interpolate(0, cr, kernel);
400 pwr1 += v1.power();
401 pwr2 += v2.power();
402 pcc->set(i, v1*v2.conj());
403 }
404 }
405 }
406 }
407 }
408
409 double scale = 1/sqrt(pwr1*pwr2);
410
411 for ( i=0; i<pcc->data_size(); i++ ) pcc->set(i, (*pcc)[i] * scale);
412
413 pcc->fft(FFTW_BACKWARD, 0);
414
415 pcc->complex_to_real();
416
417 pcc->find_peak(searchrad, 0);
418 double cc = pcc->image->FOM();
419
420 pcc->refine_peak();
421
422 // shift = mat * shift;
423
424 if ( verbose & VERB_FULL )
425 cout << view << tab << pcc->image->origin() << tab << cc << endl;
426
427 p->image->origin(ptemp->image->origin() + pcc->image->origin());
428
429 delete pcc;
430
431 return cc;
432 }
433
434
435 double* distances_from_view(View bestview, int nviews, View* view_arr)
436 {
437 int n;
438 double* d = new double[nviews];
439
440 // for ( n=0; n<nviews; n++ ) d[n] = bestview.residual(view_arr[n]);
441 for ( n=0; n<nviews; n++ ) d[n] = bestview.distance(view_arr[n]);
442 // for ( n=0; n<nviews; n++ ) d[n] = bestview.angle(view_arr[n]);
443
444 return d;
445 }
446
447 int gaussian_fit2(int n, double* d, double* cc)
448 {
449 int i;
450 double ccmax, ccavg, ccd;
451 double s, sb, t, a, r, rb;
452
453 for ( i=0, ccavg=0, ccmax=0; i<n; i++ ) {
454 if ( ccmax < cc[i] ) ccmax = cc[i];
455 ccavg += cc[i];
456 }
457 ccavg /= n;
458 ccd = ccmax - ccavg;
459
460 for ( s=0.001, sb=0, rb=1e10; s<=1; s*=1.01 ) {
461 for ( i=0, r=0; i<n; i++ ) {
462 t = d[i]/s;
463 a = cc[i] - ccavg - ccd*exp(-0.5*t*t);
464 r += a*a;
465 }
466 r = sqrt(r/n);
467 if ( rb > r ) {
468 rb = r;
469 sb = s;
470 }
471 }
472
473 if ( verbose )
474 cout << "Gaussian fit:\t" << ccavg << tab << ccd << tab << sb << tab << rb << endl;
475
476 return 0;
477 }
478
479 int gaussian_fit(int n, double* d, double* cc)
480 {
481 int i;
482 double s, sb, t, a, ab, b, bb, c, cb;
483 double* x = new double[n];
484 double* y = new double[n];
485
486 for ( i=0; i<n; i++ ) y[i] = cc[i];
487
488 for ( s=0.001, cb=0, sb=0; s<=1; s*=1.01 ) {
489 for ( i=0; i<n; i++ ) {
490 t = d[i]/s;
491 x[i] = exp(-0.5*t*t);
492 }
493 c = linear_least_squares(0, n-1, x, y, a, b);
494 if ( cb < c ) {
495 cb = c;
496 sb = s;
497 ab = a;
498 bb = b;
499 }
500 }
501
502 if ( verbose )
503 cout << "Gaussian fit:\t" << ab << tab << bb << tab << sb << tab << cb << endl;
504
505 delete[] x;
506 delete[] y;
507
508 return 0;
509 }
510
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1544
Vector3::z
Type z()
Definition: Vector3.h:139
fft_setup_plan
fft_plan fft_setup_plan(size_t x, size_t y, size_t z, fft_direction dir, int opt)
Sets up a plan for fast Fourier transforms.
Definition: fft.cpp:31
Bimage::refine_peak
int refine_peak()
Refines the position of a peak to sub-voxel resolution.
Definition: Bimage_correlate.cpp:1106
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:332
Matrix3::transpose
Matrix3 transpose() const
Definition: Matrix3.h:255
img_find.h
Header file for functions to find a template in an image.
Bimage.h
Header file for image class.
img_fcc_for_view
double img_fcc_for_view(Bimage *p, Bimage *ptemp, View view, FSI_Kernel *kernel, double hires, double lores, Bimage *pmask)
Definition: img_find.cpp:292
View::next
View * next
Definition: View.h:28
Vector3::length
double length()
Definition: Vector3.h:196
Bimage::calculate_background
int calculate_background(size_t nn)
Calculates the background for one sub-image.
Definition: Bimage_background.cpp:26
Bimage::fft
int fft()
Definition: Bimage.h:692
utilities.h
Header file for general utilities.
Matrix3
Definition: Matrix3.h:17
Complex::conj
Complex conj()
Definition: Complex.h:106
img_find_density
double img_find_density(Bimage *p, Bimage *ptemp, View *view, double hires, double lores, double search_radius, Bimage *pmask, View *currview, Vector3< float > *currshift)
Searches a 2D/3D density map for a template.
Definition: img_find.cpp:44
Vector3< double >
gaussian_fit
int gaussian_fit(int n, double *d, double *cc)
Definition: img_find.cpp:479
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:101
img_fcc_search
double img_fcc_search(Bimage *p, Bimage *ptemp, View *view, FSI_Kernel *kernel, double hires, double lores, Bimage *pmask)
Fast cross-correlation searches a 2D/3D density map for a template.
Definition: img_find.cpp:217
FSI_Kernel
Definition: FSI_Kernel.h:14
TComplex
Definition: Bimage.h:52
img_find_density_for_view
Vector3< double > img_find_density_for_view(Bimage *p, Bimage *ptemp, View view, double hires, double lores, double search_radius, Bimage *pmask, double &cc, fft_plan planf, fft_plan planb)
Definition: img_find.cpp:168
Bimage::size
Vector3< size_t > size() const
Definition: Bimage.h:327
b
long b
Definition: jpegint.h:371
Float
Definition: utilities.h:151
distances_from_view
double * distances_from_view(View bestview, int nviews, View *view_arr)
Definition: img_find.cpp:435
Bimage
General image parameter class.
Definition: Bimage.h:152
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:437
linked_list.h
Header file for generalized linked list functions.
Bimage::rescale_to_avg_std
int rescale_to_avg_std(double nuavg=0, double nustd=1)
Rescales the image data to a given average and standard deviation.
Definition: Bimage_rescale.cpp:100
Bimage::complex
Complex< double > complex(size_t j)
Returns a complex value at the given index.
Definition: Bimage.cpp:885
Bsub_image::FOM
double FOM()
Definition: Bimage.h:142
sb
int sb(0)
Complex::amp
double amp()
Definition: Complex.h:104
Vector3::x
Type x()
Definition: Vector3.h:137
Bimage::fspace_interpolate
Complex< double > fspace_interpolate(size_t img_num, Vector3< double > m, FSI_Kernel *kernel)
Calculates the complex value at an image location by kernel-based interpolation.
Definition: Bimage_fspace.cpp:25
Bimage::file_name
void file_name(Bstring s)
Definition: Bimage.h:213
Bimage::find_peak
int find_peak(double radius, double sigma)
Finds the peak in an image to the nearest voxel.
Definition: Bimage_correlate.cpp:1028
Bimage::cross_correlate
Bimage * cross_correlate(Bimage *p, Bimage *pmask=NULL)
Definition: Bimage.h:792
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:132
Bimage::set
void set(size_t j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:977
Bimage::view
void view(double vx, double vy, double vz, double va)
Definition: Bimage.h:485
fftwnd_data
Definition: fftw.h:355
VERB_RESULT
#define VERB_RESULT
Definition: utilities.h:99
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
Complex
Definition: Complex.h:23
Bimage::data_size
size_t data_size()
Definition: Bimage.h:225
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:330
View::matrix
Matrix3 matrix()
Definition: View.h:137
matrix_linear.h
Header file for matrix functions.
FFTW_BACKWARD
Definition: fftw.h:64
verbose
int verbose
fft_destroy_plan
int fft_destroy_plan(fft_plan plan)
Deallocates a plan for fast Fourier transforms.
Definition: fft.cpp:97
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:331
View
Definition: View.h:26
Bimage::rotate
int rotate()
Rotates an image using parameters defined in the image in place.
Definition: Bimage_transform.cpp:220
Complex::power
double power()
Definition: Complex.h:103
View::distance
double distance(const View &view)
Definition: View.h:142
img_cc_for_view
double img_cc_for_view(Bimage *p, Bimage *ptemp, View view, FSI_Kernel *kernel, double hires, double lores, double searchrad, Bimage *pmask)
Definition: img_find.cpp:364
FFTW_FORWARD
Definition: fftw.h:64
VERB_FULL
#define VERB_FULL
Definition: utilities.h:103
Vector3::y
Type y()
Definition: Vector3.h:138
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:183
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:483
gaussian_fit2
int gaussian_fit2(int n, double *d, double *cc)
Definition: img_find.cpp:447
linear_least_squares
double linear_least_squares(int n1, int n2, double *x, double *y, double &a, double &b)
Does a linear least squares fit between two vectors.
Definition: matrix_linear.cpp:28