process_hkl.c 7.68 KB
Newer Older
1
2
3
4
5
/*
 * process_hkl.c
 *
 * Assemble and process FEL Bragg intensities
 *
Thomas White's avatar
Thomas White committed
6
 * (c) 2006-2010 Thomas White <taw@physics.org>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * 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 "statistics.h"
#include "sfac.h"
27
#include "reflections.h"
28
29


Thomas White's avatar
Thomas White committed
30
31
32
33
/* Number of divisions for R vs |q| graphs */
#define RVQDV (20)


34
35
36
static void show_help(const char *s)
{
	printf("Syntax: %s [options]\n\n", s);
Thomas White's avatar
Thomas White committed
37
38
39
40
41
	printf(
"Assemble and process FEL Bragg intensities.\n"
"\n"
"  -h, --help              Display this help message.\n"
"  -i, --input=<filename>  Specify input filename (\"-\" for stdin).\n"
42
43
"  -o, --output=<filename> Specify output filename for merged intensities\n"
"                           (don't specify for no output).\n"
Thomas White's avatar
Thomas White committed
44
45
46
47
"\n"
"      --max-only          Take the integrated intensity to be equal to the\n"
"                           maximum intensity measured for that reflection.\n"
"                           The default is to use the mean value from all\n"
Thomas White's avatar
Thomas White committed
48
"                           measurements.\n"
Thomas White's avatar
Thomas White committed
49
"  -e, --output-every=<n>  Analyse figures of merit after every n patterns\n"
50
51
"                           Default: 1000.  A value of zero means to do the\n"
"                           analysis only after reading all the patterns.\n"
Thomas White's avatar
Thomas White committed
52
53
"      --no-analyse        Don't perform any kind of analysis, just merge the\n"
"                           intensities.\n"
Thomas White's avatar
Thomas White committed
54
"  -r, --rvsq              Output lists of R vs |q| (\"Luzzatti plots\") when\n"
Thomas White's avatar
Thomas White committed
55
"                           analysing figures of merit.\n"
Thomas White's avatar
Thomas White committed
56
57
"      --stop-after=<n>    Stop after processing n patterns.  Zero means\n"
"                           keep going until the end of the input, and is the\n"
Thomas White's avatar
Thomas White committed
58
"                           default.\n"
Thomas White's avatar
Thomas White committed
59
60
"      --zone-axis         Output an [001] zone axis pattern each time the\n"
"                           figures of merit are analysed.\n");
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
}


static void write_RvsQ(const char *name, double *ref, double *trueref,
                       unsigned int *counts, double scale, UnitCell *cell)
{
	FILE *fh;
	double smax, sbracket;
	signed int h, k, l;

	fh = fopen(name, "w");

	smax = 0.0;
	for ( h=-INDMAX; h<INDMAX; h++ ) {
	for ( k=-INDMAX; k<INDMAX; k++ ) {
	for ( l=-INDMAX; l<INDMAX; l++ ) {
		double s = resolution(cell, h, k, l);
		if ( (lookup_count(counts, h, k, l) > 0) && (s > smax) ) {
			smax = s;
		}
	}
	}
	}

Thomas White's avatar
Thomas White committed
85
	for ( sbracket=0.0; sbracket<smax; sbracket+=smax/RVQDV ) {
86
87
88

		double top = 0.0;
		double bot = 0.0;
Thomas White's avatar
Thomas White committed
89
90
91
92
		int nhits = 0;
		int nrefl = 0;
		double R;
		double hits_per_refl;
93
94
95
96
97
98
99

		for ( h=-INDMAX; h<INDMAX; h++ ) {
		for ( k=-INDMAX; k<INDMAX; k++ ) {
		for ( l=-INDMAX; l<INDMAX; l++ ) {

			double s;
			int c;
Thomas White's avatar
Thomas White committed
100
101
102

			if ( (h==0) && (k==0) && (l==0) ) continue;

103
104
			c = lookup_count(counts, h, k, l);
			s = resolution(cell, h, k, l);
Thomas White's avatar
Thomas White committed
105
			if ((s>=sbracket) && (s<sbracket+smax/RVQDV) && (c>0)) {
106
107
108
109
110
111
112

				double obs, calc, obsi;

				obs = lookup_intensity(ref, h, k, l);
				calc = lookup_intensity(trueref, h, k, l);

				obsi = obs / (double)c;
Thomas White's avatar
Thomas White committed
113
114
115
116
117
				top += pow(obsi - scale*calc, 2.0);
				bot += pow(obsi, 2.0);
				nhits += c;
				nrefl++;

118
119
120
121
122
123
			}

		}
		}
		}

Thomas White's avatar
Thomas White committed
124
125
126
127
128
		R = sqrt(top/bot);
		hits_per_refl = nrefl ? (double)nhits/nrefl : 0;

		fprintf(fh, "%8.5f %8.5f %5.2f\n", sbracket+smax/(2.0*RVQDV),
		                                R, hits_per_refl);
129
130
131
132
133
134
135
136

	}
	fclose(fh);
}


static void process_reflections(double *ref, double *trueref,
                                unsigned int *counts, unsigned int n_patterns,
Thomas White's avatar
Thomas White committed
137
                                UnitCell *cell, int do_rvsq, int do_zoneaxis)
138
139
140
141
142
143
{
	int j;
	double mean_counts;
	int ctot = 0;
	int nmeas = 0;
	double R, scale;
144
	FILE *fh;
145
146
147
148
149
150
151
152

	for ( j=0; j<LIST_SIZE; j++ ) {
		ctot += counts[j];
		if ( counts[j] > 0 ) nmeas++;
	}
	mean_counts = (double)ctot/nmeas;

	R = stat_r2(ref, trueref, counts, LIST_SIZE, &scale);
Thomas White's avatar
Thomas White committed
153
	STATUS("%8u: R=%5.2f%% (sf=%7.4e)  mean meas/refl=%5.2f,"
154
155
	       " %i reflections measured\n",
	       n_patterns, R*100.0, scale, mean_counts, nmeas);
156

Thomas White's avatar
Thomas White committed
157
158
	if ( do_rvsq ) {
		/* Record graph of R against q for this N */
Thomas White's avatar
Thomas White committed
159
		char name[64];
Thomas White's avatar
Thomas White committed
160
161
162
		snprintf(name, 63, "results/R_vs_q-%u.dat", n_patterns);
		write_RvsQ(name, ref, trueref, counts, scale, cell);
	}
Thomas White's avatar
Thomas White committed
163
164
165
166
167
168

	if ( do_zoneaxis ) {
		char name[64];
		snprintf(name, 63, "results/ZA-%u.dat", n_patterns);
		write_reflections(name, counts, ref, 1, cell);
	}
169
170
171
172

	fh = fopen("results/convergence.dat", "a");
	fprintf(fh, "%u %5.2f %5.2f\n", n_patterns, R*100.0, mean_counts);
	fclose(fh);
173
174
175
176
177
178
179
}


int main(int argc, char *argv[])
{
	int c;
	char *filename = NULL;
180
	char *output = NULL;
181
182
	FILE *fh;
	unsigned int n_patterns;
Thomas White's avatar
Thomas White committed
183
	double *ref, *trueref = NULL;
184
185
	unsigned int *counts;
	char *rval;
Thomas White's avatar
Thomas White committed
186
	struct molecule *mol = NULL;
Thomas White's avatar
Thomas White committed
187
	int config_maxonly = 0;
Thomas White's avatar
Thomas White committed
188
	int config_every = 1000;
Thomas White's avatar
Thomas White committed
189
	int config_rvsq = 0;
Thomas White's avatar
Thomas White committed
190
	int config_stopafter = 0;
Thomas White's avatar
Thomas White committed
191
	int config_zoneaxis = 0;
Thomas White's avatar
Thomas White committed
192
	int config_noanalyse = 0;
193
194
195
196
197

	/* Long options */
	const struct option longopts[] = {
		{"help",               0, NULL,               'h'},
		{"input",              1, NULL,               'i'},
Thomas White's avatar
Thomas White committed
198
		{"output",             1, NULL,               'o'},
Thomas White's avatar
Thomas White committed
199
		{"max-only",           0, &config_maxonly,     1},
Thomas White's avatar
Thomas White committed
200
		{"output-every",       1, NULL,               'e'},
Thomas White's avatar
Thomas White committed
201
		{"no-analyse",         0, &config_noanalyse,   1},
Thomas White's avatar
Thomas White committed
202
		{"rvsq",               0, NULL,               'r'},
Thomas White's avatar
Thomas White committed
203
		{"stop-after",         1, NULL,               's'},
Thomas White's avatar
Thomas White committed
204
		{"zone-axis",          0, &config_zoneaxis,    1},
205
206
207
208
		{0, 0, NULL, 0}
	};

	/* Short options */
209
	while ((c = getopt_long(argc, argv, "hi:e:ro:", longopts, NULL)) != -1) {
210
211
212
213
214
215
216
217
218
219
220
221

		switch (c) {
		case 'h' : {
			show_help(argv[0]);
			return 0;
		}

		case 'i' : {
			filename = strdup(optarg);
			break;
		}

222
223
224
225
226
		case 'o' : {
			output = strdup(optarg);
			break;
		}

Thomas White's avatar
Thomas White committed
227
228
229
230
231
		case 'r' : {
			config_rvsq = 1;
			break;
		}

Thomas White's avatar
Thomas White committed
232
233
234
235
236
		case 'e' : {
			config_every = atoi(optarg);
			break;
		}

Thomas White's avatar
Thomas White committed
237
238
239
240
241
		case 's' : {
			config_stopafter = atoi(optarg);
			break;
		}

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
		case 0 : {
			break;
		}

		default : {
			return 1;
		}
		}

	}

	if ( filename == NULL ) {
		ERROR("Please specify filename using the -i option\n");
		return 1;
	}

	ref = new_list_intensity();
	counts = new_list_count();
Thomas White's avatar
Thomas White committed
260

261
	mol = load_molecule();
Thomas White's avatar
Thomas White committed
262
263
264
265
	if ( !config_noanalyse ) {
		get_reflections_cached(mol, eV_to_J(2.0e3));
		trueref = ideal_intensities(mol->reflections);
	}
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

	if ( strcmp(filename, "-") == 0 ) {
		fh = stdin;
	} else {
		fh = fopen(filename, "r");
	}
	free(filename);
	if ( fh == NULL ) {
		ERROR("Failed to open input file\n");
		return 1;
	}

	n_patterns = 0;
	do {

		char line[1024];
Thomas White's avatar
Tidy-up    
Thomas White committed
282
		signed int h, k, l, intensity;
283
284
285
286
		int r;

		rval = fgets(line, 1023, fh);
		if ( strncmp(line, "New pattern", 11) == 0 ) {
Thomas White's avatar
Tidy-up    
Thomas White committed
287

Thomas White's avatar
Thomas White committed
288
289
290
291
			if ( n_patterns == 0 ) {
				n_patterns++;
				continue;
			}
Thomas White's avatar
Tidy-up    
Thomas White committed
292

293
			if (config_every && (n_patterns % config_every == 0)) {
294
				process_reflections(ref, trueref, counts,
Thomas White's avatar
Thomas White committed
295
				                    n_patterns, mol->cell,
Thomas White's avatar
Thomas White committed
296
297
				                    config_rvsq,
				                    config_zoneaxis);
298
			}
Thomas White's avatar
Thomas White committed
299
300
301

			if ( n_patterns == config_stopafter ) break;

Thomas White's avatar
Thomas White committed
302
			n_patterns++;
303
304
305
306
307
		}

		r = sscanf(line, "%i %i %i %i", &h, &k, &l, &intensity);
		if ( r != 4 ) continue;

Thomas White's avatar
Tidy-up    
Thomas White committed
308
309
		if ( (h==0) && (k==0) && (l==0) ) continue;

Thomas White's avatar
Thomas White committed
310
311
312
313
314
315
316
317
318
		if ( !config_maxonly ) {
			integrate_intensity(ref, h, k, l, intensity);
			integrate_count(counts, h, k, l, 1);
		} else {
			if ( intensity > lookup_intensity(ref, h, k, l) ) {
				set_intensity(ref, h, k, l, intensity);
			}
			set_count(counts, h, k, l, 1);
		}
319
320
321
322
323

	} while ( rval != NULL );

	fclose(fh);

Thomas White's avatar
Thomas White committed
324
325
326
327
	if ( !config_noanalyse ) {
		process_reflections(ref, trueref, counts, n_patterns, mol->cell,
		                    config_rvsq, config_zoneaxis);
	}
328

329
	if ( output != NULL ) {
330
		write_reflections(output, counts, ref, 0, mol->cell);
331
	}
Thomas White's avatar
Thomas White committed
332
333

	STATUS("There were %u patterns.\n", n_patterns);
334
335
336

	return 0;
}