render_hkl.c 16.5 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
#include "render_hkl.h"
34
35


36
37
38
39
static void show_help(const char *s)
{
	printf("Syntax: %s [options] <file.hkl>\n\n", s);
	printf(
40
"Render intensity lists in various ways.\n"
41
"\n"
42
"      --povray            Render a 3D animation using POV-ray.\n"
43
#ifdef HAVE_CAIRO
44
"      --zone-axis         Render a 2D zone axis pattern.\n"
45
#endif
46
"\n"
47
"  -d, --down=<h>,<k>,<l>  Indices for the axis in the downward direction.\n"
48
"                           Default: 1,0,0.\n"
49
"  -r, --right=<h>,<k>,<l> Indices for the axis in the 'right' (roughly)\n"
50
51
"                           direction.  Default: 0,1,0.\n"
"  -o, --output=<filename> Output filename (not for POV-ray).\n"
52
53
54
"      --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"
55
56
57
58
"\n"
"  -c, --colscale=<scale>  Use the given colour scale.  Choose from:\n"
"                           mono    : Greyscale, black is zero.\n"
"                           invmono : Greyscale, white is zero.\n"
Thomas White's avatar
Thomas White committed
59
"                           colour  : Colour scale:\n"
60
61
"                                     black-blue-pink-red-orange-yellow-white\n"
"\n"
62
63
"  -w  --weighting=<wght>  Colour/shade the reciprocal lattice points\n"
"                           according to:\n"
64
65
"                            I      : the intensity of the reflection.\n"
"                            sqrtI  : the square root of the intensity.\n"
Thomas White's avatar
Thomas White committed
66
"                            count  : the number of measurements for the reflection.\n"
67
"                                     (after correcting for 'epsilon')\n"
Thomas White's avatar
Thomas White committed
68
"                            rawcts : the raw number of measurements for the\n"
69
"                                     reflection (no 'epsilon' correction).\n"
70
71
72
73
"\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"
74
);
75
76
77
}


78
#ifdef HAVE_CAIRO
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
105
		signed int he, ke, le;
106
107
108
109
110
111

		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
112
113
		if ( find_unique_equiv(items, h, k, l, sym,
		                       &he, &ke, &le) == 0 ) continue;
114
115
116

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

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

139
		if ( dctx != NULL ) {
140

141
			float r, g, b;
142

143
144
145
			cairo_arc(dctx, ((double)cx)+u*scale,
			                ((double)cy)+v*scale,
			                radius, 0, 2*M_PI);
146

147
148
149
150
			render_scale(val, *max_val/boost, colscale,
			             &r, &g, &b);
			cairo_set_source_rgb(dctx, r, g, b);
			cairo_fill(dctx);
151

152
		} else {
153

154
155
156
			/* 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);
157

158
159
160
			/* Find max value for colour scale */
			if ( fabs(val) > fabs(*max_val) ) {
				*max_val = fabs(val);
161
162
			}

163
			/* Find max indices */
Thomas White's avatar
Thomas White committed
164
165
166
167
			if ( (yi==0) && (fabs(xi) > *max_ux) )
				*max_ux = fabs(xi);
			if ( (xi==0) && (fabs(yi) > *max_uy) )
				*max_uy = fabs(yi);
168
169

			/* Find max resolution */
Thomas White's avatar
Thomas White committed
170
			res = resolution(cell, h, k, l);
171
			if ( res > *max_res ) *max_res = res;
172
173
174
175
176
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
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);
	}
}


229
static void render_za(UnitCell *cell, ReflItemList *items,
230
                      double *ref, unsigned int *counts,
231
232
                      double boost, const char *sym, int wght, int colscale,
                      signed int xh, signed int xk, signed int xl,
233
234
                      signed int yh, signed int yk, signed int yl,
                      const char *outfile)
235
{
Thomas White's avatar
Thomas White committed
236
237
	cairo_surface_t *surface;
	cairo_t *dctx;
238
	double max_u, max_v, max_res, max_val;
239
	double scale_u, scale_v, scale;
Thomas White's avatar
Thomas White committed
240
	double sep_u, sep_v, max_r;
241
	double u, v;
242
	signed int max_ux, max_uy;
Thomas White's avatar
Thomas White committed
243
	double as, bs, theta;
244
245
246
	double asx, asy, asz;
	double bsx, bsy, bsz;
	double csx, csy, csz;
Thomas White's avatar
Thomas White committed
247
	float wh, ht;
248
249
250
251
252
253
254
255
	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;

256
	/* Vector product to determine the zone axis. */
257
258
259
260
	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);
261

262
	/* Size of output and centre definition */
Thomas White's avatar
Thomas White committed
263
264
	wh = 1024;
	ht = 1024;
265

Thomas White's avatar
Thomas White committed
266
	/* Work out reciprocal lattice spacings and angles for this cut */
267
	if ( cell_get_reciprocal(cell, &asx, &asy, &asz,
Thomas White's avatar
Thomas White committed
268
	                          &bsx, &bsy, &bsz,
269
270
271
272
	                          &csx, &csy, &csz) ) {
		ERROR("Couldn't get reciprocal parameters\n");
		return;
	}
273
274
275
276
277
278
279
280
281
282
	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;

283
	scale = 1.0;
284
285
	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
286
	             0.0, theta, as, bs, 0.0, 0.0, scale,
287
	             &max_ux, &max_uy, &max_val, &max_u, &max_v, &max_res);
288

Thomas White's avatar
Thomas White committed
289
	max_res /= 1e9;
290
291
	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
292

293
	if ( max_val <= 0.0 ) {
294
		STATUS("Couldn't find max value.\n");
Thomas White's avatar
Thomas White committed
295
		return;
296
297
	}

Thomas White's avatar
Thomas White committed
298
	/* Choose whichever scaling factor gives the smallest value */
299
300
	scale_u = ((double)wh-border) / (2.0*max_u);
	scale_v = ((double)ht-border) / (2.0*max_v);
301
	scale = (scale_u < scale_v) ? scale_u : scale_v;
302

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

313
314
	if ( outfile == NULL ) outfile = "za.pdf";
	surface = cairo_pdf_surface_create(outfile, wh, ht);
315
316

	if ( cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS ) {
Thomas White's avatar
Thomas White committed
317
		ERROR("Couldn't create Cairo surface\n");
318
319
320
321
322
		cairo_surface_destroy(surface);
		return;
	}

	dctx = cairo_create(surface);
Thomas White's avatar
Thomas White committed
323
324
325
326
327
	if ( cairo_status(dctx) != CAIRO_STATUS_SUCCESS ) {
		ERROR("Couldn't create Cairo context\n");
		cairo_surface_destroy(surface);
		return;
	}
328
329
330
331
332
333
334
335
336
337
338
339
340
341

	/* 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:o:",
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();
617
	ReflItemList *items = read_reflections(infile, ref, NULL, cts, NULL);
618
	if ( items == NULL ) {
Thomas White's avatar
Thomas White committed
619
620
621
622
623
		ERROR("Couldn't open file '%s'\n", infile);
		return 1;
	}

	if ( config_povray ) {
624
625
		r = povray_render_animation(cell, ref, cts, items,
		                            nproc, sym, wght, boost);
Thomas White's avatar
Thomas White committed
626
	} else if ( config_zoneaxis ) {
627
#ifdef HAVE_CAIRO
628
		render_za(cell, items, ref, cts, boost, sym, wght, colscale,
629
		          rh, rk, rl, dh, dk, dl, outfile);
630
631
632
633
634
#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
635
636
637
638
	} else {
		ERROR("Try again with either --povray or --zone-axis.\n");
	}

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

644
	return r;
645
}