compare_hkl.c 7.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * compare_hkl.c
 *
 * Compare reflection lists
 *
 * (c) 2006-2010 Thomas White <taw@physics.org>
 *
 * Part of CrystFEL - crystallography with a FEL
 *
 */


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>

#include "utils.h"
#include "sfac.h"
#include "reflections.h"
Thomas White's avatar
Thomas White committed
27
#include "statistics.h"
28
#include "symmetry.h"
29
30


Thomas White's avatar
Thomas White committed
31
/* Number of bins for plot of resolution shells */
Thomas White's avatar
Thomas White committed
32
33
34
#define NBINS (10)


35
36
static void show_help(const char *s)
{
37
	printf("Syntax: %s [options] <file1.hkl> <file2.hkl>\n\n", s);
38
39
40
41
42
	printf(
"Compare intensity lists.\n"
"\n"
"  -h, --help                 Display this help message.\n"
"  -o, --output=<filename>    Specify output filename for correction factor.\n"
43
"  -y, --symmetry=<sym>       The symmetry of both the input files.\n"
44
"  -p, --pdb=<filename>       PDB file to use (default: molecule.pdb).\n"
Thomas White's avatar
Thomas White committed
45
"      --shells               Plot the figures of merit by resolution.\n"
46
47
48
49
"\n");
}


Thomas White's avatar
Thomas White committed
50
51
static void plot_shells(const double *ref1, const double *ref2,
                        ReflItemList *items, double scale, UnitCell *cell)
Thomas White's avatar
Thomas White committed
52
53
54
55
56
57
58
59
{
	double num[NBINS];
	double den[NBINS];
	double rmin, rmax, rstep;
	int i;
	FILE *fh;

	if ( cell == NULL ) {
Thomas White's avatar
Thomas White committed
60
		ERROR("Need the unit cell to plot resolution shells.\n");
Thomas White's avatar
Thomas White committed
61
62
63
		return;
	}

Thomas White's avatar
Thomas White committed
64
	fh = fopen("shells.dat", "w");
Thomas White's avatar
Thomas White committed
65
	if ( fh == NULL ) {
Thomas White's avatar
Thomas White committed
66
		ERROR("Couldn't open 'shells.dat'\n");
Thomas White's avatar
Thomas White committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
		return;
	}

	for ( i=0; i<NBINS; i++ ) {
		num[i] = 0.0;
		den[i] = 0.0;
	}

	rmin = +INFINITY;
	rmax = 0.0;
	for ( i=0; i<num_items(items); i++ ) {

		struct refl_item *it;
		signed int h, k, l;
81
		double d;
Thomas White's avatar
Thomas White committed
82
83
84
85

		it = get_item(items, i);
		h = it->h;  k = it->k;  l = it->l;

86
87
88
		d = 0.5/resolution(cell, h, k, l);
		if ( d > rmax ) rmax = d;
		if ( d < rmin ) rmin = d;
Thomas White's avatar
Thomas White committed
89
90
91
92
93
94
95
96

	}
	rstep = (rmax-rmin) / NBINS;

	for ( i=0; i<num_items(items); i++ ) {

		struct refl_item *it;
		signed int h, k, l;
97
		double d;
Thomas White's avatar
Thomas White committed
98
		int bin;
99
		double i1, i2, f1, f2;
Thomas White's avatar
Thomas White committed
100
101
102
103

		it = get_item(items, i);
		h = it->h;  k = it->k;  l = it->l;

104
		d = 0.5/resolution(cell, h, k, l);
Thomas White's avatar
Thomas White committed
105

106
		bin = (d-rmin)/rstep;
Thomas White's avatar
Thomas White committed
107
108

		i1 = lookup_intensity(ref1, h, k, l);
109
110
111
112
113
		if ( i1 < 0.0 ) continue;
		f1 = sqrt(i1);
		i2 = lookup_intensity(ref2, h, k, l);
		if ( i2 < 0.0 ) continue;
		f2 = sqrt(i2);
Thomas White's avatar
Thomas White committed
114

115
116
		num[bin] += fabs(f1 - f2);
		den[bin] += fabs(f1 + f2) / 2.0;
Thomas White's avatar
Thomas White committed
117
118
119
120
121
122
123

	}

	for ( i=0; i<NBINS; i++ ) {

		double r2, cen;
		cen = rmin + rstep*i + rstep/2.0;
124
125
		r2 = num[i]/den[i];
		fprintf(fh, "%f %f\n", cen/1.0e-10, r2*100.0);
Thomas White's avatar
Thomas White committed
126
127
128
129
130
131
132

	}

	fclose(fh);
}


133
134
135
136
137
int main(int argc, char *argv[])
{
	int c;
	double *ref1;
	double *ref2;
138
	double *ref2_transformed;
139
	double *out;
140
	UnitCell *cell;
141
142
143
	char *outfile = NULL;
	char *afile = NULL;
	char *bfile = NULL;
Thomas White's avatar
Thomas White committed
144
	char *sym = NULL;
145
	double scale, scale_r2, R1, R2, R1i, Rdiff, pearson;
Thomas White's avatar
Thomas White committed
146
147
	int i, ncom;
	ReflItemList *i1, *i2, *icommon;
Thomas White's avatar
Thomas White committed
148
	int config_shells = 0;
149
	char *pdb = NULL;
150
151
152
153
	double *esd1;
	double *esd2;
	int rej1 = 0;
	int rej2 = 0;
154
155
156
157
158

	/* Long options */
	const struct option longopts[] = {
		{"help",               0, NULL,               'h'},
		{"output",             1, NULL,               'o'},
159
		{"symmetry",           1, NULL,               'y'},
Thomas White's avatar
Thomas White committed
160
		{"shells",             0, &config_shells,     1},
161
		{"pdb",                1, NULL,               'p'},
162
163
164
165
		{0, 0, NULL, 0}
	};

	/* Short options */
166
	while ((c = getopt_long(argc, argv, "ho:y:p:", longopts, NULL)) != -1) {
167
168

		switch (c) {
Thomas White's avatar
Thomas White committed
169
		case 'h' :
170
171
172
			show_help(argv[0]);
			return 0;

Thomas White's avatar
Thomas White committed
173
		case 'o' :
174
175
176
			outfile = strdup(optarg);
			break;

177
178
179
180
		case 'y' :
			sym = strdup(optarg);
			break;

181
182
183
184
		case 'p' :
			pdb = strdup(optarg);
			break;

Thomas White's avatar
Thomas White committed
185
		case 0 :
186
187
			break;

Thomas White's avatar
Thomas White committed
188
		default :
189
190
191
192
193
			return 1;
		}

	}

194
195
196
197
198
	if ( argc != (optind+2) ) {
		ERROR("Please provide exactly two HKL files to compare.\n");
		return 1;
	}

199
200
201
202
	if ( sym == NULL ) {
		sym = strdup("1");
	}

203
204
205
	afile = strdup(argv[optind++]);
	bfile = strdup(argv[optind]);

206
207
208
209
210
211
212
	if ( pdb == NULL ) {
		pdb = strdup("molecule.pdb");
	}

	cell = load_cell_from_pdb(pdb);
	free(pdb);

Thomas White's avatar
Thomas White committed
213
	ref1 = new_list_intensity();
214
215
	esd1 = new_list_sigma();
	i1 = read_reflections(afile, ref1, NULL, NULL, esd1);
Thomas White's avatar
Thomas White committed
216
	if ( i1 == NULL ) {
217
218
219
		ERROR("Couldn't open file '%s'\n", afile);
		return 1;
	}
Thomas White's avatar
Thomas White committed
220
	ref2 = new_list_intensity();
221
222
	esd2 = new_list_sigma();
	i2 = read_reflections(bfile, ref2, NULL, NULL, esd2);
Thomas White's avatar
Thomas White committed
223
	if ( i2 == NULL ) {
224
225
226
227
		ERROR("Couldn't open file '%s'\n", bfile);
		return 1;
	}

Thomas White's avatar
Thomas White committed
228
229
	/* List for output scale factor map */
	out = new_list_intensity();
230

231
232
233
234
235
	/* Find common reflections (taking symmetry into account) */
	icommon = new_items();
	ref2_transformed = new_list_intensity();
	for ( i=0; i<num_items(i1); i++ ) {

Thomas White's avatar
Thomas White committed
236
237
		struct refl_item *it;
		signed int h, k, l;
238
239
		signed int he, ke, le;
		double val1, val2;
240
241
		double sig1, sig2;
		int ig = 0;
242
		double d;
243

244
		it = get_item(i1, i);
Thomas White's avatar
Thomas White committed
245
		h = it->h;  k = it->k;  l = it->l;
246

247
		if ( !find_unique_equiv(i2, h, k, l, sym, &he, &ke, &le) ) {
Thomas White's avatar
Thomas White committed
248
249
			//STATUS("%i %i %i not matched (%f nm).\n", h, k, l,
			//       1.0/(2.0*resolution(cell, h, k, l)/1e9));
250
251
			continue;
		}
252

253
254
		val1 = lookup_intensity(ref1, h, k, l);
		val2 = lookup_intensity(ref2, he, ke, le);
255
		sig1 = lookup_sigma(esd1, h, k, l);
256
		sig2 = lookup_sigma(esd2, he, ke, le);
257
258
259
260
261
262
263
264
265

		if ( val1 < 3.0 * sig1 ) {
			rej1++;
			ig = 1;
		}
		if ( val2 < 3.0 * sig2 ) {
			rej2++;
			ig = 1;
		}
266
267
268
269
270

		d = 0.5/resolution(cell, h, k, l);
		if ( d > 55.0e-10 ) ig = 1;
		//if ( d < 15.0e-10 ) ig = 1;

271
272
		if ( ig ) continue;

273
274
275
		set_intensity(ref2_transformed, h, k, l, val2);
		set_intensity(out, h, k, l, val1/val2);
		add_item(icommon, h, k, l);
276
277

	}
278
	ncom = num_items(icommon);
279
280
281
282
	STATUS("%i reflections with I < 3.0*sigma(I) rejected from '%s'\n",
	       rej1, afile);
	STATUS("%i reflections with I < 3.0*sigma(I) rejected from '%s'\n",
	       rej2, bfile);
283

Thomas White's avatar
Thomas White committed
284
285
	STATUS("%i,%i reflections: %i in common\n",
	       num_items(i1), num_items(i2), ncom);
Thomas White's avatar
Thomas White committed
286
287

	R1 = stat_r1_ignore(ref1, ref2_transformed, icommon, &scale);
288
	STATUS("R1(F) = %5.4f %% (scale=%5.2e) (ignoring negative intensities)\n",
Thomas White's avatar
Thomas White committed
289
290
291
	       R1*100.0, scale);

	R1 = stat_r1_zero(ref1, ref2_transformed, icommon, &scale);
292
	STATUS("R1(F) = %5.4f %% (scale=%5.2e) (zeroing negative intensities)\n",
Thomas White's avatar
Thomas White committed
293
294
	       R1*100.0, scale);

Thomas White's avatar
Thomas White committed
295
	R2 = stat_r2(ref1, ref2_transformed, icommon, &scale_r2);
296
	STATUS("R2(I) = %5.4f %% (scale=%5.2e)\n", R2*100.0, scale_r2);
Thomas White's avatar
Thomas White committed
297

298
299
	R1i = stat_r1_i(ref1, ref2_transformed, icommon, &scale);
	STATUS("R1(I) = %5.4f %% (scale=%5.2e)\n", R1i*100.0, scale);
Thomas White's avatar
Thomas White committed
300
301

	Rdiff = stat_rdiff_ignore(ref1, ref2_transformed, icommon, &scale);
302
	STATUS("Rdiff(F) = %5.4f %% (scale=%5.2e) (ignoring negative intensities)\n",
Thomas White's avatar
Thomas White committed
303
304
305
	       Rdiff*100.0, scale);

	Rdiff = stat_rdiff_zero(ref1, ref2_transformed, icommon, &scale);
306
	STATUS("Rdiff(F) = %5.4f %% (scale=%5.2e) (zeroing negative intensities)\n",
Thomas White's avatar
Thomas White committed
307
308
309
310
311
312
313
314
315
316
317
318
	       Rdiff*100.0, scale);

	pearson = stat_pearson_i(ref1, ref2_transformed, icommon);
	STATUS("Pearson r(I) = %5.4f\n", pearson);

	pearson = stat_pearson_f_ignore(ref1, ref2_transformed, icommon);
	STATUS("Pearson r(F) = %5.4f (ignoring negative intensities)\n",
	       pearson);

	pearson = stat_pearson_f_zero(ref1, ref2_transformed, icommon);
	STATUS("Pearson r(F) = %5.4f (zeroing negative intensities)\n",
	       pearson);
Thomas White's avatar
Thomas White committed
319

Thomas White's avatar
Thomas White committed
320
321
	if ( config_shells ) {
		plot_shells(ref1, ref2_transformed, icommon, scale_r2, cell);
Thomas White's avatar
Thomas White committed
322
323
	}

324
	if ( outfile != NULL ) {
Thomas White's avatar
Thomas White committed
325
		write_reflections(outfile, icommon, out, NULL, NULL, cell);
326
	}
327
328
329

	return 0;
}