| 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_symmetry.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10 #include "rwsymop.h"
11 #include "img_symmetry.h"
12 #include "img_fourier.h"
13 #include "img_combine.h"
14 #include "Matrix3.h"
15 #include "Complex.h"
16 #include "trigonometry.h"
17 #include "linked_list.h"
18 #include "utilities.h"
19
20 // Declaration of global variables
21 extern int verbose; // Level of output to the screen
22
29 double* img_check_space_group(Bimage* p, double resolution)
30 {
31 if ( !p->data_pointer() ) {
32 cerr << "Error: Cannot check the symmetry - the data block is empty!" << endl;
33 return NULL;
34 }
35
36 if ( resolution <= 0 ) resolution = 0.1;
37
38 double* avgdx = new double[3*p->images()];
39 if ( p->space_group() < 2 ) return avgdx;
40
41 if ( p->compound_type() == TSimple ) p->fft();
42
43 p->simple_to_complex();
44
45 int nsym(0);
46 Bstring temp;
47 float* symat = read_symat(temp, p->space_group(), &nsym);
48
49 unsigned long i, j, n, x, y, z;
50 long m, nR, ni;
51 int h[3], hs[3], xs[3], nx[3], avgnx[3];
52 double dx[3]; // Shift vector
53 double order = p->sampling().x()*p->sizeX()/resolution;
54 double dist, tol(0.01);
55 double amp[200], phi[200], phis[200], damp, dphi;
56 double ampavg, phiavg, fomavg;
57 double Ramp, Rphi;
58 float* fom = p->FOM();
59
60 if ( verbose & VERB_PROCESS ) {
61 cout << "Checking symmetry for space group " << p->space_group() << endl;
62 cout << "Symmetry operators: " << nsym << endl;
63 cout << "Tolerance for selection: " << tol << endl;
64 cout << "Reflection index limit: " << order << endl;
65 } else if ( verbose & VERB_LABEL )
66 cout << "Checking symmetry for space group " << p->space_group() << endl << endl;
67
68 if ( verbose & VERB_DEBUG ) {
69 for ( i=0; i<nsym; i++ ) {
70 cout << "Symmetry operator " << i+1 << ":" << endl;
71 for ( j=0; j<3; j++ )
72 cout << "|" << symat[i*12+4*j] << " " << symat[i*12+4*j+1] << " "
73 << symat[i*12+4*j+2] << "| |" << symat[i*12+4*j+3] << "|" << endl;
74 }
75 }
76
77 if ( verbose & VERB_PROCESS )
78 cout << "Image\tRefl\tR(amp)\tR(phi)\tdx\tdy\tdz" << endl;
79
80 for ( n=0; n<p->images(); n++ ) {
81 nR = 0;
82 Ramp = Rphi = 0;
83 avgnx[0] = avgnx[1] = avgnx[2] = 0;
84 for ( z=0; z<p->sizeZ(); z++ ) {
85 h[2] = z;
86 if ( h[2] >= (p->sizeZ()+1)/2 ) h[2] -= p->sizeZ();
87 for ( y=0; y<p->sizeY(); y++ ) {
88 h[1] = y;
89 if ( h[1] >= (p->sizeY()+1)/2 ) h[1] -= p->sizeY();
90 for ( x=0; x<p->sizeX(); x++ ) {
91 h[0] = x;
92 if ( h[0] >= (p->sizeX()+1)/2 ) h[0] -= p->sizeX();
93 dist = sqrt(1.0*h[0]*h[0] + h[1]*h[1] + h[2]*h[2]);
94 // i = ((n*p->z + z)*p->y + y)*p->x + x;
95 i = p->index(0,x,y,z,n);
96 amp[0] = (p->complex(i)).amp();
97 if ( dist <= order && amp[0] > tol ) {
98 ni = 0;
99 nx[0] = nx[1] = nx[2] = 0;
100 dx[0] = dx[1] = dx[2] = 0;
101 ampavg = phiavg = fomavg = 0;
102 for ( j=0; j<nsym; j++ ) {
103 for ( m=0; m<3; m++ ) {
104 hs[m] = (int) (h[0]*symat[j*12+4*m] +
105 h[1]*symat[j*12+4*m+1] +
106 h[2]*symat[j*12+4*m+2]);
107 xs[m] = hs[m];
108 }
109 if ( xs[0] < 0 ) xs[0] += p->sizeX();
110 if ( xs[1] < 0 ) xs[1] += p->sizeY();
111 if ( xs[2] < 0 ) xs[2] += p->sizeZ();
112 i = ((n*p->sizeZ() + xs[2])*p->sizeY() + xs[1])*p->sizeX() + xs[0];
113 amp[j] = (p->complex(i)).amp();
114 if ( amp[j] > tol ) {
115 phi[j] = (p->complex(i)).phi();
116 phis[j] = phi[j] + TWOPI*(h[0]*symat[j*12+3] +
117 h[1]*symat[j*12+7] +
118 h[2]*symat[j*12+11]);
119 damp = amp[0] - amp[j];
120 dphi = phi[0] - phis[j];
121 dphi = angle_set_negPI_to_PI(dphi);
122 phis[j] = phi[0] - dphi;
123 for ( m=0; m<3; m++ ) if ( hs[m] != h[m] ) {
124 dx[m] -= dphi/(TWOPI*(hs[m]-h[m]));
125 nx[m]++;
126 }
127 if ( verbose & VERB_DEBUG ) {
128 if ( fabs(dphi) > tol )
129 cout << "amp dphi: " << x << " " << y << " "
130 << z << " " << j << " " << amp[j] << " " << dphi << endl;
131 }
132 ampavg += amp[j];
133 phiavg += phis[j]; //cout << "%6.3f ", phis[j]);
134 if ( fom ) fomavg += fom[i];
135 Ramp += damp*damp;
136 Rphi += dphi*dphi;
137 nR++;
138 ni++;
139 }
140 }
141 if ( ni ) {
142 ampavg /= ni;
143 phiavg /= ni;
144 fomavg /= ni;
145 for ( m=0; m<3; m++ ) {
146 if ( nx[m] ) dx[m] /= nx[m];
147 avgdx[3*n+m] += dx[m];
148 avgnx[m]++;
149 }
150 }
151 if ( verbose & VERB_DEBUG )
152 if ( fabs(phiavg-phi[0]) > tol )
153 cout << "d_phiavg: " << x << " " << y << " "
154 << z << " " << phi[0] << " " << phiavg << " " << ni << endl;
155 }
156 }
157 }
158 }
159 for ( m=0; m<3; m++ ) if ( avgnx[m] ) avgdx[3*n+m] /= avgnx[m];
160 if ( nR ) {
161 Ramp = sqrt(Ramp/nR);
162 Rphi = sqrt(Rphi/nR);
163 }
164 if ( verbose & VERB_PROCESS )
165 cout << n+1 << tab << nR << tab << Ramp << tab << Rphi*180/M_PI << tab <<
166 avgdx[3*n+0]*p->sizeX() << tab << avgdx[3*n+1]*p->sizeY() << tab << avgdx[3*n+2]*p->sizeZ() << endl;
167 p->image[n].origin(avgdx[3*n+0], avgdx[3*n+1], avgdx[3*n+2]);
168 }
169
170 return avgdx;
171 }
172
179 double* img_apply_space_group(Bimage* p, double resolution)
180 {
181 if ( !p->data_pointer() ) {
182 cerr << "Error: Cannot apply the symmetry - the data block is empty!" << endl;
183 return NULL;
184 }
185
186 if ( resolution <= 0 ) resolution = 0.1;
187
188 double* dx = new double[3*p->images()];
189 if ( p->space_group() < 2 ) return dx;
190
191 if ( p->compound_type() == TSimple ) p->fft();
192
193 p->simple_to_complex();
194
195 int nsym(0);
196 Bstring temp;
197 float* symat = read_symat(temp, p->space_group(), &nsym);
198
199 unsigned long i, j, n, x, y, z;
200 long m, nR, ni;
201 int h[3], hs[3], xs[3], ind[200];
202 double order = p->real_size().x()/resolution;
203 double dist, tol(0.01);
204 double amp[200], phi[200], phis[200], damp, dphi;
205 double ampavg, phiavg, fomavg;
206 double Ramp, Rphi;
207 float* fom = p->FOM();
208
209 if ( verbose & VERB_PROCESS ) {
210 cout << "Applying symmetry for space group " << p->space_group() << endl;
211 cout << "Symmetry operators: " << nsym << endl;
212 cout << "Tolerance for selection: " << tol << endl;
213 cout << "Reflection index limit: " << order << endl;
214 } else if ( verbose & VERB_LABEL )
215 cout << "Applying symmetry for space group " << p->space_group() << endl << endl;
216
217 if ( verbose & VERB_DEBUG ) {
218 for ( i=0; i<nsym; i++ ) {
219 cout << "Symmetry operator " << i+1 << ":" << endl;
220 for ( j=0; j<3; j++ )
221 cout << "|" << symat[i*12+4*j] << " " << symat[i*12+4*j+1] << " "
222 << symat[i*12+4*j+2] << "| |" << symat[i*12+4*j+3] << "|" << endl;
223 }
224 }
225
226 if ( verbose & VERB_PROCESS )
227 cout << "Image\tRefl\tR(amp)\tR(phi)\tdx\tdy\tdz" << endl;
228
229 for ( n=0; n<p->images(); n++ ) {
230 nR = 0;
231 Ramp = Rphi = 0;
232 dx[3*n+0] = -p->image[n].origin().x();
233 dx[3*n+1] = -p->image[n].origin().y();
234 dx[3*n+2] = -p->image[n].origin().z(); // Origin shift to apply
235 for ( z=0; z<p->sizeZ(); z++ ) {
236 h[2] = z;
237 if ( h[2] >= (p->sizeZ()+1)/2 ) h[2] -= p->sizeZ();
238 for ( y=0; y<p->sizeY(); y++ ) {
239 h[1] = y;
240 if ( h[1] >= (p->sizeY()+1)/2 ) h[1] -= p->sizeY();
241 for ( x=0; x<p->sizeX(); x++ ) {
242 h[0] = x;
243 if ( h[0] >= (p->sizeX()+1)/2 ) h[0] -= p->sizeX();
244 dist = sqrt(1.0*h[0]*h[0] + h[1]*h[1] + h[2]*h[2]);
245 // i = ((n*p->z + z)*p->y + y)*p->x + x;
246 i = p->index(0,x,y,z,n);
247 amp[0] = (p->complex(i)).amp();
248 if ( dist <= order && amp[0] > tol ) {
249 ni = 0;
250 ampavg = phiavg = fomavg = 0;
251 for ( j=0; j<nsym; j++ ) {
252 for ( m=0; m<3; m++ ) {
253 hs[m] = (int) (h[0]*symat[j*12+4*m] +
254 h[1]*symat[j*12+4*m+1] +
255 h[2]*symat[j*12+4*m+2]);
256 xs[m] = hs[m];
257 }
258 if ( xs[0] < 0 ) xs[0] += p->sizeX();
259 if ( xs[1] < 0 ) xs[1] += p->sizeY();
260 if ( xs[2] < 0 ) xs[2] += p->sizeZ();
261 i = ((n*p->sizeZ() + xs[2])*p->sizeY() + xs[1])*p->sizeX() + xs[0];
262 ind[j] = i;
263 amp[j] = (p->complex(i)).amp();
264 if ( amp[j] > tol ) {
265 phi[j] = (p->complex(i)).phi();
266 phis[j] = phi[j] + TWOPI*(h[0]*symat[j*12+3] +
267 h[1]*symat[j*12+7] +
268 h[2]*symat[j*12+11]);
269 damp = amp[0] - amp[j];
270 dphi = phi[0] - phis[j];
271 dphi = angle_set_negPI_to_PI(dphi);
272 phis[j] = phi[0] - dphi;
273 if ( verbose & VERB_DEBUG )
274 if ( fabs(dphi) > tol )
275 cout << "amp dphi: " << x << " " << y << " "
276 << z << " " << j << " " << amp[j] << " " << dphi << endl;
277 ampavg += amp[j];
278 phiavg += phis[j]; //cout << "%6.3f ", phis[j]);
279 if ( fom ) fomavg += fom[i];
280 Ramp += damp*damp;
281 Rphi += dphi*dphi;
282 nR++;
283 ni++;
284 }
285 }
286 if ( ni ) {
287 ampavg /= ni;
288 phiavg /= ni;
289 fomavg /= ni;
290 }
291 if ( verbose & VERB_DEBUG )
292 if ( fabs(phiavg-phi[0]) > tol )
293 cout << "d_phiavg: " << x << " " << y << " "
294 << z << " " << phi[0] << " " << phiavg << " " << ni << endl;
295 for ( j=0; j<nsym; j++ ) {
296 i = ind[j];
297 for ( m=0; m<3; m++ )
298 hs[m] = (int) (h[0]*symat[j*12+4*m] +
299 h[1]*symat[j*12+4*m+1] +
300 h[2]*symat[j*12+4*m+2]);
301 phi[j] = phi[0] - TWOPI*(h[0]*symat[j*12+3] +
302 h[1]*symat[j*12+7] +
303 h[2]*symat[j*12+11])
304 - TWOPI*((hs[0]-h[0])*dx[3*n+0] +
305 (hs[1]-h[1])*dx[3*n+1] +
306 (hs[2]-h[2])*dx[3*n+2]);
307 p->set(i, Complex<double>(ampavg*bcos(phi[j]), ampavg*bsin(phi[j])));
308 if ( fom ) fom[i] = fomavg;
309 }
310 }
311 }
312 }
313 }
314 if ( nR ) {
315 Ramp = sqrt(Ramp/nR);
316 Rphi = sqrt(Rphi/nR);
317 }
318 if ( verbose & VERB_PROCESS )
319 cout << n+1 << tab << nR << tab << Ramp << tab << Rphi*180/M_PI << tab <<
320 dx[3*n+0] << tab << dx[3*n+1] << tab << dx[3*n+2] << endl;
321 }
322
323 return dx;
324 }
325
337 int img_apply_friedel(Bimage* p)
338 {
339 unsigned long i, j, n, x, y, z;
340 long nR, xf, yf, zf;
341 double amp, amps, phi, phis, damp, dphi;
342 double ampavg, phiavg, fomavg;
343 double Ramp, Rphi;
344 double tol(0.01);
345 Complex<double> cv;
346 float* fom = p->FOM();
347
348 if ( verbose & VERB_PROCESS ) {
349 cout << "Applying Friedel symmetry:" << endl;
350 cout << "Image\tRefl\tR(amp)\tR(phi)" << endl;
351 } else if ( verbose & VERB_LABEL )
352 cout << "Applying Friedel symmetry" << endl << endl;
353
354 for ( n=0; n<p->images(); n++ ) {
355 nR = 0;
356 Ramp = Rphi = 0;
357 for ( z=0; z<p->sizeZ(); z++ ) {
358 zf = -z;
359 if ( zf < 0 ) zf += p->sizeZ();
360 for ( y=0; y<p->sizeY(); y++ ) {
361 yf = -y;
362 if ( yf < 0 ) yf += p->sizeY();
363 for ( x=0; x<(p->sizeX()+1)/2; x++ ) {
364 xf = -x;
365 if ( xf < 0 ) xf += p->sizeX();
366 // i = ((n*p->z + z)*p->y + y)*p->x + x;
367 i = p->index(0,x,y,z,n);
368 // j = ((n*p->z + zf)*p->y + yf)*p->x + xf;
369 j = p->index(0,xf,yf,zf,n);
370 amp = (p->complex(i)).amp();
371 amps = (p->complex(j)).amp();
372 phi = (p->complex(i)).phi();
373 phis = (p->complex(j)).phi();
374 damp = amp - amps;
375 dphi = phi + phis;
376 dphi = angle_set_negPI_to_PI(dphi);
377 if ( verbose & VERB_DEBUG )
378 if ( fabs(dphi) > tol )
379 cout << "amp dphi: " << x << " " << y << " "
380 << z << " " << j << " " << damp << " " << dphi << endl;
381 ampavg = (amp + amps)/2;
382 phiavg = phi - dphi/2;
383 cv = Complex<double>(ampavg*bcos(phiavg), ampavg*bsin(phiavg));
384 p->set(i, cv);
385 p->set(j, cv.conj());
386 if ( fom ) {
387 fomavg = (fom[i] + fom[j])/2;
388 fom[i] = fomavg;
389 fom[j] = fomavg;
390 }
391 Ramp += damp*damp;
392 Rphi += dphi*dphi;
393 nR++;
394 }
395 }
396 }
397 if ( nR ) {
398 Ramp = sqrt(Ramp/nR);
399 Rphi = sqrt(Rphi/nR);
400 }
401 if ( verbose & VERB_PROCESS )
402 cout << n+1 << tab << nR << tab << Ramp << tab << Rphi*180/M_PI << endl;
403 }
404 cout << endl;
405
406 return 0;
407 }
408
420 double img_check_friedel(Bimage* p)
421 {
422 p->simple_to_complex();
423
424 unsigned long i, j, n, x, y, z, ix, iy, iz;
425 double d, w, s(0), R(0), Ri(0), Rr(0), Ra(0), Rp(0);
426
427 // Bimage* pf = new Bimage(Float, TComplex, p->sizeX(), p->sizeY(), p->sizeZ(), p->images());
428
429 for ( n=0; n<p->images(); n++ ) {
430 for ( z=0; z<p->sizeZ(); z++ ) {
431 iz = (z > 0)? p->sizeZ() - z: z;
432 for ( y=0; y<p->sizeY(); y++ ) {
433 iy = (y > 0)? p->sizeY() - y: y;
434 for ( x=0; x<p->sizeX(); x++ ) {
435 ix = (x > 0)? p->sizeX() - x: x;
436 // j = ((n*p->z + z)*p->y + y)*p->x + x;
437 j = p->index(0,x,y,z,n);
438 // i = ((n*p->z + iz)*p->sizeY() + iy)*p->x + ix;
439 i = p->index(0,ix,iy,iz,n);
440 // pf->set(j, p->complex(j) - (p->complex(i)).conj());
441 w = ((p->complex(j)).power() + (p->complex(i)).power())/2;
442 if ( !isfinite(w) ) cout << x << " " << y << " " << z << " " << w << endl;
443 d = (p->complex(i)).real() - (p->complex(j)).real();
444 Rr += d*d*w;
445 d = (p->complex(i)).imag() + (p->complex(j)).imag();
446 Ri += d*d*w;
447 d = (p->complex(i)).amp() - (p->complex(j)).amp();
448 Ra += d*d*w;
449 d = angle_set_negPI_to_PI((p->complex(i)).phi() + (p->complex(j)).phi());
450 Rp += d*d*w;
451 s += w;
452 }
453 }
454 }
455 }
456
457 Rr = sqrt(Rr/s);
458 Ri = sqrt(Ri/s);
459 Ra = sqrt(Ra/s);
460 Rp = sqrt(Rp/s);
461 R = sqrt(Rr*Rr + Ri*Ri);
462
463 if ( verbose & VERB_PROCESS ) {
464 cout << "Friedel symmetry residuals:" << endl;
465 cout << "Real: " << Rr << endl;
466 cout << "Imaginary: " << Ri << endl;
467 cout << "Amplitude: " << Ra << endl;
468 cout << "Phase: " << Rp*180.0/M_PI << " degrees" << endl;
469 cout << "Overall: " << R << endl << endl;
470 // write_img("friedel_residual.pif", pf);
471 }
472
473 // delete pf;
474
475 return R;
476 }
477
478
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:321
read_symat
float * read_symat(Bstring &filename, int spacegroup, int *nsym)
Reading crystallographic symmetry operators.
Definition: rwsymop.cpp:34
Bimage.h
Header file for image class.
bcos
double bcos(double x)
Avoid non-zero values for cos(PI/2) and cos(-PI/2).
Definition: trigonometry.cpp:27
Bimage::fft
int fft()
Definition: Bimage.h:596
utilities.h
Header file for general utilities.
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:104
angle_set_negPI_to_PI
double angle_set_negPI_to_PI(double angle)
Returns an angle between -PI and PI.
Definition: utilities.cpp:530
Bimage::compound_type
CompoundType compound_type()
Definition: Bimage.h:296
Complex.h
Class for complex numbers.
Complex::conj
Complex conj()
Definition: Complex.h:106
rwsymop.h
Header file for reading and writing symmetry operators.
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:99
Bimage::index
size_t index(size_t nx, size_t ny)
Definition: Bimage.h:325
Matrix3.h
3x3 Matrix manipulation functions
bsin
double bsin(double x)
Avoid non-zero values for sin(PI) and sin(-PI).
Definition: trigonometry.cpp:48
TSimple
Definition: Bimage.h:71
Bimage
General image parameter class.
Definition: Bimage.h:153
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:400
M_PI
#define M_PI
Definition: utilities.h:51
linked_list.h
Header file for generalized linked list functions.
img_check_friedel
double img_check_friedel(Bimage *p)
Checks Friedel symmetry.
Definition: img_symmetry.cpp:420
Bimage::complex
Complex< double > complex(size_t j)
Returns a complex value at the given index.
Definition: Bimage.cpp:792
Bimage::sampling
void sampling(double s)
Definition: Bimage.h:403
Bimage::FOM
float * FOM()
Definition: Bimage.h:238
img_fourier.h
General FFT for n-dimensional data.
img_combine.h
Header file for combining two images in various ways.
Bimage::simple_to_complex
void simple_to_complex()
A simple image is converted to a complex image.
Definition: Bimage_complex.cpp:22
Bimage::space_group
unsigned int space_group()
Definition: Bimage.h:443
Vector3::x
Type x()
Definition: Vector3.h:139
img_check_space_group
double * img_check_space_group(Bimage *p, double resolution)
Checks the crystal space group symmetry and the shift to a symmetry axis.
Definition: img_symmetry.cpp:29
verbose
int verbose
trigonometry.h
Header file for trigonometry functions.
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:133
Bimage::set
void set(size_t j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:884
Bimage::images
size_t images()
Definition: Bimage.h:401
Complex
Definition: Complex.h:23
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:230
Bstring
Definition: Bstring.h:25
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:319
img_symmetry.h
Header file for symmetry functions.
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:320
img_apply_friedel
int img_apply_friedel(Bimage *p)
Applies Friedel symmetry.
Definition: img_symmetry.cpp:337
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:98
img_apply_space_group
double * img_apply_space_group(Bimage *p, double resolution)
Applies the necessary shift to superimpose the origin on a symmetry axis.
Definition: img_symmetry.cpp:179
TWOPI
#define TWOPI
Definition: utilities.h:60
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:184