From a2f4977e0f8bd9becd50ab5a2ef903038273133c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 18 Feb 2019 16:56:52 +0100 Subject: Implement parse_symmetry_operations --- libcrystfel/src/rational.c | 25 ++++++++++ libcrystfel/src/rational.h | 1 + libcrystfel/src/symmetry.c | 122 ++++++++++++++++++--------------------------- libcrystfel/src/symmetry.h | 9 ++-- libcrystfel/src/symop.l | 1 + libcrystfel/src/symop.y | 41 +++++++++++++-- 6 files changed, 117 insertions(+), 82 deletions(-) (limited to 'libcrystfel') 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; irows; i++ ) { + for ( j=0; jcols; 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 - * 2014 Kenneth Beyerlein + * 2010-2019 Thomas White + * 2014 Kenneth Beyerlein * * 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 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 - * 2014 Kenneth Beyerlein + * 2010-2019 Thomas White + * 2014 Kenneth Beyerlein * * 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 #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 NUMBER %type 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); } -- cgit v1.2.3