compare_hkl.c 7.36 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 */
32
#define NBINS (10)
Thomas White's avatar
Thomas White committed
33
34


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
{
	double num[NBINS];
Thomas White's avatar
Thomas White committed
54
	int cts[NBINS];
Thomas White's avatar
Thomas White committed
55
	double den;
Thomas White's avatar
Thomas White committed
56
57
	double rmin, rmax, rstep;
	int i;
Thomas White's avatar
Thomas White committed
58
	int ctot;
Thomas White's avatar
Thomas White committed
59
60
61
	FILE *fh;

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

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

	for ( i=0; i<NBINS; i++ ) {
		num[i] = 0.0;
Thomas White's avatar
Thomas White committed
74
		cts[i] = 0;
Thomas White's avatar
Thomas White committed
75
76
77
78
79
80
81
82
	}

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

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

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

88
		d = resolution(cell, h, k, l) * 2.0;
89
90
		if ( d > rmax ) rmax = d;
		if ( d < rmin ) rmin = d;
Thomas White's avatar
Thomas White committed
91
92
93
94

	}
	rstep = (rmax-rmin) / NBINS;

Thomas White's avatar
Thomas White committed
95
	den = 0.0;
Thomas White's avatar
Thomas White committed
96
	ctot = 0;
Thomas White's avatar
Thomas White committed
97
98
99
100
	for ( i=0; i<num_items(items); i++ ) {

		struct refl_item *it;
		signed int h, k, l;
101
		double d;
Thomas White's avatar
Thomas White committed
102
		int bin;
103
		double i1, i2, f1, f2;
Thomas White's avatar
Thomas White committed
104
105
106
107

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

108
		d = resolution(cell, h, k, l) * 2.0;
Thomas White's avatar
Thomas White committed
109

110
		bin = (d-rmin)/rstep;
Thomas White's avatar
Thomas White committed
111
		if ( bin == NBINS ) bin = NBINS-1;
Thomas White's avatar
Thomas White committed
112
113

		i1 = lookup_intensity(ref1, h, k, l);
114
115
116
117
118
		if ( i1 < 0.0 ) continue;
		f1 = sqrt(i1);
		i2 = lookup_intensity(ref2, h, k, l);
		if ( i2 < 0.0 ) continue;
		f2 = sqrt(i2);
119
		f2 *= scale;
Thomas White's avatar
Thomas White committed
120

121
		num[bin] += fabs(f1 - f2);
Thomas White's avatar
Thomas White committed
122
		den += (f1 + f2) / 2.0;
Thomas White's avatar
Thomas White committed
123
124
		cts[bin]++;
		ctot++;
Thomas White's avatar
Thomas White committed
125
126
127
128
129

	}

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

130
		double r, cen;
Thomas White's avatar
Thomas White committed
131
		cen = rmin + rstep*i + rstep/2.0;
132
		r = (num[i]/den)*((double)ctot/cts[i]);
Thomas White's avatar
Thomas White committed
133
		fprintf(fh, "%f %f %i\n", cen*1.0e-9, r*100.0, cts[i]);
Thomas White's avatar
Thomas White committed
134
135
136
137
138
139
140

	}

	fclose(fh);
}


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

	/* Long options */
	const struct option longopts[] = {
		{"help",               0, NULL,               'h'},
		{"output",             1, NULL,               'o'},
167
		{"symmetry",           1, NULL,               'y'},
Thomas White's avatar
Thomas White committed
168
		{"shells",             0, &config_shells,     1},
169
		{"pdb",                1, NULL,               'p'},
170
171
172
173
		{0, 0, NULL, 0}
	};

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

		switch (c) {
Thomas White's avatar
Thomas White committed
177
		case 'h' :
178
179
180
			show_help(argv[0]);
			return 0;

Thomas White's avatar
Thomas White committed
181
		case 'o' :
182
183
184
			outfile = strdup(optarg);
			break;

185
186
187
188
		case 'y' :
			sym = strdup(optarg);
			break;

189
190
191
192
		case 'p' :
			pdb = strdup(optarg);
			break;

Thomas White's avatar
Thomas White committed
193
		case 0 :
194
195
			break;

Thomas White's avatar
Thomas White committed
196
		default :
197
198
199
200
201
			return 1;
		}

	}

202
203
204
205
206
	if ( argc != (optind+2) ) {
		ERROR("Please provide exactly two HKL files to compare.\n");
		return 1;
	}

207
208
209
210
	if ( sym == NULL ) {
		sym = strdup("1");
	}

211
212
213
	afile = strdup(argv[optind++]);
	bfile = strdup(argv[optind]);

214
215
216
217
218
219
220
	if ( pdb == NULL ) {
		pdb = strdup("molecule.pdb");
	}

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

Thomas White's avatar
Thomas White committed
221
	ref1 = new_list_intensity();
222
223
	esd1 = new_list_sigma();
	i1 = read_reflections(afile, ref1, NULL, NULL, esd1);
Thomas White's avatar
Thomas White committed
224
	if ( i1 == NULL ) {
225
226
227
		ERROR("Couldn't open file '%s'\n", afile);
		return 1;
	}
Thomas White's avatar
Thomas White committed
228
	ref2 = new_list_intensity();
229
230
	esd2 = new_list_sigma();
	i2 = read_reflections(bfile, ref2, NULL, NULL, esd2);
Thomas White's avatar
Thomas White committed
231
	if ( i2 == NULL ) {
232
233
234
235
		ERROR("Couldn't open file '%s'\n", bfile);
		return 1;
	}

Thomas White's avatar
Thomas White committed
236
237
	/* List for output scale factor map */
	out = new_list_intensity();
238

239
240
241
242
243
	/* 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
244
245
		struct refl_item *it;
		signed int h, k, l;
246
247
		signed int he, ke, le;
		double val1, val2;
248
249
		double sig1, sig2;
		int ig = 0;
250
		double d;
251

252
		it = get_item(i1, i);
Thomas White's avatar
Thomas White committed
253
		h = it->h;  k = it->k;  l = it->l;
254

255
		if ( !find_unique_equiv(i2, h, k, l, sym, &he, &ke, &le) ) {
Thomas White's avatar
Thomas White committed
256
257
			//STATUS("%i %i %i not matched (%f nm).\n", h, k, l,
			//       1.0/(2.0*resolution(cell, h, k, l)/1e9));
258
259
			continue;
		}
260

261
262
		val1 = lookup_intensity(ref1, h, k, l);
		val2 = lookup_intensity(ref2, he, ke, le);
263
		sig1 = lookup_sigma(esd1, h, k, l);
264
		sig2 = lookup_sigma(esd2, he, ke, le);
265
266
267
268
269
270
271
272
273

		if ( val1 < 3.0 * sig1 ) {
			rej1++;
			ig = 1;
		}
		if ( val2 < 3.0 * sig2 ) {
			rej2++;
			ig = 1;
		}
274
275
276
277
278

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

279
		//if ( ig ) continue;
280

281
282
283
		set_intensity(ref2_transformed, h, k, l, val2);
		set_intensity(out, h, k, l, val1/val2);
		add_item(icommon, h, k, l);
284
285

	}
286
	ncom = num_items(icommon);
287
288
289
290
	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);
291

Thomas White's avatar
Thomas White committed
292
293
	STATUS("%i,%i reflections: %i in common\n",
	       num_items(i1), num_items(i2), ncom);
Thomas White's avatar
Thomas White committed
294
295

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

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

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

306
307
	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
308

309
	Rdiff = stat_rdiff_ignore(ref1, ref2_transformed, icommon, &scale_rdig);
310
	STATUS("Rdiff(F) = %5.4f %% (scale=%5.2e) (ignoring negative intensities)\n",
Thomas White's avatar
Thomas White committed
311
312
313
	       Rdiff*100.0, scale);

	Rdiff = stat_rdiff_zero(ref1, ref2_transformed, icommon, &scale);
314
	STATUS("Rdiff(F) = %5.4f %% (scale=%5.2e) (zeroing negative intensities)\n",
Thomas White's avatar
Thomas White committed
315
316
317
318
319
320
321
322
323
324
325
326
	       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
327

Thomas White's avatar
Thomas White committed
328
	if ( config_shells ) {
329
		plot_shells(ref1, ref2_transformed, icommon, scale_rdig, cell);
Thomas White's avatar
Thomas White committed
330
331
	}

332
	if ( outfile != NULL ) {
Thomas White's avatar
Thomas White committed
333
		write_reflections(outfile, icommon, out, NULL, NULL, cell);
334
	}
335
336
337

	return 0;
}