| Bsoft 2.0.5 Bernard's software package

bmapdist.cpp
Go to the documentation of this file.
1
9 #include "rwimg.h"
10 #include "rwmg.h"
11 #include "mg_img_proc.h"
12 #include "Matrix.h"
13 #include "cluster.h"
14 #include "linked_list.h"
15 #include "file_util.h"
16 #include "utilities.h"
17 #include "options.h"
18 #include "timer.h"
19
20 // Declaration of global variables
21 extern int verbose; // Level of output to the screen
22
23 // Function prototypes
24 Matrix img_map_distance(Bstring* file_list, int type, double* cutoff,
25 double hires, double lores, Bimage* pmask);
26 int project_set_selection(Bproject* project, long n, long* idx);
27 int project_rec_select(Bproject* project, long* idx);
28
29 Bstring* project_get_filenames(Bproject* project, int flag)
30 {
31 Bstring* file_list = NULL;
32 Bparticle* part = project->class_avg;
33 Breconstruction* rec;
34
35 if ( flag ) {
36 if ( part )
37 // for ( part = project->class_avg; part; part = part->next )
38 if ( part->fpart.length() > 3 ) string_add(&file_list, part->fpart);
39 } else {
40 for ( rec = project->rec; rec; rec = rec->next )
41 if ( rec->frec.length() > 3 ) string_add(&file_list, rec->frec);
42 }
43
44 return file_list;
45 }
46
47
48 // Usage assistance
49 const char* use[] = {
50 " ",
51 "Usage: bmapdist [options] input.star/input.img [input.star/input.img]",
52 "---------------------------------------------------------------------",
53 "Calculates distance criterions between a set of 2D images or 3D maps.",
54 "CC: Correlation coefficient.",
55 "R: R factor (Euclidean distance).",
56 "FSC: Resolution based on Fourier shell correlation.",
57 "DPR: Resolution based on differential phase residual.",
58 "Clustering: The preference value should be set to the approximate average in the",
59 " similarity matrix. The damping factor should be ~0.5, or between 0.1 and 0.9.",
60 " ",
61 "Actions:",
62 "-type fsc Output type of criterion: cc (default), r, fsc, dpr.",
63 "-preference -10 Homogenous preference value for clustering.",
64 "-TwoD Compare 2D images rather than 3D maps.",
65 " ",
66 "Parameters:",
67 "-verbose 7 Verbosity of output.",
68 "-resolution 15.3 Resolution limit (angstrom).",
69 "-cutoff 0.5,45 Resolution cutoffs for FSC and DPR.",
70 "-lambda 0.6 Damping factor for clustering (default 0.5).",
71 " ",
72 "Input:",
73 "-mask mask.tif Real space mask (same size as input maps).",
74 " ",
75 "Output:",
76 "-output file.star Output parameter file.",
77 "-matrix mat.dat Output comparison matrix file.",
78 " ",
79 NULL
80 };
81
82 int main(int argc, char **argv)
83 {
84 // Initialize variables
85 int type(0); // Default type is CC
86 int flag(0); // Flag to indicate 2D images
87 double hires(0.01); // Default resolution is all-inclusive
88 double lores(1e37); // Default resolution is all-inclusive
89 double cutoff[4] = {0.5,45,1,0.5}; // Cutoff values
90 double pref(-1e37); // Preference value for clustering
91 double lambda(0.5); // Damping factor for clustering
92 Bstring real_mask_file; // Real space mask file
93 Bstring outfile; // Output parameter file
94 Bstring matfile; // Output comparison matrix file
95
96 int optind;
97 Boption* option = get_option_list(use, argc, argv, optind);
98 Boption* curropt;
99 for ( curropt = option; curropt; curropt = curropt->next ) {
100 if ( curropt->tag == "type" ) {
101 if ( curropt->value[0] == 'r' ) type = 1;
102 if ( curropt->value[0] == 'f' ) type = 2;
103 if ( curropt->value[0] == 'd' ) type = 3;
104 }
105 if ( curropt->tag == "preference" )
106 if ( ( pref = curropt->value.real() ) < -1e36 )
107 cerr << "-preference: A preference value must be specified!" << endl;
108 if ( curropt->tag == "TwoD" ) flag = 1;
109 if ( curropt->tag == "resolution" )
110 if ( curropt->values(hires, lores) < 1 )
111 cerr << "-resolution: A resolution limit must be specified!" << endl;
112 if ( curropt->tag == "cutoff" )
113 if ( curropt->values(cutoff[0], cutoff[1], cutoff[2], cutoff[3]) < 1 )
114 cerr << "-cutoff: A cuttoff must be specified!" << endl;
115 if ( curropt->tag == "lambda" )
116 if ( ( lambda = curropt->value.real() ) < 0.001 )
117 cerr << "-lambda: A damping factor must be specified!" << endl;
118 if ( curropt->tag == "mask" )
119 real_mask_file = curropt->filename();
120 if ( curropt->tag == "output" )
121 outfile = curropt->filename();
122 if ( curropt->tag == "matrix" )
123 matfile = curropt->filename();
124 }
125 option_kill(option);
126
127 double ti = timer_start();
128
129 // Read all the parameter files
130 Bstring* file_list = NULL;
131 while ( optind < argc ) string_add(&file_list, argv[optind++]);
132 if ( !file_list ) {
133 cerr << "Error: No image or parameter files specified!" << endl;
134 bexit(-1);
135 }
136
137 Bproject* project = NULL;
138
139 if ( file_type(*file_list) == Micrograph ) {
140 project = read_project(file_list);
141 string_kill(file_list);
142 file_list = project_get_filenames(project, flag);
143 }
144
145 if ( !file_list ) {
146 cerr << "Error: No image file names found!" << endl;
147 bexit(-1);
148 }
149
150 Bimage* pmask = NULL;
151 if ( real_mask_file.length() )
152 pmask = read_img(real_mask_file, 1, 0);
153
154 Matrix matrix = img_map_distance(file_list, type, cutoff, hires, lores, pmask);
155
156 long i, *idx, ncluster(0);
157 if ( matrix.rows() ) {
158 if ( pref > -1e30 ) {
159 for ( i=0; i<matrix.rows(); i++ )
160 matrix[i][i] = pref;
161 idx = affin_prop_clustering(matrix, 500, 50, lambda, ncluster);
162 if ( project ) {
163 if ( flag )
164 project_set_selection(project, ncluster, idx);
165 else
166 project_rec_select(project, idx);
167 }
168 delete[] idx;
169 }
170
171 if ( matfile.length() )
172 matrix.write(matfile);
173
174 }
175
176 // Write an output parameter file if a name is given
177 if ( project && outfile.length() ) {
178 project_update_comment(project, argc, argv);
179 write_project(outfile, project, 0, 0);
180 }
181
182 project_kill(project);
183 delete pmask;
184
185 if ( verbose & VERB_TIME )
186 timer_report(ti);
187
188 bexit(0);
189 }
190
191 Matrix img_map_distance(Bstring* file_list, int type, double* cutoff,
192 double hires, double lores, Bimage* pmask)
193 {
194 if ( type < 0 || type > 3 ) type = 0;
195
196 if ( hires < 0.01 ) hires = 0.01;
197
198 // long nmap = count_list((char *)file_list);
199 // Main loop over all reference maps
200 long i, j, ii, jj, n1, n2, nmap(0);
201 Bstring* fn1;
202 Bstring* fn2;
203 Bimage* p1 = NULL;
204 Bimage* p2 = NULL;
205
206 for ( fn1 = file_list; fn1; fn1 = fn1->next ) {
207 p1 = read_img(*fn1, 0, -1);
208 nmap += p1->images();
209 delete p1;
210 }
211
212 if ( verbose ) {
213 cout << "Calculating the similarities and differences between " << nmap << " images:" << endl;
214 cout << "Resolution limit: " << hires << endl;
215 if ( pmask )
216 cout << "Mask: " << pmask->file_name() << endl;
217 }
218
219 Matrix matrix;
220
221 if ( nmap < 2 ) return matrix;
222
223 Bimage* pc = NULL;
224 double* CC = new double[nmap*nmap];
225 double* R = new double[nmap*nmap];
226 double* FSC = new double[nmap*nmap];
227 double* DPR = new double[nmap*nmap];
228 Bplot* plot;
229
230 cout << "Map1\tMap2\tCC\tR\tFSC\tDPR" << endl;
231 for ( i=0, fn1 = file_list; fn1; fn1 = fn1->next ) {
232 p1 = read_img(*fn1, 0, -1);
233 if ( !p1 ) bexit(-1);
234 n1 = p1->images();
235 delete p1;
236 for ( ii=0; ii<n1; ++ii, ++i ) {
237 p1 = read_img(*fn1, 1, ii);
238 p1->change_type(Float);
239 p1->rescale_to_avg_std(0, 1);
240 if ( pmask ) p1->multiply(pmask);
241 for ( j=0, fn2 = file_list; j<i && fn2; fn2 = fn2->next ) {
242 p2 = read_img(*fn2, 0, -1);
243 if ( !p2 ) bexit(-1);
244 n2 = p2->images();
245 delete p2;
246 for ( jj=0; j<i && jj<n2; ++jj, ++j ) {
247 p2 = read_img(*fn2, 1, jj);
248 p2->change_type(Float);
249 p2->rescale_to_avg_std(0, 1);
250 if ( pmask ) p2->multiply(pmask);
251 CC[i*nmap+j] = CC[j*nmap+i] = p1->correlate(p2);
252 R[i*nmap+j] = R[j*nmap+i] = p1->R_factor(p2);
253 pc = p1->resolution_prepare(p2);
254 delete p2;
255 plot = pc->fsc_dpr(hires, 1);
256 delete pc;
257 FSC[i*nmap+j] = FSC[j*nmap+i] = 1/plot->cut(1, cutoff[0], -1);
258 DPR[i*nmap+j] = DPR[j*nmap+i] = 1/plot->cut(2, cutoff[1], 1);
259 delete plot;
260 cout << *fn1 << "(" << i << ")" << tab << *fn2 << "(" << j << ")" << tab <<
261 CC[i*nmap+j] << tab << R[i*nmap+j] << tab <<
262 FSC[i*nmap+j] << tab << DPR[i*nmap+j] << endl;
263 }
264 }
265 delete p1;
266 }
267 }
268
269 // All CC values
270 cout << endl << "Correlation coefficients:" << endl;
271 for ( i=0; i<nmap; i++ ) {
272 CC[i*nmap+i] = 1;
273 cout << tab << i+1;
274 }
275 cout << endl;
276 for ( i=0; i<nmap; i++ ) {
277 cout << i+1;
278 for ( j=0; j<nmap; j++ )
279 cout << tab << CC[i*nmap+j];
280 cout << endl;
281 }
282 cout << endl;
283
284 // The negative logarithm of the CC values
285 cout << "-log(Correlation coefficients):" << endl;
286 for ( i=0; i<nmap; i++ )
287 cout << tab << i+1;
288 cout << endl;
289 for ( i=0; i<nmap; i++ ) {
290 cout << i+1;
291 for ( j=0; j<nmap; j++ )
292 cout << tab << -log(CC[i*nmap+j]);
293 cout << endl;
294 }
295 cout << endl;
296
297 // All R values
298 cout << "R factors:" << endl;
299 for ( i=0; i<nmap; i++ ) {
300 R[i*nmap+i] = 0;
301 cout << tab << i+1;
302 }
303 cout << endl;
304 for ( i=0; i<nmap; i++ ) {
305 cout << i+1;
306 for ( j=0; j<nmap; j++ )
307 cout << tab << R[i*nmap+j];
308 cout << endl;
309 }
310 cout << endl;
311
312 // The FSC values
313 cout << "Resolution based on Fourier shell correlation:" << endl;
314 cout << "Cutoff: " << cutoff[0] << endl;
315 for ( i=0; i<nmap; i++ ) {
316 cout << tab << i+1;
317 FSC[i*nmap+i] = hires;
318 }
319 cout << endl;
320 for ( i=0; i<nmap; i++ ) {
321 cout << i+1;
322 for ( j=0; j<nmap; j++ )
323 cout << tab << FSC[i*nmap+j];
324 cout << endl;
325 }
326 cout << endl;
327
328 // The DPR values
329 cout << "Resolution based on differential phase residuals:" << endl;
330 cout << "Cutoff: " << cutoff[1] << endl;
331 for ( i=0; i<nmap; i++ ) {
332 cout << tab << i+1;
333 DPR[i*nmap+i] = hires;
334 }
335 cout << endl;
336 for ( i=0; i<nmap; i++ ) {
337 cout << i+1;
338 for ( j=0; j<nmap; j++ )
339 cout << tab << DPR[i*nmap+j];
340 cout << endl;
341 }
342 cout << endl;
343
344 matrix = Matrix(nmap, nmap);
345
346 Bstring label;
347 for ( i=0; i<nmap; i++ ) {
348 switch ( type ) {
349 case 0:
350 for ( j=0; j<nmap; j++ ) matrix[i][j] = CC[i*nmap+j];
351 break;
352 case 1:
353 for ( j=0; j<nmap; j++ ) matrix[i][j] = R[i*nmap+j];
354 break;
355 case 2:
356 for ( j=0; j<nmap; j++ ) matrix[i][j] = FSC[i*nmap+j];
357 break;
358 case 3:
359 for ( j=0; j<nmap; j++ ) matrix[i][j] = DPR[i*nmap+j];
360 break;
361 }
362 }
363
364 delete[] CC;
365 delete[] R;
366 delete[] FSC;
367 delete[] DPR;
368
369 return matrix;
370 }
371
372 int project_set_selection(Bproject* project, long n, long* idx)
373 {
374 long i, j;
375 Bimage* p = NULL;
376
377 if ( project->class_avg && project->class_avg->fpart.length() )
378 p = read_img(project->class_avg->fpart, 1, -1);
379 else {
380 cerr << "Error: No class averages!" << endl;
381 return -1;
382 }
383
384 Bstring filename(project->class_avg->fpart);
385 filename = filename.pre_rev('.') + "_cluster." + filename.post_rev('.');
386
387 if ( verbose ) {
388 cout << "Replacing class averages:" << endl;
389 cout << "Old number: " << p->images() << endl;
390 cout << "New number: " << n << endl;
391 cout << "New file name: " << filename << endl;
392 }
393
394 Bfield* field = project->field;
395 Bmicrograph* mg = field->mg;
396 Bparticle* part = NULL;
397
398 for ( field = project->field; field; field = field->next )
399 for ( mg = field->mg; mg; mg = mg->next )
400 for ( part = mg->part; part; part = part->next )
401 if ( part->sel )
402 part->sel = idx[part->sel-1] + 1;
403
404 Bimage* pnu = p->copy_header(n);
405 pnu->data_alloc();
406 Bimage* p1;
407 Bparticle* partlist = NULL;
408 Bparticle* nupart = NULL;
409
410 for ( i=j=0, part = project->class_avg; i < p->images(); ++i, part = part->next ) {
411 if ( i == idx[i] ) {
412 nupart = particle_copy(&partlist, part);
413 nupart->fpart = filename;
414 nupart->id = ++j;
415 nupart->group = i;
416 nupart->sel = 0;
417 }
418 }
419
420 for ( i=0, part = project->class_avg; i < p->images(); ++i, part = part->next ) {
421 for ( j=0, nupart = partlist; nupart; ++j, nupart = nupart->next )
422 if ( nupart->group == idx[i] ) break;
423 nupart->sel += part->sel;
424 p1 = p->extract(i);
425 pnu->add(j, p1);
426 delete p1;
427 }
428
429 pnu->statistics();
430
431 for ( j=0; j<pnu->images(); ++j )
432 pnu->rescale_to_avg_std(j, 0, 1);
433
434 particle_kill(project->class_avg);
435 project->class_avg = partlist;
436
437 write_img(filename, pnu, 0);
438
439 delete pnu;
440 delete p;
441
442 return 0;
443 }
444
445
446 int project_rec_select(Bproject* project, long* idx)
447 {
448 long i;
449 Breconstruction* rec;
450
451 for ( i=0, rec = project->rec; rec; rec = rec->next, i++ ) {
452 rec->select = idx[i] + 1;
453 }
454
455 return 0;
456 }
457
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
write_project
int write_project(const char *filename, Bproject *project)
Writing micrograph parameters to a file.
Definition: rwmg.cpp:320
Bparticle::id
int id
Definition: mg_processing.h:92
rwmg.h
Header file for reading and writing micrograph parameters.
Bstring::real
double real()
Definition: Bstring.cpp:545
Bplot::cut
double cut(long icol, double threshold, int dir=1)
Definition: Bplot.h:246
string_add
Bstring * string_add(Bstring **list, const char *string)
Adds a string to a linked list.
Definition: Bstring.cpp:705
Bimage::copy_header
Bimage * copy_header()
Definition: Bimage.h:650
Bproject::rec
Breconstruction * rec
Definition: mg_processing.h:344
Matrix::rows
long rows()
Definition: Matrix.h:153
Bimage::add
void add(long j, double v)
Definition: Bimage.h:308
verbose
int verbose
utilities.h
Header file for general utilities.
particle_copy
Bparticle * particle_copy(Bparticle **partlist, Bparticle *part)
Adds one particle onto a list of particle parameters.
Definition: mg_processing.cpp:1409
Boption::value
Bstring value
Definition: options.h:30
Breconstruction
Definition: mg_processing.h:280
Boption::tag
Bstring tag
Definition: options.h:29
mg_img_proc.h
Header file for image processing from micrograph structures.
file_type
FileType file_type(const char *filename)
Checks the file type using the extension and contents.
Definition: file_util.cpp:178
Bimage::resolution_prepare
Bimage * resolution_prepare(Bimage *p)
Definition: Bimage_resolution.cpp:17
project_set_selection
int project_set_selection(Bproject *project, long n, long *idx)
Definition: bmapdist.cpp:372
read_project
Bproject * read_project(const char *filename, int flags=0)
Reading micrograph parameters from files.
Definition: rwmg.cpp:140
main
int main(int argc, char **argv)
Definition: bmapdist.cpp:82
Bstring::length
long length() const
Definition: Bstring.cpp:263
affin_prop_clustering
long * affin_prop_clustering(Matrix s, long maxit, long convit, double lambda, long &ncluster)
Generate clusters from a similarity matrix using affinity propagation.
Definition: cluster.cpp:102
project
Bproject * project
Definition: bshow.cpp:31
particle_kill
int particle_kill(Bparticle *part)
Frees a list of particles.
Definition: mg_processing.cpp:1323
Matrix.h
Generalized matrix class.
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
get_option_list
Boption * get_option_list(const char *use[], int argc, char *argv[], int &optind)
Parses command line arguments based on a template.
Definition: options.cpp:40
read_img
Bimage * read_img(char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:76
Bimage::correlate
double correlate(Bimage *p)
Calculates correlation coefficient between two images.
Definition: Bimage_correlate.cpp:36
Boption::filename
Bstring filename()
Definition: options.h:85
Bfield::next
Bfield * next
Definition: mg_processing.h:258
Bmicrograph::part
Bparticle * part
Definition: mg_processing.h:239
timer.h
Utilities for timing functions.
Float
Definition: utilities.h:157
Bimage
General image parameter class.
Definition: Bimage.h:163
Micrograph
Definition: file_util.h:23
Bimage::data_alloc
unsigned char * data_alloc()
Definition: Bimage.h:256
Bparticle::sel
long sel
Definition: mg_processing.h:103
Bfield
Definition: mg_processing.h:257
linked_list.h
Header file for generalized linked list functions.
Bimage::extract
Bimage * extract(long nn)
Extracts one sub-image into new image structure.
Definition: Bimage_extract.cpp:21
Bimage::statistics
long statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
Bstring::next
Bstring * next
Definition: Bstring.h:31
Boption
A class for a command line input option.
Definition: options.h:26
Bproject::field
Bfield * field
Definition: mg_processing.h:343
VERB_TIME
#define VERB_TIME
Definition: utilities.h:110
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
Bimage::R_factor
double R_factor(Bimage *p)
Calculates an R factor between two images.
Definition: Bimage_correlate.cpp:218
Bmicrograph
Definition: mg_processing.h:200
use
const char * use[]
Definition: bmapdist.cpp:49
write_img
int write_img(const char *filename, Bimage *p, int compression)
General driver function to write multiple image formats.
Definition: rwimg.cpp:280
Bproject::class_avg
Bparticle * class_avg
Definition: mg_processing.h:345
Bparticle::group
int group
Definition: mg_processing.h:93
file_util.h
Header file for file checking functions.
Bparticle::fpart
Bstring fpart
Definition: mg_processing.h:91
Bimage::fsc_dpr
Bplot * fsc_dpr(double hi_res, double sampling_ratio=1, int flag=0)
Calculates an FSC and DPR curves from two images.
Definition: Bimage_resolution.cpp:92
Bfield::mg
Bmicrograph * mg
Definition: mg_processing.h:264
Bstring::post_rev
Bstring post_rev(char c)
Definition: Bstring.cpp:428
Boption::next
Boption * next
Definition: options.h:28
Bparticle
Definition: mg_processing.h:89
Matrix
Definition: Matrix.h:21
Bstring
Definition: Bstring.h:29
project_kill
int project_kill(Bproject *project)
Frees a whole project.
Definition: mg_processing.cpp:1224
Breconstruction::select
long select
Definition: mg_processing.h:283
Matrix::write
void write(Bstring &filename)
Definition: Matrix.h:95
project_rec_select
int project_rec_select(Bproject *project, long *idx)
Definition: bmapdist.cpp:446
timer_report
double timer_report(double lasttime)
Reports the time elapsed since a given time.
Definition: timer.cpp:67
cluster.h
Header file for clustering functions.
option_kill
int option_kill(Boption *option)
Deallocates a linked list of option structures.
Definition: options.cpp:109
Breconstruction::frec
Bstring frec
Definition: mg_processing.h:287
rwimg.h
Header file for 2D and 3D image I/O.
options.h
Header file for option handlers.
Bimage::images
long images()
Definition: Bimage.h:491
img_map_distance
Matrix img_map_distance(Bstring *file_list, int type, double *cutoff, double hires, double lores, Bimage *pmask)
Definition: bmapdist.cpp:191
Bstring::pre_rev
Bstring pre_rev(char c)
Definition: Bstring.cpp:413
project_update_comment
int project_update_comment(Bproject *project, int n, char **strings)
Puts a set of strings and time in the main comment of a project.
Definition: rwmg.cpp:468
Bparticle::next
Bparticle * next
Definition: mg_processing.h:90
Boption::values
long values(T1 &v1, T2 &v2)
Definition: options.h:115
bexit
int bexit(int value)
Exit function for cleanup and debugging.
Definition: utilities.cpp:273
Breconstruction::next
Breconstruction * next
Definition: mg_processing.h:281
project_get_filenames
Bstring * project_get_filenames(Bproject *project, int flag)
Definition: bmapdist.cpp:29
timer_start
double timer_start()
Starts timer and prints the time.
Definition: timer.cpp:52
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bproject
Definition: mg_processing.h:333
string_kill
int string_kill(Bstring *list)
Kills a string linked list.
Definition: Bstring.cpp:760
Bplot
Definition: Bplot.h:146
Bmicrograph::next
Bmicrograph * next
Definition: mg_processing.h:201