aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2019-02-18 16:56:52 +0100
committerThomas White <taw@physics.org>2019-03-11 16:49:37 +0100
commita2f4977e0f8bd9becd50ab5a2ef903038273133c (patch)
treee754341a53aa89f821a5fc6a39bc6d34fb2a3806 /libcrystfel
parent169e7c5677ffc9c296c0a7eeddb0b77e024a4a55 (diff)
Implement parse_symmetry_operations
Diffstat (limited to 'libcrystfel')
-rw-r--r--libcrystfel/src/rational.c25
-rw-r--r--libcrystfel/src/rational.h1
-rw-r--r--libcrystfel/src/symmetry.c122
-rw-r--r--libcrystfel/src/symmetry.h9
-rw-r--r--libcrystfel/src/symop.l1
-rw-r--r--libcrystfel/src/symop.y41
6 files changed, 117 insertions, 82 deletions
diff --git a/libcrystfel/src/rational.c b/libcrystfel/src/rational.c
index b6ca5dd4..5db83165 100644
--- a/libcrystfel/src/rational.c
+++ b/libcrystfel/src/rational.c
@@ -326,6 +326,31 @@ RationalMatrix *rtnl_mtx_from_intmat(const IntegerMatrix *m)
}
+IntegerMatrix *intmat_from_rtnl_mtx(const RationalMatrix *m)
+{
+ IntegerMatrix *n;
+ int i, j;
+
+ n = intmat_new(m->rows, m->cols);
+ if ( n == NULL ) return NULL;
+
+ for ( i=0; i<m->rows; i++ ) {
+ for ( j=0; j<m->cols; j++ ) {
+ Rational v = rtnl_mtx_get(m, i, j);
+ squish(&v);
+ if ( v.den != 1 ) {
+ ERROR("Rational matrix can't be converted to integers\n");
+ intmat_free(n);
+ return NULL;
+ }
+ intmat_set(n, i, j, v.num);
+ }
+ }
+
+ return n;
+}
+
+
void rtnl_mtx_free(RationalMatrix *mtx)
{
if ( mtx == NULL ) return;
diff --git a/libcrystfel/src/rational.h b/libcrystfel/src/rational.h
index e2d3e5bf..925f9be1 100644
--- a/libcrystfel/src/rational.h
+++ b/libcrystfel/src/rational.h
@@ -82,6 +82,7 @@ extern RationalMatrix *rtnl_mtx_copy(const RationalMatrix *m);
extern Rational rtnl_mtx_get(const RationalMatrix *m, int i, int j);
extern void rtnl_mtx_set(const RationalMatrix *m, int i, int j, Rational v);
extern RationalMatrix *rtnl_mtx_from_intmat(const IntegerMatrix *m);
+extern IntegerMatrix *intmat_from_rtnl_mtx(const RationalMatrix *m);
extern void rtnl_mtx_free(RationalMatrix *mtx);
extern void rtnl_mtx_mult(const RationalMatrix *m, const Rational *vec,
Rational *ans);
diff --git a/libcrystfel/src/symmetry.c b/libcrystfel/src/symmetry.c
index 19c754ea..9ee80a16 100644
--- a/libcrystfel/src/symmetry.c
+++ b/libcrystfel/src/symmetry.c
@@ -3,12 +3,12 @@
*
* Symmetry
*
- * Copyright © 2012-2016 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2019 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2014,2016 Thomas White <taw@physics.org>
- * 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
+ * 2010-2019 Thomas White <taw@physics.org>
+ * 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
*
* This file is part of CrystFEL.
*
@@ -1638,102 +1638,76 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
}
-static IntegerMatrix *parse_symmetry_operation(const char *s)
+/* Parse a single symmetry operation, e.g. 'h,-2k,(h+l)/3' */
+RationalMatrix *parse_symmetry_operation(const char *s)
{
- IntegerMatrix *m;
- char **els;
- int n, i;
+ YY_BUFFER_STATE b;
+ RationalMatrix *m;
+ int r;
+ m = rtnl_mtx_new(3, 3);
+ b = symop_scan_string(s);
+ r = symopparse(m, NULL);
+ symop_delete_buffer(b);
- n = assplode(s, ",", &els, ASSPLODE_NONE);
- if ( n != 3 ) {
- for ( i=0; i<n; i++ ) free(els[i]);
- free(els);
+ if ( r ) {
+ ERROR("Failed to parse '%s'\n", s);
+ rtnl_mtx_free(m);
return NULL;
}
- m = intmat_new(3, 3);
- if ( m == NULL ) return NULL;
-
- for ( i=0; i<n; i++ ) {
-
- int c;
- size_t cl;
- signed int nh = 0;
- signed int nk = 0;
- signed int nl = 0;
- signed int mult = 1;
- int ndigit = 0;
- signed int sign = +1;
-
- /* We have one expression something like "-2h+k" */
- cl = strlen(els[i]);
- for ( c=0; c<cl; c++ ) {
-
- if ( els[i][c] == '-' ) sign *= -1;
- if ( els[i][c] == 'h' ) {
- nh = mult*sign;
- mult = 1;
- ndigit = 0;
- sign = +1;
- }
- if ( els[i][c] == 'k' ) {
- nk = mult*sign;
- mult = 1;
- ndigit = 0;
- sign = +1;
- }
- if ( els[i][c] == 'l' ) {
- nl = mult*sign;
- mult = 1;
- ndigit = 0;
- sign = +1;
- }
- if ( isdigit(els[i][c]) ) {
- if ( ndigit > 0 ) {
- mult *= 10;
- mult += els[i][c] - '0';
- } else {
- mult *= els[i][c] - '0';
- }
- ndigit++;
- }
- }
-
- intmat_set(m, i, 0, nh);
- intmat_set(m, i, 1, nk);
- intmat_set(m, i, 2, nl);
-
- free(els[i]);
+ return m;
+}
- }
- free(els);
- return m;
+/**
+ * parse_cell_transformation
+ * @s: Textual representation of cell transformation
+ *
+ * Parses @s, for example 'a,(b+a)/2,c', and returns the corresponding
+ * %RationalMatrix.
+ *
+ * Returns: A %RationalMatrix describing the transformation, or NULL on error.
+ *
+ */
+RationalMatrix *parse_cell_transformation(const char *s)
+{
+ return parse_symmetry_operation(s);
}
+/**
+ * parse_symmetry_operations
+ * @s: Textual representation of a list of symmetry operations
+ *
+ * Parses @s, for example 'h,k,l;k,h,-l', and returns the corresponding
+ * %SymOpList
+ *
+ * Returns: A %SymOpList, or NULL on error.
+ *
+ */
SymOpList *parse_symmetry_operations(const char *s)
{
YY_BUFFER_STATE b;
RationalMatrix *m;
+ SymOpList *list;
int r;
- m = rtnl_mtx_new(3, 3);
+ m = rtnl_mtx_new(3, 3); /* Scratch space for parser */
+ list = new_symoplist(); /* The result we want */
+
b = symop_scan_string(s);
- r = symopparse(m);
+ r = symopparse(m, list);
symop_delete_buffer(b);
+ rtnl_mtx_free(m);
if ( r ) {
ERROR("Failed to parse '%s'\n", s);
- rtnl_mtx_free(m);
+ free_symoplist(list);
return NULL;
}
- STATUS("Parsed OK\n");
- rtnl_mtx_print(m);
-
- return NULL;
+ return list;
}
diff --git a/libcrystfel/src/symmetry.h b/libcrystfel/src/symmetry.h
index a61ca96f..ab2aa934 100644
--- a/libcrystfel/src/symmetry.h
+++ b/libcrystfel/src/symmetry.h
@@ -3,12 +3,12 @@
*
* Symmetry
*
- * Copyright © 2012-2016 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2019 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2014,2016 Thomas White <taw@physics.org>
- * 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
+ * 2010-2019 Thomas White <taw@physics.org>
+ * 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
*
* This file is part of CrystFEL.
*
@@ -36,6 +36,7 @@
#include "integer_matrix.h"
+#include "rational.h"
/**
* SymOpList
@@ -93,7 +94,9 @@ extern int is_centric(signed int h, signed int k, signed int l,
extern void pointgroup_warning(const char *sym);
extern void add_symop(SymOpList *ops, IntegerMatrix *m);
+extern RationalMatrix *parse_symmetry_operation(const char *s);
extern SymOpList *parse_symmetry_operations(const char *s);
+extern RationalMatrix *parse_cell_transformation(const char *s);
extern char *get_matrix_name(const IntegerMatrix *m, int row);
#ifdef __cplusplus
diff --git a/libcrystfel/src/symop.l b/libcrystfel/src/symop.l
index b00b35b4..ed38a65e 100644
--- a/libcrystfel/src/symop.l
+++ b/libcrystfel/src/symop.l
@@ -47,5 +47,6 @@
[clz] { return L; }
[(] { return OPENB; }
[)] { return CLOSEB; }
+[;] { return SEMICOLON; }
%%
diff --git a/libcrystfel/src/symop.y b/libcrystfel/src/symop.y
index 4aec791a..a304ea37 100644
--- a/libcrystfel/src/symop.y
+++ b/libcrystfel/src/symop.y
@@ -30,15 +30,20 @@
#include <stdio.h>
#include "rational.h"
+ #include "symmetry.h"
extern int symoplex();
- extern int symopparse(RationalMatrix *m);
- void symoperror(RationalMatrix *m, const char *s);
+ extern int symopparse(RationalMatrix *m, SymOpList *list);
+ void symoperror(RationalMatrix *m, SymOpList *list, const char *s);
%}
%define api.prefix {symop}
-%parse-param {RationalMatrix *m}
+%parse-param {RationalMatrix *m} {SymOpList *list}
+
+%code requires {
+ #include "symmetry.h"
+}
%union {
RationalMatrix *m; /* Full rational matrix */
@@ -47,6 +52,7 @@
int n; /* Just a number */
}
+%token SEMICOLON
%token COMMA
%token NUMBER
%token OPENB CLOSEB
@@ -63,8 +69,33 @@
%type <n> NUMBER
%type <r> fraction
+%{
+static int try_add_symop(SymOpList *list, RationalMatrix *m)
+{
+ if ( list == NULL ) {
+ yyerror(m, list, "Must be a single symmetry operation");
+ return 1;
+ } else {
+ IntegerMatrix *im;
+ im = intmat_from_rtnl_mtx(m);
+ if ( im == NULL ) {
+ yyerror(m, list, "Symmetry operations must all be integer");
+ return 1;
+ } else {
+ add_symop(list, im);
+ }
+ }
+ return 0;
+}
+%}
+
%%
+symoplist:
+ symop { if ( try_add_symop(list, m) ) YYERROR; }
+| symoplist SEMICOLON symop { if ( try_add_symop(list, m) ) YYERROR; }
+;
+
symop:
axexpr COMMA axexpr COMMA axexpr { rtnl_mtx_set(m, 0, 0, $1[0]);
rtnl_mtx_set(m, 0, 1, $1[1]);
@@ -101,6 +132,6 @@ fraction:
%%
-void symoperror(RationalMatrix *m, const char *s) {
- printf("Error\n");
+void symoperror(RationalMatrix *m, SymOpList *list, const char *s) {
+ printf("Error: %s\n", s);
}