| Bsoft 2.0.5 Bernard's software package

mg_merge.cpp
Go to the documentation of this file.
1
9 #include "mg_merge.h"
10 #include "utilities.h"
11
12 // Definition of the global variables
13 extern int verbose; // Level of output to the screen
14
15
31 int img_unique_shift_global_rotate(Bimage* p, Vector3<float>* origin, Vector3<float>* shift, float angle)
32 {
33 Vector3<double> start;
34 Vector3<double> scale(1,1,1), axis(0,0,1);
35 Vector3<long> size(p->size());
36 Matrix3 mat = Matrix3(axis, angle);
37 Bimage* p1;
38
39 p->change_type(Float);
40
41 long n;
42
43 for ( n=0; n<p->images(); n++ ) {
44 // p1 = p->extract(n);
45 // img_transform(p1, size, scale, origin[n], shift[n], mat, FILL_BACKGROUND, 0);
46 p1 = p->transform(n, size, scale, origin[n], shift[n], mat, FILL_BACKGROUND, 0);
47 p->replace(n, p1);
48 delete p1;
49 }
50
51 return n;
52 }
53
54
75 int mg_particle_merge_series(Bproject* project, int mg_ref_select, int mg_index,
76 float mg_rot_ang, int mg_ori_select, Bstring outimg)
77 {
78
79 long nmgs; // total number of micrographs in field
80 long i, j; // indices
81 long ifield; // index for field block
82 long long_ids(0); // flag to test for long micrograph ids
83 double inplane_angle(0); // rotation for an entire micrograph
84 long datasize; // number of data points in images
85 Vector3<float>* shifts = NULL; // array of translational shifts
86 Vector3<float>* origins = NULL; // array of origins
87 Bstring filename; // outimg + micrograph ids
88 Bstring insert("_merged."); // Insert for default file name
89
90 Bimage* pimg = NULL; // Particle image being processed
91 Bimage* pref = NULL; // Reference particle image(s)
92 Bimage* psum = NULL; // Summed image(s)
93
94 Bfield* field; // Field currently being processed
95 Bmicrograph* mg = NULL; // Micrograph currently being processed
96 Bmicrograph* mg_ref = NULL; // Reference micrograph, the one to which other images are aligned
97 Bmicrograph* mg2 = NULL; // Micrograph place holder
98 Bparticle* particle = NULL; // Particle currently being processed
99 Bparticle* particle_ref = NULL; // Reference particle
100
101
102 if ( verbose ) {
103 cout << "Merging particle images on micrograph series:" << endl;
104 if ( mg_ori_select == 0 ) cout << "Origins obtained from parameter files." << endl;
105 else if ( mg_ori_select == 1 ) cout << "Origins obtained from cross-correlation with reference micrograph." << endl;
106 else if ( mg_ori_select == 2 ) cout << "Origins obtained from particle image files." << endl;
107 else if ( mg_ori_select == -1 ) cout << "Images are merged without translational or rotational alignment." << endl;
108 }
109
110 // Loop over all fields in project
111 for ( field = project->field, ifield=0; field; field = field->next, ifield++ ) {
112
113 // Determine reference micrograph for current field
114 mg_ref = field_find_micrograph(field, mg_ref_select, mg_index, mg_rot_ang);
115
116 // Read in reference image file as the image to which the other(s) will be added
117 // -copy to pref if user wishes to find origins
118 if (verbose & VERB_RESULT)
119 cout << endl << "Reference image file for field " << field->id << ": " << mg_ref->fpart << endl;
120
121 psum = read_img(mg_ref->fpart, 1, -1);
122 if ( !psum ) {
123 error_show("Error in mg_particle_merge_series", __FILE__, __LINE__);
124 cerr << "File " << mg_ref->fpart << " was not found or read in properly." << endl;
125 return -1;
126 }
127 psum->change_type(Float); // convert to floating point
128 if ( mg_ori_select == 1 ) pref = psum->copy(); // as reference for finding origins
129
130 datasize = psum->data_size();
131 nmgs = field_count_micrographs(field); // number of micrographs in current field, for normalizing summed images
132
133 // Loop through micrographs in field,
134 // if not reference micrograph, align (if desired) each
135 // image to corresponding reference image, sum images
136 for ( mg = field->mg; mg; mg = mg->next ) if ( mg != mg_ref ) {
137 if (verbose & VERB_RESULT)
138 cout << "Aligning and adding images in " << mg->fpart << " to reference in " << mg_ref->fpart << endl;
139
140 // Calculate rotation for all particles in micrograph, if alignment is desired
141 if ( mg_ori_select > -1 ) {
142 inplane_angle = mg->rot_angle - mg_ref->rot_angle;
143 if (verbose & VERB_RESULT)
144 cout << "in-plane rotation angle = " << (180/M_PI)*inplane_angle << endl;
145 }
146
147 // Get images from "non-reference" micrograph, convert to float
148 pimg = read_img(mg->fpart, 1, -1);
149 pimg->change_type(Float);
150
151 // Check that psum and pimg have the same number of images
152 if ( pimg->images() != psum->images() ) {
153 cerr << "WARNING: The number of images is not consistent (" << psum->images() << " and " << pimg->images() << ") and may cause program to crash." << endl;
154 }
155
156 // Get origins and translational shift of non-std images, then align to reference images
157 if ( mg_ori_select > -1 ) {
158 origins = new Vector3<float>[pimg->images()];
159
160 // get origins from input parameter file
161 if ( mg_ori_select == 0 ) {
162 shifts = new Vector3<float>[psum->images()];
163 for ( i=0, particle=mg->part, particle_ref=mg_ref->part; particle; i++, particle=particle->next, particle_ref=particle_ref->next) {
164 shifts[i] = particle_ref->ori - particle->ori;
165 origins[i] = particle->ori;
166 }
167
168 }
169
170 // find new origins via cross-correlation
171 else if ( mg_ori_select == 1 ) {
172 // img_find_shift(pimg, pref, NULL, pref->sampling()[0]*2, 1e10, pref->sizeX()/4.0, 0, 1);
173 pimg->find_shift(pref, NULL, pref->sampling()[0]*2, 1e10, pref->sizeX()/4.0, 0, 1);
174 for ( i=0, particle=mg->part; particle; i++, particle=particle->next) {
175 shifts[i] = pref->image[i].origin() - pimg->image[i].origin();
176 origins[i] = pimg->image[i].origin();
177 }
178 }
179
180 // get origins from Bsubimage structure
181 else if ( mg_ori_select == 2 ) {
182 shifts = new Vector3<float>[psum->images()];
183 for ( i=0, particle=mg->part, particle_ref=mg_ref->part; particle; i++, particle=particle->next, particle_ref=particle_ref->next) {
184 origins[i] = pimg->image[i].origin();
185 shifts[i] = psum->image[i].origin() - origins[i];
186 }
187 }
188
189 // align non-reference images to reference images
190 img_unique_shift_global_rotate(pimg, origins, shifts, inplane_angle);
191 delete[] shifts;
192 delete[] origins;
193
194 }
195
196 // Add non-reference image to corresponding reference image
197 // -sum background values
198 for ( i=0, j=0; i<datasize; i++, j++ ) psum->set(i, (*psum)[i] + (*pimg)[j]);
199 for ( i=0; i<psum->images(); i++ ) psum->background(i, psum->background(i) + pimg->background(i));
200
201 delete pimg; // free allocated memory for non-reference image
202
203 } // End of for loop (micrographs in field) and if statement (analyze if not a reference micrograph)
204 if ( mg_ori_select == 1 ) delete pref; // used as reference for finding origins
205
206 // Normalize summed images
207 for ( i=0; i<datasize; i++ ) psum->set(i, (*psum)[i] / nmgs);
208 for ( i=0; i<psum->images(); i++ ) psum->background(i, psum->background(i) / nmgs);
209
210 // Write out summed, normalized images
211 long_ids = 0;
212 if ( outimg.length() ) { // If adding micrograph ids to filename, make sure all ids are <= 6 characters
213 for ( mg = field->mg; mg; mg = mg->next ) if ( (mg->id.length() > 6) || (mg->id.length() == 0) ) long_ids++;
214 if ( long_ids )
215 cerr << "Error: Micrograph ids are too long to add together, revert to default file name." << endl;
216 } else long_ids = 1;
217
218 if ( !long_ids ) { // Add micrograph ids or "_merged" to an input file name
219 filename = outimg.pre_rev('.') + "_" + mg_ref->id + "." + outimg.post_rev('.');
220 for ( mg = field->mg; mg; mg = mg->next ) if ( mg != mg_ref ) { // Test if micrograph is reference, if not add id to file name
221 filename = filename.pre_rev('.') + "_" + mg->id + "." + filename.post_rev('.');
222 }
223 } else filename = mg_ref->fpart.pre_rev('.') + insert + mg_ref->fpart.post_rev('.');
224
225 if ( verbose & VERB_RESULT )
226 cout << "Writing summed images to " << filename << endl; // Write images to file
227
228 psum->label("Written by Bsoft: Merged image");
229 write_img(filename, psum, 0);
230 delete psum;
231
232 // Delete non-reference micrographs from project structure
233 for ( mg = field->mg; mg; ) {
234 mg2 = mg->next;
235 if ( mg != mg_ref ) micrograph_kill(mg);
236 mg = mg2;
237 }
238 field->mg = mg_ref;
239 mg_ref->next = NULL;
240 mg_ref->block = ifield;
241 mg_ref->fpart = filename;
242
243 } // end of loop over all fields in project
244
245 return 0;
246 }
247
271 int mg_particle_unmerge(Bproject* project, Bproject* orientations, float fom_diff)
272 {
273
274 Bfield* field = NULL; // Field-of-view currently being processed
275 Bfield* fieldo = NULL; // Corresponding field-of-view with orientations to be used
276 Bmicrograph* mg = NULL; // Micrograph currently being processed
277 Bmicrograph* mgo = NULL; // Corresponding micrograph with orientations to be used
278 Bparticle* particle = NULL; // Particle currently being processed
279 Bparticle* particleo = NULL; // Corresponding micrograph with orientation to be used
280 int change; // Flag to substitute values from orientations structure
281 int ccount(0); // Counts number of values that are changed
282 int num, numo; // For checking that the number of particles is consistent
283 int total; // Total number of particles, changed or unchanged
284 int ucount(0); // Counts number of values that are not changed
285 float rotang_diff; // Difference in rotation angle between mgo and mg
286
287 project->euler_flag = orientations->euler_flag; // project gets euler and omega flags of the orientations, since
288 project->omega_flag = orientations->omega_flag; // these general parameters relate to the orientation
289
290 for ( field=project->field, fieldo=orientations->field; field && fieldo; field=field->next, fieldo=fieldo->next ) {
291 if ( field->id != fieldo->id ) {
292 error_show("Error in mg_particle_unmerge", __FILE__, __LINE__);
293 cerr << "Field-of-view IDs do not match. Please check your data." << endl;
294 cerr << "ID of reference field: " << fieldo->id << endl;
295 cerr << "ID of other field: " << field->id << endl;
296 return -1;
297 }
298 if ( verbose ) cout << "\nUnmerging field: " << fieldo->id << endl;
299 for ( mgo=fieldo->mg; mgo; mgo=mgo->next ) {
300 if ( verbose & VERB_PROCESS ) cout << " reference micrograph: " << mgo->id << endl;
301 for ( mg=field->mg; mg; mg=mg->next ) {
302 if ( verbose & VERB_PROCESS ) cout << " unmerging " << mg->id << endl;
303 numo = micrograph_count_particles(mgo); num = micrograph_count_particles(mg);
304 if ( num != numo ) {
305 error_show("Error in mg_particle_unmerge", __FILE__, __LINE__);
306 cerr << "Error: The number of particles in micrographs " << mg->id
307 << " (" << num << ") and " << mgo->id << " (" << numo
308 << ") do not match." << endl;
309 cerr << "Please check your data" << endl;
310 return -1;
311 }
312 rotang_diff = mg->rot_angle - mgo->rot_angle;
313 for ( particle=mg->part, particleo=mgo->part; particle && particleo; particle=particle->next, particleo=particleo->next ) {
314 if ( particle->id != particleo->id ) {
315 error_show("Error in mg_particle_unmerge", __FILE__, __LINE__);
316 cerr << "Error: Particle IDs do not match. Please check your data" << endl;
317 return -1;
318 }
319 change = 1;
320 if ( fom_diff > 0 ) {
321 if ( particle->fom[0] - particleo->fom[0] > fom_diff ) { // Don't change if particle FOM is better by fom_diff
322 change = 0;
323 ucount++;
324 }
325 }
326 if ( change ) {
327 particle->view = particleo->view;
328 particle->fom[0] = particleo->fom[0];
329 particle->sel = particleo->sel;
330 particle->view[3] += rotang_diff; // applies difference in micrograph rotation angle
331 ccount++;
332 }
333 }
334 }
335 }
336 }
337
338 total = ccount + ucount;
339 if ( verbose ) {
340 cout << "\nUn-merge option:" << endl;
341 if ( fom_diff > 0 ) {
342 cout << "Total number of particles: " << total << endl;
343 cout << "Number of unchanged particles: " << ucount << endl;
344 cout << "FOM-difference threshold: " << fom_diff << endl << endl;
345 } else
346 cout << "Particle orientations changed: " << ccount << endl << endl;
347 }
348
349 return 0;
350 }
351
352
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bparticle::id
int id
Definition: mg_processing.h:92
Bimage::replace
int replace(Bimage *img)
Replaces the data with that from the given image.
Definition: Bimage.cpp:2828
FILL_BACKGROUND
#define FILL_BACKGROUND
Definition: utilities.h:174
insert
string insert(string &filename, string ins)
Definition: string_util.cpp:48
Bparticle::view
View view
Definition: mg_processing.h:101
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
Bmicrograph::id
Bstring id
Definition: mg_processing.h:202
utilities.h
Header file for general utilities.
mg_particle_merge_series
int mg_particle_merge_series(Bproject *project, int mg_ref_select, int mg_index, float mg_rot_ang, int mg_ori_select, Bstring outimg)
Aligns and merges (sums) 2D particle images from a focal, or other, series and writes to new image fi...
Definition: mg_merge.cpp:75
Bparticle::fom
double fom[NFOM]
Definition: mg_processing.h:102
Matrix3
Definition: Matrix3.h:17
Bstring::length
long length() const
Definition: Bstring.cpp:263
project
Bproject * project
Definition: bshow.cpp:31
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bproject::omega_flag
int omega_flag
Definition: mg_processing.h:341
read_img
Bimage * read_img(char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:76
Bfield::next
Bfield * next
Definition: mg_processing.h:258
mg_merge.h
Header file for functions to merge images.
Bmicrograph::part
Bparticle * part
Definition: mg_processing.h:239
Float
Definition: utilities.h:157
Bimage
General image parameter class.
Definition: Bimage.h:163
Bmicrograph::fpart
Bstring fpart
Definition: mg_processing.h:207
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
Bfield
Definition: mg_processing.h:257
M_PI
#define M_PI
Definition: utilities.h:59
img_unique_shift_global_rotate
int img_unique_shift_global_rotate(Bimage *p, Vector3< float > *origin, Vector3< float > *shift, float angle)
Shifts and rotates each image as defined in individual shift vectors.
Definition: mg_merge.cpp:31
micrograph_kill
int micrograph_kill(Bmicrograph *mg)
Frees a whole micrograph parameter structure.
Definition: mg_processing.cpp:1288
Bfield::id
Bstring id
Definition: mg_processing.h:259
Bimage::label
void label(string s)
Definition: Bimage.h:235
Bproject::field
Bfield * field
Definition: mg_processing.h:343
Bmicrograph
Definition: mg_processing.h:200
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
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
field_find_micrograph
Bmicrograph * field_find_micrograph(Bfield *field, int mg_select, int mg_index, double mg_ang)
Returns a pointer to a specific micrograph in a field-of-view structure based on a unique characteris...
Definition: mg_processing.cpp:183
micrograph_count_particles
long micrograph_count_particles(Bmicrograph *mg)
Counts all the particles in the micrograph structure.
Definition: mg_processing.cpp:1132
mg_particle_unmerge
int mg_particle_unmerge(Bproject *project, Bproject *orientations, float fom_diff)
Gives corresponding particles in a field-of-view the same orientation, figure-of-merit (FOM),...
Definition: mg_merge.cpp:271
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
VERB_RESULT
#define VERB_RESULT
Definition: utilities.h:105
Bparticle
Definition: mg_processing.h:89
Bmicrograph::block
int block
Definition: mg_processing.h:204
Bmicrograph::rot_angle
double rot_angle
Definition: mg_processing.h:219
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
Vector3< float >
Bimage::find_shift
int find_shift(Bimage *pref, Bimage *pmask, double hires, double lores, double radius, double sigma, int refine_flag)
Calculates a cross-correlation map to find the shift for the pair of images.
Definition: Bimage_correlate.cpp:932
field_count_micrographs
long field_count_micrographs(Bfield *field)
Counts all the micrographs in the field-of-view structure.
Definition: mg_processing.cpp:1067
Bimage::images
long images()
Definition: Bimage.h:491
Bstring::pre_rev
Bstring pre_rev(char c)
Definition: Bstring.cpp:413
Bparticle::next
Bparticle * next
Definition: mg_processing.h:90
verbose
int verbose
Bimage::background
double background(long nn)
Definition: Bimage.h:542
Bproject::euler_flag
int euler_flag
Definition: mg_processing.h:340
Bimage::data_size
long data_size()
Definition: Bimage.h:255
error_show
int error_show(string message, string file, int line)
Displays the error with file and line reference.
Definition: utilities.cpp:755
Bproject
Definition: mg_processing.h:333
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
Bmicrograph::next
Bmicrograph * next
Definition: mg_processing.h:201