render_hkl.c 16.4 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
/*
 * render_hkl.c
 *
 * Draw pretty renderings of 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>
23
#ifdef HAVE_CAIRO
Thomas White's avatar
Thomas White committed
24
25
#include <cairo.h>
#include <cairo-pdf.h>
26
#endif
27
28
29

#include "utils.h"
#include "reflections.h"
30
#include "povray.h"
31
#include "symmetry.h"
32
#include "render.h"
33

34
35
36
37
enum {
	WGHT_I,
	WGHT_SQRTI,
	WGHT_COUNTS,
38
	WGHT_RAWCOUNTS,
39
};
40

41
42
43
44
static void show_help(const char *s)
{
	printf("Syntax: %s [options] <file.hkl>\n\n", s);
	printf(
45
"Render intensity lists in various ways.\n"
46
"\n"
47
"      --povray            Render a 3D animation using POV-ray.\n"
48
#ifdef HAVE_CAIRO
49
"      --zone-axis         Render a 2D zone axis pattern.\n"
50
#endif
51
"\n"
52
"  -d, --down=<h>,<k>,<l>  Indices for the axis in the downward direction.\n"
53
"                           Default: 1,0,0.\n"
54
"  -r, --right=<h>,<k>,<l> Indices for the axis in the 'right' (roughly)\n"
55
56
"                           direction.  Default: 0,1,0.\n"
"  -o, --output=<filename> Output filename (not for POV-ray).\n"
57
58
59
"      --boost=<val>       Squash colour scale by <val>.\n"
"  -p, --pdb=<file>        PDB file from which to get the unit cell.\n"
"  -y, --symmetry=<sym>    Expand reflections according to point group <sym>.\n"
60
61
62
63
64
65
66
"\n"
"  -c, --colscale=<scale>  Use the given colour scale.  Choose from:\n"
"                           mono    : Greyscale, black is zero.\n"
"                           invmono : Greyscale, white is zero.\n"
"                           colour  : Colours scale:\n"
"                                     black-blue-pink-red-orange-yellow-white\n"
"\n"
67
68
"  -w  --weighting=<wght>  Colour/shade the reciprocal lattice points\n"
"                           according to:\n"
69
70
71
72
73
74
"                            I      : the intensity of the reflection.\n"
"                            sqrtI  : the square root of the intensity.\n"
"                            count  : the number of hits for the reflection.\n"
"                                     (after correcting for 'epsilon')\n"
"                            rawcts : the raw number of hits for the\n"
"                                     reflection (no 'epsilon' correction).\n"
75
76
77
78
"\n"
"      --colour-key        Draw (only) the key for the current colour scale.\n"
"  -j <n>                  Run <n> instances of POV-ray in parallel.\n"
"  -h, --help              Display this help message.\n"
79
);
80
81
82
}


83
#ifdef HAVE_CAIRO
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
static void draw_circles(signed int xh, signed int xk, signed int xl,
                         signed int yh, signed int yk, signed int yl,
                         signed int zh, signed int zk, signed int zl,
                         double *ref, unsigned int *counts, ReflItemList *items,
                         const char *sym,
                         cairo_t *dctx, int wght, double boost, int colscale,
                         UnitCell *cell, double radius, double theta,
                         double as, double bs, double cx, double cy,
                         double scale,
                         signed int *max_ux, signed int *max_uy,
                         double *max_val, double *max_u, double *max_v,
                         double *max_res)
{
	signed int xi, yi;

	if ( dctx == NULL ) {
		*max_u = 0.0;  *max_v = 0.0;  *max_val = 0.0;
		*max_res = 0.0;  *max_ux = 0;  *max_uy = 0;
	}

	/* Loop across the two basis directions */
	for ( xi=-INDMAX; xi<INDMAX; xi++ ) {
	for ( yi=-INDMAX; yi<INDMAX; yi++ ) {

		double u, v, val, res;
		signed int h, k, l;
Thomas White's avatar
Thomas White committed
110
		signed int he, ke, le;
111
112
113
114
115
116

		h = xi*xh + yi*yh;
		k = xi*xk + yi*yk;
		l = xi*xl + yi*yl;

		/* Got this reflection? */
Thomas White's avatar
Thomas White committed
117
118
		if ( find_unique_equiv(items, h, k, l, sym,
		                       &he, &ke, &le) == 0 ) continue;
119
120
121

		switch ( wght ) {
		case WGHT_I :
Thomas White's avatar
Thomas White committed
122
			val = lookup_intensity(ref, he, ke, le);
123
124
			break;
		case WGHT_SQRTI :
Thomas White's avatar
Thomas White committed
125
			val = lookup_intensity(ref, he, ke, le);
126
127
128
			val = (val>0.0) ? sqrt(val) : 0.0;
			break;
		case WGHT_COUNTS :
Thomas White's avatar
Thomas White committed
129
130
			val = lookup_count(counts, he, ke, le);
			val /= (float)num_equivs(he, ke, le, sym);
131
132
			break;
		case WGHT_RAWCOUNTS :
Thomas White's avatar
Thomas White committed
133
			val = lookup_count(counts, he, ke, le);
134
135
136
137
138
139
			break;
		default :
			ERROR("Invalid weighting.\n");
			abort();
		}

140
		/* Absolute location in image based on 2D basis */
Thomas White's avatar
Thomas White committed
141
142
		u = (double)xi*as*sin(theta);
		v = (double)xi*as*cos(theta) + (double)yi*bs;
143

144
		if ( dctx != NULL ) {
145

146
			float r, g, b;
147

148
149
150
			cairo_arc(dctx, ((double)cx)+u*scale,
			                ((double)cy)+v*scale,
			                radius, 0, 2*M_PI);
151

152
153
154
155
			render_scale(val, *max_val/boost, colscale,
			             &r, &g, &b);
			cairo_set_source_rgb(dctx, r, g, b);
			cairo_fill(dctx);
156

157
		} else {
158

159
160
161
			/* Find max vectors in plane for scaling */
			if ( fabs(u) > fabs(*max_u) ) *max_u = fabs(u);
			if ( fabs(v) > fabs(*max_v) ) *max_v = fabs(v);
162

163
164
165
			/* Find max value for colour scale */
			if ( fabs(val) > fabs(*max_val) ) {
				*max_val = fabs(val);
166
167
			}

168
			/* Find max indices */
Thomas White's avatar
Thomas White committed
169
170
171
172
			if ( (yi==0) && (fabs(xi) > *max_ux) )
				*max_ux = fabs(xi);
			if ( (xi==0) && (fabs(yi) > *max_uy) )
				*max_uy = fabs(yi);
173
174

			/* Find max resolution */
Thomas White's avatar
Thomas White committed
175
			res = resolution(cell, h, k, l);
176
			if ( res > *max_res ) *max_res = res;
177
178
179
180
181
182
183
		}

	}
	}
}


184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
static void render_overlined_indices(cairo_t *dctx,
                                     signed int h, signed int k, signed int l)
{
	char tmp[256];
	cairo_text_extents_t size;
	double x, y;
	const double sh = 39.0;

	cairo_get_current_point(dctx, &x, &y);
	cairo_set_line_width(dctx, 4.0);

	/* Draw 'h' */
	snprintf(tmp, 255, "%i", abs(h));
	cairo_text_extents(dctx, tmp, &size);
	cairo_show_text(dctx, tmp);
	cairo_fill(dctx);
	if ( h < 0 ) {
		cairo_move_to(dctx, x+size.x_bearing, y-sh);
		cairo_rel_line_to(dctx, size.width, 0.0);
		cairo_stroke(dctx);
	}
	x += size.x_advance;

	/* Draw 'k' */
	cairo_move_to(dctx, x, y);
	snprintf(tmp, 255, "%i", abs(k));
	cairo_text_extents(dctx, tmp, &size);
	cairo_show_text(dctx, tmp);
	cairo_fill(dctx);
	if ( k < 0 ) {
		cairo_move_to(dctx, x+size.x_bearing, y-sh);
		cairo_rel_line_to(dctx, size.width, 0.0);
		cairo_stroke(dctx);
	}
	x += size.x_advance;

	/* Draw 'l' */
	cairo_move_to(dctx, x, y);
	snprintf(tmp, 255, "%i", abs(l));
	cairo_text_extents(dctx, tmp, &size);
	cairo_show_text(dctx, tmp);
	cairo_fill(dctx);
	if ( l < 0 ) {
		cairo_move_to(dctx, x+size.x_bearing, y-sh);
		cairo_rel_line_to(dctx, size.width, 0.0);
		cairo_stroke(dctx);
	}
}


234
static void render_za(UnitCell *cell, ReflItemList *items,
235
                      double *ref, unsigned int *counts,
236
237
                      double boost, const char *sym, int wght, int colscale,
                      signed int xh, signed int xk, signed int xl,
238
239
                      signed int yh, signed int yk, signed int yl,
                      const char *outfile)
240
{
Thomas White's avatar
Thomas White committed
241
242
	cairo_surface_t *surface;
	cairo_t *dctx;
243
	double max_u, max_v, max_res, max_val;
244
	double scale_u, scale_v, scale;
Thomas White's avatar
Thomas White committed
245
	double sep_u, sep_v, max_r;
246
	double u, v;
247
	signed int max_ux, max_uy;
Thomas White's avatar
Thomas White committed
248
	double as, bs, theta;
249
250
251
	double asx, asy, asz;
	double bsx, bsy, bsz;
	double csx, csy, csz;
Thomas White's avatar
Thomas White committed
252
	float wh, ht;
253
254
255
256
257
258
259
260
	signed int zh, zk, zl;
	double xx, xy, xz;
	double yx, yy, yz;
	char tmp[256];
	cairo_text_extents_t size;
	double cx, cy;
	const double border = 200.0;

261
	/* Vector product to determine the zone axis. */
262
263
264
265
	zh = xk*yl - xl*yk;
	zk = - xh*yl + xl*yh;
	zl = xh*yk - xk*yh;
	STATUS("Zone axis is %i %i %i\n", zh, zk, zl);
266

267
	/* Size of output and centre definition */
Thomas White's avatar
Thomas White committed
268
269
	wh = 1024;
	ht = 1024;
270

Thomas White's avatar
Thomas White committed
271
	/* Work out reciprocal lattice spacings and angles for this cut */
272
	if ( cell_get_reciprocal(cell, &asx, &asy, &asz,
Thomas White's avatar
Thomas White committed
273
	                          &bsx, &bsy, &bsz,
274
275
276
277
	                          &csx, &csy, &csz) ) {
		ERROR("Couldn't get reciprocal parameters\n");
		return;
	}
278
279
280
281
282
283
284
285
286
287
	xx = xh*asx + xk*bsx + xl*csx;
	xy = xh*asy + xk*bsy + xl*csy;
	xz = xh*asz + xk*bsz + xl*csz;
	yx = yh*asx + yk*bsx + yl*csx;
	yy = yh*asy + yk*bsy + yl*csy;
	yz = yh*asz + yk*bsz + yl*csz;
	theta = angle_between(xx, xy, xz, yx, yy, yz);
	as = modulus(xx, xy, xz) / 1e9;
	bs = modulus(yx, yy, yz) / 1e9;

288
	scale = 1.0;
289
290
	draw_circles(xh, xk, xl, yh, yk, yl, zh, zk, zl,
	             ref, counts, items, sym, NULL, wght, boost, colscale, cell,
Thomas White's avatar
Thomas White committed
291
	             0.0, theta, as, bs, 0.0, 0.0, scale,
292
	             &max_ux, &max_uy, &max_val, &max_u, &max_v, &max_res);
293

Thomas White's avatar
Thomas White committed
294
	max_res /= 1e9;
295
296
	printf("Maximum resolution is 1/d = %5.3f nm^-1, d = %5.3f nm\n",
	       max_res*2.0, 1.0/(max_res*2.0));
Thomas White's avatar
Thomas White committed
297

298
	if ( max_val <= 0.0 ) {
299
		STATUS("Couldn't find max value.\n");
Thomas White's avatar
Thomas White committed
300
		return;
301
302
	}

Thomas White's avatar
Thomas White committed
303
	/* Choose whichever scaling factor gives the smallest value */
304
305
	scale_u = ((double)wh-border) / (2.0*max_u);
	scale_v = ((double)ht-border) / (2.0*max_v);
306
	scale = (scale_u < scale_v) ? scale_u : scale_v;
307

308
309
	sep_u = scale*as;
	sep_v = scale*bs;
310
	/* We are interested in the smaller of the two separations */
311
	max_r = (sep_u < sep_v) ? sep_u : sep_v;
312
	max_r /= 2.0;  /* Max radius is half the separation */
313
	max_r -= 1.0;  /* Add a tiny separation between circles */
314
315
316
	if ( max_r < 1.0 ) {
		ERROR("Circle radius is probably too small (%f).\n", max_r);
	}
Thomas White's avatar
Thomas White committed
317

318
319
	if ( outfile == NULL ) outfile = "za.pdf";
	surface = cairo_pdf_surface_create(outfile, wh, ht);
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

	if ( cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS ) {
		fprintf(stderr, "Couldn't create Cairo surface\n");
		cairo_surface_destroy(surface);
		return;
	}

	dctx = cairo_create(surface);

	/* Black background */
	cairo_rectangle(dctx, 0.0, 0.0, wh, ht);
	cairo_set_source_rgb(dctx, 0.0, 0.0, 0.0);
	cairo_fill(dctx);

	/* Test size of text that goes to the right(ish) */
	cairo_set_font_size(dctx, 40.0);
	snprintf(tmp, 255, "%i%i%i", abs(xh), abs(xk), abs(xl));
	cairo_text_extents(dctx, tmp, &size);

	cx = 532.0 - size.width;
	cy = 512.0 - 20.0;

342
343
344
345
	draw_circles(xh, xk, xl, yh, yk, yl, zh, zk, zl,
	             ref, counts, items, sym, dctx, wght, boost, colscale, cell,
	             max_r, theta, as, bs, cx, cy, scale,
	             NULL, NULL, &max_val, NULL, NULL, NULL);
346

Thomas White's avatar
Thomas White committed
347
	/* Centre marker */
348
349
	cairo_arc(dctx, (double)cx,
			(double)cy, max_r, 0, 2*M_PI);
Thomas White's avatar
Thomas White committed
350
351
352
	cairo_set_source_rgb(dctx, 1.0, 0.0, 0.0);
	cairo_fill(dctx);

353
	/* Draw indexing lines */
354
	cairo_set_line_cap(dctx, CAIRO_LINE_CAP_ROUND);
355
	cairo_set_line_width(dctx, 4.0);
356
	cairo_move_to(dctx, (double)cx, (double)cy);
357
358
	u = (2.0+max_ux)*as*sin(theta);
	v = (2.0+max_ux)*as*cos(theta);
359
	cairo_line_to(dctx, cx+u*scale, cy+v*scale);
360
361
362
	cairo_set_source_rgb(dctx, 0.0, 1.0, 0.0);
	cairo_stroke(dctx);

363
	cairo_set_font_size(dctx, 40.0);
364
	snprintf(tmp, 255, "%i%i%i", abs(xh), abs(xk), abs(xl));
365
366
367
	cairo_text_extents(dctx, tmp, &size);

	cairo_move_to(dctx, cx+u*scale + 20.0, cy+v*scale + size.height/2.0);
368
	render_overlined_indices(dctx, xh, xk, xl);
369
370
	cairo_fill(dctx);

371
	snprintf(tmp, 255, "%i%i%i", abs(yh), abs(yk), abs(yl));
372
373
374
	cairo_text_extents(dctx, tmp, &size);

	cairo_move_to(dctx, (double)cx, (double)cy);
375
	u = 0.0;
376
	v = (2.0+max_uy)*bs;
377
	cairo_line_to(dctx, cx+u*scale, cy+v*scale);
378
379
380
	cairo_set_source_rgb(dctx, 0.0, 1.0, 0.0);
	cairo_stroke(dctx);

381
382
	cairo_move_to(dctx, cx+u*scale - size.width/2.0,
	                    cy+v*scale + size.height + 20.0);
383
	render_overlined_indices(dctx, yh, yk, yl);
384
385
	cairo_fill(dctx);

Thomas White's avatar
Thomas White committed
386
387
388
	cairo_surface_finish(surface);
	cairo_destroy(dctx);
}
389

390

391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
static int render_key(int colscale)
{
	cairo_surface_t *surface;
	cairo_t *dctx;
	float wh, ht;
	float y;

	wh = 128;
	ht = 1024;

	surface = cairo_pdf_surface_create("key.pdf", wh, ht);

	if ( cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS ) {
		fprintf(stderr, "Couldn't create Cairo surface\n");
		cairo_surface_destroy(surface);
		return 1;
	}

	dctx = cairo_create(surface);

	for ( y=0; y<ht; y++ ) {

		float r, g, b;

		cairo_rectangle(dctx, 0.0, y, wh, y+1.0);

		render_scale(ht-y, ht, colscale, &r, &g, &b);
		cairo_set_source_rgb(dctx, r, g, b);

		cairo_fill(dctx);

	}

	cairo_surface_finish(surface);
	cairo_destroy(dctx);

	return 0;
}
429
#endif
Thomas White's avatar
Thomas White committed
430
431
432
433
434
435
436
437
438
439


int main(int argc, char *argv[])
{
	int c;
	UnitCell *cell;
	char *infile;
	double *ref;
	int config_povray = 0;
	int config_zoneaxis = 0;
Thomas White's avatar
Thomas White committed
440
	int config_sqrt = 0;
441
	int config_colkey = 0;
Thomas White's avatar
Thomas White committed
442
	unsigned int nproc = 1;
443
	char *pdb = NULL;
444
	int r = 0;
445
	double boost = 1.0;
446
	char *sym = NULL;
447
448
	char *weighting = NULL;
	int wght;
449
450
	int colscale;
	char *cscale = NULL;
Thomas White's avatar
Thomas White committed
451
	unsigned int *cts;
452
453
454
455
	signed int dh=1, dk=0, dl=0;
	signed int rh=0, rk=1, rl=0;
	char *down = NULL;
	char *right = NULL;
456
	char *outfile = NULL;
Thomas White's avatar
Thomas White committed
457
458
459
460
461
462

	/* Long options */
	const struct option longopts[] = {
		{"help",               0, NULL,               'h'},
		{"povray",             0, &config_povray,      1},
		{"zone-axis",          0, &config_zoneaxis,    1},
463
		{"output",             1, NULL,               'o'},
464
		{"pdb",                1, NULL,               'p'},
465
		{"boost",              1, NULL,               'b'},
466
		{"symmetry",           1, NULL,               'y'},
467
		{"weighting",          1, NULL,               'w'},
468
		{"colscale",           1, NULL,               'c'},
469
470
		{"down",               1, NULL,               'd'},
		{"right",              1, NULL,               'r'},
471
		{"counts",             0, &config_sqrt,        1},
472
		{"colour-key",         0, &config_colkey,      1},
Thomas White's avatar
Thomas White committed
473
474
475
476
		{0, 0, NULL, 0}
	};

	/* Short options */
477
	while ((c = getopt_long(argc, argv, "hj:p:w:c:y:d:r:",
478
	                        longopts, NULL)) != -1) {
Thomas White's avatar
Thomas White committed
479
480

		switch (c) {
Thomas White's avatar
Thomas White committed
481
		case 'h' :
Thomas White's avatar
Thomas White committed
482
483
484
			show_help(argv[0]);
			return 0;

Thomas White's avatar
Thomas White committed
485
		case 'j' :
Thomas White's avatar
Thomas White committed
486
487
488
			nproc = atoi(optarg);
			break;

489
490
491
492
		case 'p' :
			pdb = strdup(optarg);
			break;

493
494
495
496
		case 'b' :
			boost = atof(optarg);
			break;

497
498
499
500
		case 'y' :
			sym = strdup(optarg);
			break;

501
502
503
504
		case 'w' :
			weighting = strdup(optarg);
			break;

505
506
507
508
		case 'c' :
			cscale = strdup(optarg);
			break;

509
510
511
512
513
514
515
516
		case 'd' :
			down = strdup(optarg);
			break;

		case 'r' :
			right = strdup(optarg);
			break;

517
518
519
520
		case 'o' :
			outfile = strdup(optarg);
			break;

Thomas White's avatar
Thomas White committed
521
		case 0 :
Thomas White's avatar
Thomas White committed
522
523
			break;

Thomas White's avatar
Thomas White committed
524
		default :
Thomas White's avatar
Thomas White committed
525
526
527
528
529
			return 1;
		}

	}

530
531
532
533
	if ( pdb == NULL ) {
		pdb = strdup("molecule.pdb");
	}

534
535
536
537
	if ( sym == NULL ) {
		sym = strdup("1");
	}

538
539
540
541
542
543
544
545
546
547
	if ( weighting == NULL ) {
		weighting = strdup("I");
	}

	if ( strcmp(weighting, "I") == 0 ) {
		wght = WGHT_I;
	} else if ( strcmp(weighting, "sqrtI") == 0 ) {
		wght = WGHT_SQRTI;
	} else if ( strcmp(weighting, "count") == 0 ) {
		wght = WGHT_COUNTS;
548
549
	} else if ( strcmp(weighting, "counts") == 0 ) {
		wght = WGHT_COUNTS;
550
551
	} else if ( strcmp(weighting, "rawcts") == 0 ) {
		wght = WGHT_RAWCOUNTS;
552
553
554
555
	} else if ( strcmp(weighting, "rawcount") == 0 ) {
		wght = WGHT_RAWCOUNTS;
	} else if ( strcmp(weighting, "rawcounts") == 0 ) {
		wght = WGHT_RAWCOUNTS;
556
557
558
559
	} else {
		ERROR("Unrecognised weighting '%s'\n", weighting);
		return 1;
	}
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
	free(weighting);

	if ( cscale == NULL ) {
		cscale = strdup("mono");
	}

	if ( strcmp(cscale, "mono") == 0 ) {
		colscale = SCALE_MONO;
	} else if ( strcmp(cscale, "invmono") == 0 ) {
		colscale = SCALE_INVMONO;
	} else if ( strcmp(cscale, "colour") == 0 ) {
		colscale = SCALE_COLOUR;
	} else if ( strcmp(cscale, "color") == 0 ) {
		colscale = SCALE_COLOUR;
	} else {
		ERROR("Unrecognised colour scale '%s'\n", cscale);
		return 1;
	}
	free(cscale);
579

580
581
582
583
	if ( config_colkey ) {
		return render_key(colscale);
	}

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
	if ( config_zoneaxis ) {
		if ( (( down == NULL ) && ( right != NULL ))
		  || (( down != NULL ) && ( right == NULL )) ) {
			ERROR("Either specify both 'down' and 'right', or neither.\n");
			return 1;
		}
		if ( down != NULL ) {
			int r;
			r = sscanf(down, "%i,%i,%i", &dh, &dk, &dl);
			if ( r != 3 ) {
				ERROR("Invalid format for 'down'\n");
				return 1;
			}
		}
		if ( right != NULL ) {
			int r;
			r = sscanf(right, "%i,%i,%i", &rh, &rk, &rl);
			if ( r != 3 ) {
				ERROR("Invalid format for 'right'\n");
				return 1;
			}
		}
	}

Thomas White's avatar
Thomas White committed
608
609
	infile = argv[optind];

610
	cell = load_cell_from_pdb(pdb);
611
612
613
614
	if ( cell == NULL ) {
		ERROR("Couldn't load unit cell from %s\n", pdb);
		return 1;
	}
Thomas White's avatar
Thomas White committed
615
	ref = new_list_intensity();
Thomas White's avatar
Thomas White committed
616
	cts = new_list_count();
Thomas White's avatar
Thomas White committed
617
	ReflItemList *items = read_reflections(infile, ref, NULL, cts);
Thomas White's avatar
Thomas White committed
618
619
620
621
622
623
	if ( ref == NULL ) {
		ERROR("Couldn't open file '%s'\n", infile);
		return 1;
	}

	if ( config_povray ) {
624
		r = povray_render_animation(cell, ref, cts, nproc);
Thomas White's avatar
Thomas White committed
625
	} else if ( config_zoneaxis ) {
626
#ifdef HAVE_CAIRO
627
		render_za(cell, items, ref, cts, boost, sym, wght, colscale,
628
		          rh, rk, rl, dh, dk, dl, outfile);
629
630
631
632
633
#else
		ERROR("This version of CrystFEL was compiled without Cairo");
		ERROR(" support, which is required to plot a zone axis");
		ERROR(" pattern.  Sorry!\n");
#endif
Thomas White's avatar
Thomas White committed
634
635
636
637
	} else {
		ERROR("Try again with either --povray or --zone-axis.\n");
	}

638
	free(pdb);
639
	free(sym);
640
	delete_items(items);
641
	if ( outfile != NULL ) free(outfile);
642

643
	return r;
644
}