| 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_multislice.cpp
Go to the documentation of this file.
1
9 #include "img_multislice.h"
10 #include "img_ctf.h"
11 #include "molecule_to_map.h"
12 #include "mol_edit.h"
13 #include "Complex.h"
14 #include "Vector3.h"
15 #include "utilities.h"
16
17 // Declaration of global variables
18 extern int verbose; // Level of output to the screen
19
38 Bimage* img_calc_multi_slice(Bimage* pgrate, double thickness, double volt, double resolution)
39 {
40 Vector3<int> size(pgrate->size());
41
42 // wavelength & size - loop one slice -> propagator (one 2D image)
43 Bimage* prop = img_calc_wave_propagator(size, pgrate->sampling(), thickness, volt, resolution);
44
45 // For all slices: Multiply previous exitwave with phasegrating - FFT -
46 // multiply with propagator - FFT-1 - next slice -> exitwave (one 2D image)
47 unsigned long i;
48 Bimage* p = new Bimage(Float, TComplex, size.x(), size.y(), 1, 1);
49 p->label(pgrate->label());
50 p->fourier_type(NoTransform);
51 p->origin(pgrate->image->origin());
52 p->sampling(pgrate->sampling());
53
54 unsigned long slice_size = size.x()*size.y();
55 Complex<double> cv(1);
56 for ( i=0; i<slice_size; i++ ) p->set(i, cv);
57
58 Bimage* ptemp;
59 for ( i=0; i<pgrate->images(); i++ ) {
60 ptemp = pgrate->extract(i); // Get phase grating slice
61 p->complex_product(ptemp); // Multiply with current wave
62 delete ptemp;
63 p->fft(FFTW_FORWARD, 0); // Normalization in propagator
64 if ( i < pgrate->images()-1 ) {
65 p->complex_product(prop); // Multiply with propagator
66 p->fft(FFTW_BACKWARD, 0); // Normalization in propagator
67 }
68 }
69
70 delete prop;
71
72 return p;
73 }
74
84 Bimage* img_calc_wave_propagator(Vector3<int> size, Vector3<float> sampling,
85 double thickness, double volt, double resolution)
86 {
87 Bimage* p = new Bimage(Float, TComplex, size.x(), size.y(), 1, 1);
88 p->sampling(sampling);
89 if ( resolution < sampling.x() || resolution > 1000 )
90 resolution = sampling.x();
91
92 long i, h, k, x, y;
93 double wavelength = electron_wavelength(volt);
94 double arg, sx2, sy2, s2;
95 double afactor = M_PI*wavelength*thickness;
96 double nfactor = 1.0/(p->sizeX()*p->sizeY()); // Normalization for passing through FFT's
97 double resmax2 = 1.0/(resolution*resolution);
98 double xscale2 = 1.0/(p->sizeX()*p->sizeX()*sampling.x()*sampling.x());
99 double yscale2 = 1.0/(p->sizeY()*p->sizeY()*sampling.y()*sampling.y());
100
101 for ( y=0; y<p->sizeY(); y++ ) {
102 k = y;
103 if ( k > (p->sizeY()-1)/2 ) k -= p->sizeY();
104 sy2 = k*k*yscale2;
105 if ( sy2 <= resmax2 ) for ( x=0; x<p->sizeX(); x++ ) {
106 h = x;
107 if ( h > (p->sizeX()-1)/2 ) h -= p->sizeX();
108 sx2 = h*h*xscale2;
109 s2 = sx2 + sy2;
110 if ( s2 <= resmax2 ) {
111 i = y*p->sizeX() + x;
112 arg = afactor*s2;
113 p->set(i, Complex<double>(cos(arg), sin(arg)) * nfactor);
114 }
115 }
116 }
117
118 // write_img("propagator.map", p);
119
120 return p;
121 }
122
136 Bimage* img_calc_potential(Bmolgroup* molgroup, Vector3<int> size, Vector3<float> origin,
137 Vector3<float> sampling, double thickness, double resolution, double Bfactor,
138 Bstring& paramfile, int type)
139 {
140 // Atoms & scat cross-sections - Loop slices - calc 2D reciprocal space structure factors
141 unsigned long i, j, k;
142 int nslices(0);
143 Bmolgroup** slice_molgroup = molgroup_split_into_slices(molgroup, thickness, nslices);
144
145 if ( verbose )
146 cout << "Calculating the atomic potential" << endl;
147
148 int spacegroup(0);
149 UnitCell unit_cell(sampling.x()*size.x(),sampling.y()*size.y(),sampling.z()*size.z(),M_PI_2,M_PI_2,M_PI_2);
150 Bimage* ptemp = NULL;
151 Bimage* p = new Bimage(Float, TComplex, size.x(), size.y(), 1, nslices);
152 unsigned long imgsize = p->sizeX()*p->sizeY()*p->channels();
153 p->label(molgroup->comment);
154 p->unit_cell(unit_cell);
155 p->sampling(sampling.x(), sampling.y(), thickness);
156 p->space_group(spacegroup);
157
158 for ( i=0; i<nslices; i++ ) {
159 if ( type ) {
160 origin[2] = -slice_molgroup[i]->min.z()/sampling.z() - 0.5;
161 size[2] = (int) (thickness/sampling.z() + 1);
162 ptemp = img_from_molecule(slice_molgroup[i], origin, size, sampling,
163 resolution, 0.001, 0, 2 - type, spacegroup, unit_cell);
164 // img_project(ptemp);
165 ptemp->project('z', 1);
166 ptemp->simple_to_complex();
167 } else {
168 // origin[2] = -slice_molgroup[i]->min.z()/sampling.z() - 0.5;
169 // origin[2] = -i*thickness;
170 // origin[2] = 0;
171 size[2] = 1;
172 sampling[2] = thickness;
173 ptemp = img_sf_from_molecule(slice_molgroup[i], origin, size, sampling,
174 resolution, spacegroup, unit_cell, 2, Bfactor, paramfile);
175 ptemp->fft(FFTW_BACKWARD, 0); // No normalization - get actual potential at the beam
176 }
177 for ( j=0, k=i*imgsize; j<imgsize; j++, k++ ) p->set(k, (*ptemp)[j]);
178 delete ptemp;
179 p->image[i].origin(origin);
180 if ( verbose )
181 cout << "Slice " << i+1 << " done" << endl << endl;
182 }
183
184 p->fourier_type(NoTransform);
185
186 for ( i=0; i<nslices; i++ )
187 molgroup_kill(slice_molgroup[i]);
188
189 delete[] slice_molgroup;
190
191 return p;
192 }
193
203 int img_calc_phase_grating(Bimage* p, double volt)
204 {
205 p->simple_to_complex();
206
207 unsigned long i, j, n;
208 unsigned long imgsize = p->sizeX()*p->sizeY();
209 double wavelength = electron_wavelength(volt);
210 double arg;
211 double sigma = 0.0208886 * wavelength *
212 sqrt(1 + 5.8886579e-4/(wavelength*wavelength)); // According to Roar Kilaas
213
214 if ( verbose & VERB_FULL )
215 cout << "Sigma (interaction factor): " << sigma << endl;
216
217 for ( i=n=0; n<p->images(); n++ ) {
218 for ( j=0; j<imgsize; i++, j++ ) {
219 arg = -sigma*(p->complex(i)).real();
220 p->set(i, Complex<double>(cos(arg), sin(arg)));
221 }
222 }
223
224 return 0;
225 }
226
247 int img_apply_complex_CTF(Bimage* p, double def_avg, double def_dev, double ast_angle,
248 double volts, double Cs, double Cc, double amp_fac, double alpha, double energy_spread)
249 {
250
251 unsigned long i, n, x, y, z;
252 double xx, yy, zz, sx2, sy2, sz2, s, s2, defocus, dphi, env, arg;
253 // double phi_fac = sqrt(1-amp_fac*amp_fac);
254 double lambda = electron_wavelength(volts);
255 double hpil3Cs = M_PI_2*lambda*lambda*lambda*Cs;
256 double pil = M_PI*lambda;
257 double pialf = M_PI*alpha;
258 double Csl2 = Cs*lambda*lambda;
259 double focus_spread = Cc*energy_spread;
260 double pi2l2df2 = M_PI*M_PI*lambda*lambda*focus_spread*focus_spread/(16.0*log(2.0));
261 Complex<double> ctf;
262 Vector3<double> freq_scale(1.0/p->real_size());
263
264 if ( verbose & ( VERB_LABEL | VERB_PROCESS ) )
265 cout << "Applying a CTF to a complex Fourier transform" << endl;
266
267 if ( verbose & VERB_PROCESS ) {
268 cout << "Defocus average & deviation: " << def_avg << " A " << def_dev << " A" << endl;
269 cout << "Astigmatism angle: " << ast_angle*180/M_PI << " degrees" << endl;
270 cout << "Voltage: " << volts << " V" << endl;
271 cout << "Wavelength: " << lambda << endl;
272 cout << "Cs: " << Cs << " A" << endl;
273 cout << "Cc: " << Cc << " A" << endl;
274 cout << "Amplitude contrast: " << amp_fac << endl;
275 cout << "Beam source size: " << alpha << " radians" << endl;
276 cout << "Energy spread (focus spread): " << energy_spread << " (" << focus_spread << " A)" << endl << endl;
277 }
278
279 for ( i=n=0; n<p->images(); n++ ) {
280 for ( z=0; z<p->sizeZ(); z++ ) {
281 zz = z;
282 if ( z > (p->sizeZ() - 1)/2 ) zz -= p->sizeZ();
283 sz2 = freq_scale.z()*zz;
284 sz2 *= sz2;
285 for ( y=0; y<p->sizeY(); y++ ) {
286 yy = y;
287 if ( y > (p->sizeY() - 1)/2 ) yy -= p->sizeY();
288 sy2 = freq_scale.y()*yy;
289 sy2 *= sy2;
290 for ( x=0; x<p->sizeX(); x++, i++ ) {
291 xx = x;
292 if ( x > (p->sizeX() - 1)/2 ) xx -= p->sizeX();
293 sx2 = freq_scale.x()*xx;
294 sx2 *= sx2;
295 s2 = sx2 + sy2 + sz2;
296 s = sqrt(s2);
297 defocus = def_avg + def_dev*cos(2*(atan2(yy,xx)-ast_angle));
298 dphi = (hpil3Cs*s2 - pil*defocus)*s2;
299 arg = pialf*(Csl2*s2 - defocus)*s;
300 // arg = pialf*defocus*s;
301 arg = arg*arg + pi2l2df2*s2*s2;
302 env = exp(-arg);
303 //env=1;//dphi -= arg*arg;
304 ctf = Complex<double>(cos(dphi), sin(dphi));
305 p->set(i, ((*p)[i] * ctf) * env);
306 }
307 }
308 }
309 }
310
311 return 0;
312 }
313
Vector3::z
Type z()
Definition: Vector3.h:139
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:332
M_PI_2
#define M_PI_2
Definition: utilities.h:56
UnitCell
Definition: UnitCell.h:22
Bmolgroup::min
Vector3< float > min
Definition: rwmolecule.h:182
img_calc_wave_propagator
Bimage * img_calc_wave_propagator(Vector3< int > size, Vector3< float > sampling, double thickness, double volt, double resolution)
Calculates the wave propagation function between slices.
Definition: img_multislice.cpp:84
molecule_to_map.h
Header file for functions to calculate a 3D map from atomic coordinates.
Bimage::fft
int fft()
Definition: Bimage.h:692
utilities.h
Header file for general utilities.
Bimage::complex_product
int complex_product(Bimage *p)
Calculates the complex product of two complex images.
Definition: Bimage_complex.cpp:383
img_apply_complex_CTF
int img_apply_complex_CTF(Bimage *p, double def_avg, double def_dev, double ast_angle, double volts, double Cs, double Cc, double amp_fac, double alpha, double energy_spread)
Applies a complex CTF function to a Fourier transform.
Definition: img_multislice.cpp:247
Complex.h
Class for complex numbers.
Bimage::unit_cell
void unit_cell(UnitCell u)
Definition: Bimage.h:492
Vector3< int >
img_calc_phase_grating
int img_calc_phase_grating(Bimage *p, double volt)
Calculates the phase grating approximation from the atomic potential.
Definition: img_multislice.cpp:203
img_calc_potential
Bimage * img_calc_potential(Bmolgroup *molgroup, Vector3< int > size, Vector3< float > origin, Vector3< float > sampling, double thickness, double resolution, double Bfactor, Bstring &paramfile, int type)
Calculates the atomic potential.
Definition: img_multislice.cpp:136
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:101
TComplex
Definition: Bimage.h:52
Bimage::size
Vector3< size_t > size() const
Definition: Bimage.h:327
img_sf_from_molecule
Bimage * img_sf_from_molecule(Bmolgroup *molgroup, Vector3< float > origin, Vector3< int > size, Vector3< float > sampling, double resolution, int spacegroup, UnitCell unit_cell, int wrap, double Bfactor, Bstring &paramfile)
Calculates a 3D set of structure factors from a set of atomic coordinates.
Definition: molecule_to_map.cpp:356
Float
Definition: utilities.h:151
Bimage
General image parameter class.
Definition: Bimage.h:152
Bimage::real_size
Vector3< double > real_size()
Definition: Bimage.h:437
M_PI
#define M_PI
Definition: utilities.h:53
Bmolgroup
Definition: rwmolecule.h:170
Bimage::complex
Complex< double > complex(size_t j)
Returns a complex value at the given index.
Definition: Bimage.cpp:885
Bimage::channels
size_t channels()
Definition: Bimage.h:325
Bimage::sampling
void sampling(double s)
Definition: Bimage.h:440
Bmolgroup::comment
Bstring comment
Definition: rwmolecule.h:175
molgroup_kill
int molgroup_kill(Bmolgroup *molgroup)
Destroys a molecule group.
Definition: rwmolecule.cpp:368
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:487
Vector3::x
Type x()
Definition: Vector3.h:137
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::extract
Bimage * extract(size_t nn)
Extracts one sub-image into new image structure.
Definition: Bimage_extract.cpp:21
Bimage::images
size_t images()
Definition: Bimage.h:438
Complex
Definition: Complex.h:23
img_ctf.h
Header file for CTF (contrast transfer function) functions.
Bstring
Definition: Bstring.h:28
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:330
verbose
int verbose
FFTW_BACKWARD
Definition: fftw.h:64
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:331
Vector3.h
Class for 3-value vectors.
img_calc_multi_slice
Bimage * img_calc_multi_slice(Bimage *pgrate, double thickness, double volt, double resolution)
Simulates the electron imaging process using a multi-slice approach.
Definition: img_multislice.cpp:38
NoTransform
Definition: Bimage.h:34
img_multislice.h
Header file for multi-slice simulation of the electron imaging process.
img_from_molecule
Bimage * img_from_molecule(Bmolgroup *molgroup, Vector3< float > origin, Vector3< int > size, Vector3< float > sampling, double resolution, double Bfactor, int wrap, int gextype, int spacegroup, UnitCell unit_cell)
Calculates a 3D density map from a set of atomic coordinates.
Definition: molecule_to_map.cpp:54
FFTW_FORWARD
Definition: fftw.h:64
VERB_FULL
#define VERB_FULL
Definition: utilities.h:103
molgroup_split_into_slices
Bmolgroup ** molgroup_split_into_slices(Bmolgroup *molgroup, double slice_thickness, int &nslices)
Splits a set of coordinates into slices with a given thickness.
Definition: mol_edit.cpp:158
Bimage::label
void label(Bstring s)
Definition: Bimage.h:217
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:100
electron_wavelength
double electron_wavelength(double volt)
Calculates the wavelength in angstrom from the acceleration voltage.
Definition: ctf.cpp:387
Vector3::y
Type y()
Definition: Vector3.h:138
mol_edit.h
Library routines used for atomic coordinates.
Bimage::fourier_type
FourierType fourier_type()
Definition: Bimage.h:321
Bimage::image
Bsub_image * image
Definition: Bimage.h:183
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:483