From 85d6684288fd474f3eea89d6aa53c28b8fdafe91 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 25 Sep 2018 15:51:16 +0200 Subject: Initial cell_tool (implementing find_ambi only) --- src/cell_tool.c | 306 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 src/cell_tool.c (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c new file mode 100644 index 00000000..adf9c2a0 --- /dev/null +++ b/src/cell_tool.c @@ -0,0 +1,306 @@ +/* + * cell_tool.c + * + * Unit cell tool + * + * Copyright © 2018 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2012-2018 Thomas White + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see . + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "cell.h" +#include "cell-utils.h" +#include "reflist-utils.h" +#include "reflist.h" + + +static void show_help(const char *s) +{ + printf("Syntax: %s [options]\n\n", s); + printf( +"Unit cell manipulation tool.\n" +"\n" +" -h, --help Display this help message.\n" +" -p, --pdb= Get unit cell from (PDB or CrystFEL format).\n" +"\n" +" Actions:\n" +" --find-ambi Find indexing ambiguities for the cell.\n" +" --uncenter Calculate a primitive cell.\n" +" --rings Calculate powder ring positions.\n" +" --compare-cell Compare unit cell with cell from .\n" +"\n" +" -y Real point group of the structure.\n" +" --tolerance= Set the tolerances for cell reduction.\n" +" Default: 5,5,5,1.5.\n" +); +} + + +static int cells_are_similar(UnitCell *cell1, UnitCell *cell2, float *tols) +{ + double a1, b1, c1, al1, be1, ga1; + double a2, b2, c2, al2, be2, ga2; + UnitCellTransformation *tfn1, *tfn2; + UnitCell *pcell1, *pcell2; + + /* Compare primitive cells, not centered */ + pcell1 = uncenter_cell(cell1, &tfn1); + pcell2 = uncenter_cell(cell2, &tfn2); + + cell_get_parameters(pcell1, &a1, &b1, &c1, &al1, &be1, &ga1); + cell_get_parameters(pcell2, &a2, &b2, &c2, &al2, &be2, &ga2); + + cell_free(pcell1); + cell_free(pcell2); + + if ( !within_tolerance(a1, a2, tols[0]) ) return 0; + if ( !within_tolerance(b1, b2, tols[1]) ) return 0; + if ( !within_tolerance(c1, c2, tols[2]) ) return 0; + if ( !within_tolerance(al1, al2, tols[3]) ) return 0; + if ( !within_tolerance(be1, be2, tols[3]) ) return 0; + if ( !within_tolerance(ga1, ga2, tols[3]) ) return 0; + + return 1; +} + + +static int find_ambi(UnitCell *cell, SymOpList *sym, float *tols) +{ + SymOpList *amb; + SymOpList *ops; + signed int i[9]; + const int maxorder = 3; + + ops = get_pointgroup("1"); + if ( ops == NULL ) return 1; + set_symmetry_name(ops, "Observed"); + + STATUS("Looking for ambiguities up to 3x each lattice length.\n"); + STATUS("This will take about 30 seconds. Please wait...\n"); + + for ( i[0]=-maxorder; i[0]<=+maxorder; i[0]++ ) { + for ( i[1]=-maxorder; i[1]<=+maxorder; i[1]++ ) { + for ( i[2]=-maxorder; i[2]<=+maxorder; i[2]++ ) { + for ( i[3]=-maxorder; i[3]<=+maxorder; i[3]++ ) { + for ( i[4]=-maxorder; i[4]<=+maxorder; i[4]++ ) { + for ( i[5]=-maxorder; i[5]<=+maxorder; i[5]++ ) { + for ( i[6]=-maxorder; i[6]<=+maxorder; i[6]++ ) { + for ( i[7]=-maxorder; i[7]<=+maxorder; i[7]++ ) { + for ( i[8]=-maxorder; i[8]<=+maxorder; i[8]++ ) { + + UnitCellTransformation *tfn; + UnitCell *nc; + IntegerMatrix *m; + int j, k; + int l = 0; + + m = intmat_new(3, 3); + for ( j=0; j<3; j++ ) { + for ( k=0; k<3; k++ ) { + intmat_set(m, j, k, i[l++]); + } + } + + if ( intmat_det(m) != +1 ) continue; + + tfn = tfn_from_intmat(m); + nc = cell_transform(cell, tfn); + + if ( cells_are_similar(cell, nc, tols) ) { + if ( !intmat_is_identity(m) ) add_symop(ops, m); + STATUS("-----------------------------------------------" + "-------------------------------------------\n"); + cell_print(nc); + intmat_print(m); + } else { + intmat_free(m); + } + + tfn_free(tfn); + cell_free(nc); + + } + } + } + } + } + } + } + } + } + + STATUS("Observed symmetry operations:\n"); + describe_symmetry(ops); + + amb = get_ambiguities(ops, sym); + if ( amb == NULL ) { + STATUS("No ambiguities (or error calculating them)\n"); + } else { + STATUS("Ambiguity operations:\n"); + describe_symmetry(amb); + free_symoplist(amb); + } + + free_symoplist(ops); + + return 0; +} + + +enum { + CT_NOTHING, + CT_FINDAMBI, + CT_UNCENTER, + CT_RINGS, + CT_COMPARE, + CT_CHOICES, +}; + + +int main(int argc, char *argv[]) +{ + int c; + char *cell_file = NULL; + UnitCell *cell; + char *toler = NULL; + float tols[4] = {5.0, 5.0, 5.0, 1.5}; /* a,b,c,angles (%,%,%,deg) */ + char *sym_str = NULL; + SymOpList *sym; + int mode = CT_NOTHING; + char *comparecell = NULL; + + /* Long options */ + const struct option longopts[] = { + {"help", 0, NULL, 'h'}, + {"pdb", 1, NULL, 'p'}, + {"tolerance", 1, NULL, 2}, + + /* Modes of operation */ + {"find-ambi", 0, &mode, CT_FINDAMBI}, + {"uncenter", 0, &mode, CT_UNCENTER}, + {"uncentre", 0, &mode, CT_UNCENTER}, + {"rings", 0, &mode, CT_RINGS}, + {"compare-cell", 1, NULL, 3}, + {"highres", 1, NULL, 5}, + + {0, 0, NULL, 0} + }; + + /* Short options */ + while ((c = getopt_long(argc, argv, "hp:y:", + longopts, NULL)) != -1) { + + switch (c) { + + case 'h' : + show_help(argv[0]); + return 0; + + case 'p' : + cell_file = strdup(optarg); + break; + + case 'y' : + sym_str = strdup(optarg); + break; + + case 2 : + toler = strdup(optarg); + break; + + case 3 : + comparecell = strdup(optarg); + mode = CT_COMPARE; + break; + + case 0 : + break; + + default : + return 1; + + } + + } + + if ( cell_file == NULL ) { + ERROR("You must give a filename for the unit cell PDB file.\n"); + return 1; + } + cell = load_cell_from_file(cell_file); + if ( cell == NULL ) { + ERROR("Failed to load cell from '%s'\n", cell_file); + return 1; + } + free(cell_file); + + if ( toler != NULL ) { + int ttt; + ttt = sscanf(toler, "%f,%f,%f,%f", + &tols[0], &tols[1], &tols[2], &tols[3] ); + if ( ttt != 4 ) { + ERROR("Invalid parameters for '--tolerance'\n"); + return 1; + } + free(toler); + } + + STATUS("Input unit cell:\n"); + cell_print(cell); + + if ( validate_cell(cell) ) { + ERROR("Cell is invalid.\n"); + return 1; + } + + if ( sym_str == NULL ) { + ERROR("Please specify the point group of the structure.\n"); + return 1; + } + + sym = get_pointgroup(sym_str); + if ( sym == NULL ) return 1; + free(sym_str); + + if ( mode == CT_NOTHING ) { + ERROR("Please specify mode of operation (see --help)\n"); + return 1; + } + + if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, tols); + + /* FIXME: Everything else */ + ERROR("Sorry, this mode of operation is not yet implemented.\n"); + return 1; +} -- cgit v1.2.3 From 95047782595e3d246d65e350802fe6c012da4d5d Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 27 Sep 2018 11:13:43 +0200 Subject: cell_tool: Add --uncenter --- src/cell_tool.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index adf9c2a0..48cbeaa7 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -106,6 +106,11 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, float *tols) if ( ops == NULL ) return 1; set_symmetry_name(ops, "Observed"); + if ( sym == NULL ) { + ERROR("Please specify the point group of the structure.\n"); + return 1; + } + STATUS("Looking for ambiguities up to 3x each lattice length.\n"); STATUS("This will take about 30 seconds. Please wait...\n"); @@ -178,6 +183,23 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, float *tols) } +static int uncenter(UnitCell *cell) +{ + UnitCell *cnew; + UnitCellTransformation *trans; + + cnew = uncenter_cell(cell, &trans); + + STATUS("------------------> The primitive unit cell:\n"); + cell_print(cnew); + + STATUS("------------------> The decentering transformation:\n"); + tfn_print(trans); + + return 0; +} + + enum { CT_NOTHING, CT_FINDAMBI, @@ -196,7 +218,7 @@ int main(int argc, char *argv[]) char *toler = NULL; float tols[4] = {5.0, 5.0, 5.0, 1.5}; /* a,b,c,angles (%,%,%,deg) */ char *sym_str = NULL; - SymOpList *sym; + SymOpList *sym = NULL; int mode = CT_NOTHING; char *comparecell = NULL; @@ -276,7 +298,7 @@ int main(int argc, char *argv[]) free(toler); } - STATUS("Input unit cell:\n"); + STATUS("------------------> The input unit cell:\n"); cell_print(cell); if ( validate_cell(cell) ) { @@ -284,21 +306,19 @@ int main(int argc, char *argv[]) return 1; } - if ( sym_str == NULL ) { - ERROR("Please specify the point group of the structure.\n"); - return 1; + if ( sym_str != NULL ) { + sym = get_pointgroup(sym_str); + if ( sym == NULL ) return 1; + free(sym_str); } - sym = get_pointgroup(sym_str); - if ( sym == NULL ) return 1; - free(sym_str); - if ( mode == CT_NOTHING ) { ERROR("Please specify mode of operation (see --help)\n"); return 1; } if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, tols); + if ( mode == CT_UNCENTER ) return uncenter(cell); /* FIXME: Everything else */ ERROR("Sorry, this mode of operation is not yet implemented.\n"); -- cgit v1.2.3 From ed1fd7f414b11c5db3848bd8c2a216af7df928f8 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 27 Sep 2018 14:19:03 +0200 Subject: cell_tool --uncenter: Write unit cell to file --- src/cell_tool.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 48cbeaa7..3e638179 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -53,6 +53,7 @@ static void show_help(const char *s) "\n" " -h, --help Display this help message.\n" " -p, --pdb= Get unit cell from (PDB or CrystFEL format).\n" +" -o Output unit cell file.\n" "\n" " Actions:\n" " --find-ambi Find indexing ambiguities for the cell.\n" @@ -183,7 +184,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, float *tols) } -static int uncenter(UnitCell *cell) +static int uncenter(UnitCell *cell, const char *out_file) { UnitCell *cnew; UnitCellTransformation *trans; @@ -196,6 +197,16 @@ static int uncenter(UnitCell *cell) STATUS("------------------> The decentering transformation:\n"); tfn_print(trans); + if ( out_file != NULL ) { + FILE *fh = fopen(out_file, "w"); + if ( fh == NULL ) { + ERROR("Failed to open '%s'\n", out_file); + return 1; + } + write_cell(cnew, fh); + fclose(fh); + } + return 0; } @@ -221,12 +232,14 @@ int main(int argc, char *argv[]) SymOpList *sym = NULL; int mode = CT_NOTHING; char *comparecell = NULL; + char *out_file = NULL; /* Long options */ const struct option longopts[] = { {"help", 0, NULL, 'h'}, {"pdb", 1, NULL, 'p'}, {"tolerance", 1, NULL, 2}, + {"output", 1, NULL, 'o'}, /* Modes of operation */ {"find-ambi", 0, &mode, CT_FINDAMBI}, @@ -240,7 +253,7 @@ int main(int argc, char *argv[]) }; /* Short options */ - while ((c = getopt_long(argc, argv, "hp:y:", + while ((c = getopt_long(argc, argv, "hp:y:o:", longopts, NULL)) != -1) { switch (c) { @@ -253,6 +266,10 @@ int main(int argc, char *argv[]) cell_file = strdup(optarg); break; + case 'o' : + out_file = strdup(optarg); + break; + case 'y' : sym_str = strdup(optarg); break; @@ -318,7 +335,7 @@ int main(int argc, char *argv[]) } if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, tols); - if ( mode == CT_UNCENTER ) return uncenter(cell); + if ( mode == CT_UNCENTER ) return uncenter(cell, out_file); /* FIXME: Everything else */ ERROR("Sorry, this mode of operation is not yet implemented.\n"); -- cgit v1.2.3 From 0cb30a180c57d918febb541126ff840144398e69 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 1 Oct 2018 14:25:36 +0200 Subject: cell_tool: Add --rings --- src/cell_tool.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 3e638179..1403b394 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -96,6 +96,115 @@ static int cells_are_similar(UnitCell *cell1, UnitCell *cell2, float *tols) } +struct sortmerefl { + signed int h; + signed int k; + signed int l; + double resolution; + int multi; +}; + + +static int cmpres(const void *av, const void *bv) +{ + const struct sortmerefl *a = av; + const struct sortmerefl *b = bv; + return a->resolution > b->resolution; +} + + +static int all_rings(UnitCell *cell, SymOpList *sym) +{ + double ax, ay, az; + double bx, by, bz; + double cx, cy, cz; + int hmax, kmax, lmax; + double mres; + signed int h, k, l; + RefList *list; + int i, n; + RefListIterator *iter; + Reflection *refl; + struct sortmerefl *sortus; + double highres = 2.0; /* Angstroms */ + + mres = 1.0/(highres*1e-10); + cell_get_cartesian(cell, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz); + hmax = mres * modulus(ax, ay, az); + kmax = mres * modulus(bx, by, bz); + lmax = mres * modulus(cx, cy, cz); + list = reflist_new(); + for ( h=-hmax; h<=hmax; h++ ) { + for ( k=-kmax; k<=kmax; k++ ) { + for ( l=-lmax; l<=lmax; l++ ) { + + signed int ha, ka, la; + + if ( forbidden_reflection(cell, h, k, l) ) continue; + if ( 2.0*resolution(cell, h, k, l) > mres ) continue; + + if ( sym != NULL ) { + + Reflection *refl; + + get_asymm(sym, h, k, l, &ha, &ka, &la); + refl = find_refl(list, ha, ka, la); + if ( refl == NULL ) { + refl = add_refl(list, ha, ka, la); + set_redundancy(refl, 1); + } else { + set_redundancy(refl, get_redundancy(refl)+1); + } + + } else { + Reflection *refl; + refl = add_refl(list, h, k, l); + set_redundancy(refl, 1); + } + + } + } + } + + n = num_reflections(list); + sortus = malloc(n*sizeof(struct sortmerefl)); + + i = 0; + for ( refl = first_refl(list, &iter); + refl != NULL; + refl = next_refl(refl, iter) ) + { + signed int h, k, l; + + get_indices(refl, &h, &k, &l); + + sortus[i].h = h; + sortus[i].k = k; + sortus[i].l = l; + sortus[i].resolution = 2.0*resolution(cell, h, k, l); /* one over d */ + sortus[i].multi = get_redundancy(refl); + i++; + + } + + qsort(sortus, n, sizeof(struct sortmerefl), cmpres); + + STATUS("\nAll powder rings up to %f Ångstrøms.\n", highres); + STATUS("Note that screw axis or glide plane absences are not " + "omitted from this list.\n"); + STATUS("\n d (Å) 1/d (m^-1) h k l multiplicity\n"); + STATUS("------------------------------------------------------\n"); + for ( i=0; i Date: Mon, 1 Oct 2018 17:00:17 +0200 Subject: cell_tool: Use libcrystfel cells_are_similar() function --- src/cell_tool.c | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 1403b394..4a719391 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -62,37 +62,12 @@ static void show_help(const char *s) " --compare-cell Compare unit cell with cell from .\n" "\n" " -y Real point group of the structure.\n" -" --tolerance= Set the tolerances for cell reduction.\n" -" Default: 5,5,5,1.5.\n" +" --tolerance= Set the tolerances for cell comparison.\n" +" Default: 5,1.5 (axis percentage, angle deg).\n" ); } -static int cells_are_similar(UnitCell *cell1, UnitCell *cell2, float *tols) -{ - double a1, b1, c1, al1, be1, ga1; - double a2, b2, c2, al2, be2, ga2; - UnitCellTransformation *tfn1, *tfn2; - UnitCell *pcell1, *pcell2; - - /* Compare primitive cells, not centered */ - pcell1 = uncenter_cell(cell1, &tfn1); - pcell2 = uncenter_cell(cell2, &tfn2); - - cell_get_parameters(pcell1, &a1, &b1, &c1, &al1, &be1, &ga1); - cell_get_parameters(pcell2, &a2, &b2, &c2, &al2, &be2, &ga2); - - cell_free(pcell1); - cell_free(pcell2); - - if ( !within_tolerance(a1, a2, tols[0]) ) return 0; - if ( !within_tolerance(b1, b2, tols[1]) ) return 0; - if ( !within_tolerance(c1, c2, tols[2]) ) return 0; - if ( !within_tolerance(al1, al2, tols[3]) ) return 0; - if ( !within_tolerance(be1, be2, tols[3]) ) return 0; - if ( !within_tolerance(ga1, ga2, tols[3]) ) return 0; - - return 1; } @@ -205,7 +180,7 @@ static int all_rings(UnitCell *cell, SymOpList *sym) } -static int find_ambi(UnitCell *cell, SymOpList *sym, float *tols) +static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) { SymOpList *amb; SymOpList *ops; @@ -252,7 +227,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, float *tols) tfn = tfn_from_intmat(m); nc = cell_transform(cell, tfn); - if ( cells_are_similar(cell, nc, tols) ) { + if ( cells_are_similar(cell, nc, ltl, atl) ) { if ( !intmat_is_identity(m) ) add_symop(ops, m); STATUS("-----------------------------------------------" "-------------------------------------------\n"); @@ -336,7 +311,8 @@ int main(int argc, char *argv[]) char *cell_file = NULL; UnitCell *cell; char *toler = NULL; - float tols[4] = {5.0, 5.0, 5.0, 1.5}; /* a,b,c,angles (%,%,%,deg) */ + double ltl = 5.0/100.0; + double atl = deg2rad(1.5); char *sym_str = NULL; SymOpList *sym = NULL; int mode = CT_NOTHING; @@ -414,13 +390,12 @@ int main(int argc, char *argv[]) free(cell_file); if ( toler != NULL ) { - int ttt; - ttt = sscanf(toler, "%f,%f,%f,%f", - &tols[0], &tols[1], &tols[2], &tols[3] ); - if ( ttt != 4 ) { - ERROR("Invalid parameters for '--tolerance'\n"); + if ( sscanf(toler, "%f,%f", <l, &atl) != 2 ) { + ERROR("Invalid parameters for --tolerance\n"); return 1; } + ltl /= 100.0; /* Percent to fraction */ + atl = deg2rad(atl); free(toler); } @@ -443,7 +418,7 @@ int main(int argc, char *argv[]) return 1; } - if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, tols); + if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, ltl, atl); if ( mode == CT_UNCENTER ) return uncenter(cell, out_file); if ( mode == CT_RINGS ) return all_rings(cell, sym); -- cgit v1.2.3 From cd9951423216c429755954e671cac2111eedb953 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 1 Oct 2018 17:00:36 +0200 Subject: Show the actual number of orders --- src/cell_tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 4a719391..beb03597 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -196,7 +196,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) return 1; } - STATUS("Looking for ambiguities up to 3x each lattice length.\n"); + STATUS("Looking for ambiguities up to %ix each lattice length.\n", maxorder); STATUS("This will take about 30 seconds. Please wait...\n"); for ( i[0]=-maxorder; i[0]<=+maxorder; i[0]++ ) { -- cgit v1.2.3 From 95e4bb31cb32d684dfdafaf3f0e76fb17541fe26 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 1 Oct 2018 17:00:56 +0200 Subject: cell_tool: Improve option processing --- src/cell_tool.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index beb03597..8453c9f7 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -378,10 +378,25 @@ int main(int argc, char *argv[]) } + /* If there's a parameter left over, we assume it's the unit cell */ + if ( (argc > optind) && (cell_file == NULL) ) { + cell_file = strdup(argv[optind++]); + } + + /* If there's STILL a parameter left over, complain*/ + if ( argc > optind ) { + ERROR("Excess command-line arguments:\n"); + do { + ERROR("'%s'\n", argv[optind++]); + } while ( argc > optind ); + return 1; + } + if ( cell_file == NULL ) { ERROR("You must give a filename for the unit cell PDB file.\n"); return 1; } + STATUS("Input unit cell: %s\n", cell_file); cell = load_cell_from_file(cell_file); if ( cell == NULL ) { ERROR("Failed to load cell from '%s'\n", cell_file); -- cgit v1.2.3 From 08abdc901b1268aea325c04f4a5697c90a6a7d45 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 1 Oct 2018 17:21:24 +0200 Subject: Fix tolerances --- src/cell_tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 8453c9f7..70d80552 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -311,8 +311,8 @@ int main(int argc, char *argv[]) char *cell_file = NULL; UnitCell *cell; char *toler = NULL; - double ltl = 5.0/100.0; - double atl = deg2rad(1.5); + float ltl = 5.0/100.0; + float atl = deg2rad(1.5); char *sym_str = NULL; SymOpList *sym = NULL; int mode = CT_NOTHING; -- cgit v1.2.3 From 5ce8e318bcd3389acb28685c930e23087bf8722b Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 1 Oct 2018 17:26:12 +0200 Subject: cell_tool: Add --compare (doesn't seem to work yet for some reason) --- src/cell_tool.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 70d80552..3450c299 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -68,6 +68,82 @@ static void show_help(const char *s) } +static int comparecells(UnitCell *cell, const char *comparecell, + double ltl, double atl) +{ + signed int i[9]; + const int maxorder = 2; + UnitCell *cell2; + + STATUS("Comparing with: %s\n", comparecell); + + cell2 = load_cell_from_file(comparecell); + if ( cell2 == NULL ) { + ERROR("Failed to load unit cell from '%s'\n", comparecell); + return 1; + } + if ( validate_cell(cell2) ) { + ERROR("Comparison cell is invalid.\n"); + return 1; + } + STATUS("------------------> The reference unit cell:\n"); + cell_print(cell2); + + STATUS("Comparing cells up to %ix each lattice length.\n", maxorder); + STATUS("Reciprocal axis length tolerance %f %%\n", ltl*100.0); + STATUS("Reciprocal angle tolerance %f degrees\n", rad2deg(atl)); + STATUS("This will take about 30 seconds. Please wait...\n"); + + for ( i[0]=-maxorder; i[0]<=+maxorder; i[0]++ ) { + for ( i[1]=-maxorder; i[1]<=+maxorder; i[1]++ ) { + for ( i[2]=-maxorder; i[2]<=+maxorder; i[2]++ ) { + for ( i[3]=-maxorder; i[3]<=+maxorder; i[3]++ ) { + for ( i[4]=-maxorder; i[4]<=+maxorder; i[4]++ ) { + for ( i[5]=-maxorder; i[5]<=+maxorder; i[5]++ ) { + for ( i[6]=-maxorder; i[6]<=+maxorder; i[6]++ ) { + for ( i[7]=-maxorder; i[7]<=+maxorder; i[7]++ ) { + for ( i[8]=-maxorder; i[8]<=+maxorder; i[8]++ ) { + + UnitCellTransformation *tfn; + UnitCell *nc; + IntegerMatrix *m; + int j, k; + int l = 0; + + m = intmat_new(3, 3); + for ( j=0; j<3; j++ ) { + for ( k=0; k<3; k++ ) { + intmat_set(m, j, k, i[l++]); + } + } + + if ( intmat_det(m) < 1 ) continue; + + tfn = tfn_from_intmat(m); + nc = cell_transform(cell, tfn); + + if ( cells_are_similar(cell2, nc, ltl, atl) ) { + STATUS("-----------------------------------------------" + "-------------------------------------------\n"); + cell_print(nc); + intmat_print(m); + } + + intmat_free(m); + tfn_free(tfn); + cell_free(nc); + + } + } + } + } + } + } + } + } + } + + return 0; } @@ -436,6 +512,7 @@ int main(int argc, char *argv[]) if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, ltl, atl); if ( mode == CT_UNCENTER ) return uncenter(cell, out_file); if ( mode == CT_RINGS ) return all_rings(cell, sym); + if ( mode == CT_COMPARE ) return comparecells(cell, comparecell, ltl, atl); /* FIXME: Everything else */ ERROR("Sorry, this mode of operation is not yet implemented.\n"); -- cgit v1.2.3 From e06952e9eefb0affb65d5361d1919d28bee5974d Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 15 Oct 2018 16:01:47 +0200 Subject: Remove cells_are_similar() from API There are two functions with this name. Avoid confusion. --- src/cell_tool.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 3450c299..085134b3 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -68,6 +68,34 @@ static void show_help(const char *s) } +static int cells_the_same(UnitCell *cell1, UnitCell *cell2, float ltl, float atl) +{ + double a1, b1, c1, al1, be1, ga1; + double a2, b2, c2, al2, be2, ga2; + UnitCellTransformation *tfn1, *tfn2; + UnitCell *pcell1, *pcell2; + + /* Compare primitive cells, not centered */ + pcell1 = uncenter_cell(cell1, &tfn1); + pcell2 = uncenter_cell(cell2, &tfn2); + + cell_get_parameters(pcell1, &a1, &b1, &c1, &al1, &be1, &ga1); + cell_get_parameters(pcell2, &a2, &b2, &c2, &al2, &be2, &ga2); + + cell_free(pcell1); + cell_free(pcell2); + + if ( !within_tolerance(a1, a2, ltl) ) return 0; + if ( !within_tolerance(b1, b2, ltl) ) return 0; + if ( !within_tolerance(c1, c2, ltl) ) return 0; + if ( !within_tolerance(al1, al2, atl) ) return 0; + if ( !within_tolerance(be1, be2, atl) ) return 0; + if ( !within_tolerance(ga1, ga2, atl) ) return 0; + + return 1; +} + + static int comparecells(UnitCell *cell, const char *comparecell, double ltl, double atl) { @@ -122,7 +150,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, tfn = tfn_from_intmat(m); nc = cell_transform(cell, tfn); - if ( cells_are_similar(cell2, nc, ltl, atl) ) { + if ( cells_the_same(cell2, nc, ltl, atl) ) { STATUS("-----------------------------------------------" "-------------------------------------------\n"); cell_print(nc); @@ -303,7 +331,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) tfn = tfn_from_intmat(m); nc = cell_transform(cell, tfn); - if ( cells_are_similar(cell, nc, ltl, atl) ) { + if ( cells_the_same(cell, nc, ltl, atl) ) { if ( !intmat_is_identity(m) ) add_symop(ops, m); STATUS("-----------------------------------------------" "-------------------------------------------\n"); -- cgit v1.2.3 From 1fdd992e4c05a198af907c5312f188374e13c57f Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 16 Oct 2018 09:50:15 +0200 Subject: Don't use within_tolerance for angles --- src/cell_tool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 085134b3..3fd206e9 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -88,9 +88,9 @@ static int cells_the_same(UnitCell *cell1, UnitCell *cell2, float ltl, float atl if ( !within_tolerance(a1, a2, ltl) ) return 0; if ( !within_tolerance(b1, b2, ltl) ) return 0; if ( !within_tolerance(c1, c2, ltl) ) return 0; - if ( !within_tolerance(al1, al2, atl) ) return 0; - if ( !within_tolerance(be1, be2, atl) ) return 0; - if ( !within_tolerance(ga1, ga2, atl) ) return 0; + if ( fabs(al1-al2) > atl ) return 0; + if ( fabs(be1-be2) > atl ) return 0; + if ( fabs(ga1-ga2) > atl ) return 0; return 1; } -- cgit v1.2.3 From 27869f1c27421cd11d61a13224253b6f0dece22c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 16 Oct 2018 09:50:24 +0200 Subject: cell_tool: Check --tolerance has the right number of commas --- src/cell_tool.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 3fd206e9..51e7ea01 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -509,6 +509,16 @@ int main(int argc, char *argv[]) free(cell_file); if ( toler != NULL ) { + int i; + int ncomma = 0; + size_t l = strlen(toler); + for ( i=0; i Date: Tue, 23 Oct 2018 11:19:15 +0200 Subject: cell_tool: Don't uncenter cells before comparison --- src/cell_tool.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 51e7ea01..1a2f33fb 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -73,17 +73,13 @@ static int cells_the_same(UnitCell *cell1, UnitCell *cell2, float ltl, float atl double a1, b1, c1, al1, be1, ga1; double a2, b2, c2, al2, be2, ga2; UnitCellTransformation *tfn1, *tfn2; - UnitCell *pcell1, *pcell2; - /* Compare primitive cells, not centered */ - pcell1 = uncenter_cell(cell1, &tfn1); - pcell2 = uncenter_cell(cell2, &tfn2); + /* Centering must match: we don't arbitrarte primitive vs centered, + * different cell choices etc */ + if ( cell_get_centering(cell1) != cell_get_centering(cell2) ) return 0; - cell_get_parameters(pcell1, &a1, &b1, &c1, &al1, &be1, &ga1); - cell_get_parameters(pcell2, &a2, &b2, &c2, &al2, &be2, &ga2); - - cell_free(pcell1); - cell_free(pcell2); + cell_get_parameters(cell1, &a1, &b1, &c1, &al1, &be1, &ga1); + cell_get_parameters(cell2, &a2, &b2, &c2, &al2, &be2, &ga2); if ( !within_tolerance(a1, a2, ltl) ) return 0; if ( !within_tolerance(b1, b2, ltl) ) return 0; -- cgit v1.2.3 From 481c13eac53cce18272ff3ef3e4994170c7d2e62 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 23 Oct 2018 14:18:40 +0200 Subject: Change horribly confusing names of unit cell comparison functions cells_are_similar -> compare_cell_parameters_and_orientation compare_cells -> compare_reindexed_cell_parameters_and_orientation cell_tool.c:cells_the_same -> cellutils.c:compare_cell_parameters All comparisons now done in real space, checking that centering is the same, and without uncentering anything. --- src/cell_tool.c | 28 ++-------------------------- src/whirligig.c | 13 +++++++------ 2 files changed, 9 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 1a2f33fb..ee82f332 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -68,30 +68,6 @@ static void show_help(const char *s) } -static int cells_the_same(UnitCell *cell1, UnitCell *cell2, float ltl, float atl) -{ - double a1, b1, c1, al1, be1, ga1; - double a2, b2, c2, al2, be2, ga2; - UnitCellTransformation *tfn1, *tfn2; - - /* Centering must match: we don't arbitrarte primitive vs centered, - * different cell choices etc */ - if ( cell_get_centering(cell1) != cell_get_centering(cell2) ) return 0; - - cell_get_parameters(cell1, &a1, &b1, &c1, &al1, &be1, &ga1); - cell_get_parameters(cell2, &a2, &b2, &c2, &al2, &be2, &ga2); - - if ( !within_tolerance(a1, a2, ltl) ) return 0; - if ( !within_tolerance(b1, b2, ltl) ) return 0; - if ( !within_tolerance(c1, c2, ltl) ) return 0; - if ( fabs(al1-al2) > atl ) return 0; - if ( fabs(be1-be2) > atl ) return 0; - if ( fabs(ga1-ga2) > atl ) return 0; - - return 1; -} - - static int comparecells(UnitCell *cell, const char *comparecell, double ltl, double atl) { @@ -146,7 +122,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, tfn = tfn_from_intmat(m); nc = cell_transform(cell, tfn); - if ( cells_the_same(cell2, nc, ltl, atl) ) { + if ( compare_cell_parameters(cell2, nc, ltl, atl) ) { STATUS("-----------------------------------------------" "-------------------------------------------\n"); cell_print(nc); @@ -327,7 +303,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) tfn = tfn_from_intmat(m); nc = cell_transform(cell, tfn); - if ( cells_the_same(cell, nc, ltl, atl) ) { + if ( compare_cell_parameters(cell, nc, ltl, atl) ) { if ( !intmat_is_identity(m) ) add_symop(ops, m); STATUS("-----------------------------------------------" "-------------------------------------------\n"); diff --git a/src/whirligig.c b/src/whirligig.c index f5a435c2..54ade40a 100644 --- a/src/whirligig.c +++ b/src/whirligig.c @@ -309,9 +309,9 @@ static IntegerMatrix *try_all(struct window *win, int n1, int n2, for ( i=0; in_crystals; i++ ) { for ( j=0; jn_crystals; j++ ) { - if ( compare_cells(crystal_get_cell(i1->crystals[i]), - crystal_get_cell(i2->crystals[j]), - 0.1, deg2rad(5.0), &m) ) + if ( compare_reindexed_cell_parameters_and_orientation(crystal_get_cell(i1->crystals[i]), + crystal_get_cell(i2->crystals[j]), + 0.1, deg2rad(5.0), &m) ) { if ( !crystal_used(win, n1, i) && !crystal_used(win, n2, j) ) @@ -377,9 +377,10 @@ static int try_join(struct window *win, int sn) for ( j=0; jimg[win->join_ptr].n_crystals; j++ ) { Crystal *cr2; cr2 = win->img[win->join_ptr].crystals[j]; - if ( compare_cells(ref, crystal_get_cell(cr2), - 0.1, deg2rad(5.0), - &win->mat[sn][win->join_ptr]) ) { + if ( compare_reindexed_cell_parameters_and_orientation(ref, crystal_get_cell(cr2), + 0.1, deg2rad(5.0), + &win->mat[sn][win->join_ptr]) ) + { win->ser[sn][win->join_ptr] = j; cell_free(ref); return 1; -- cgit v1.2.3 From b7d39a5087e2cb4bfaf4bf98b660625f66df8d41 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 26 Oct 2018 16:04:55 +0200 Subject: cell_tool: Fix length tolerance units --- src/cell_tool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index ee82f332..5aaa68a6 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -90,7 +90,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, cell_print(cell2); STATUS("Comparing cells up to %ix each lattice length.\n", maxorder); - STATUS("Reciprocal axis length tolerance %f %%\n", ltl*100.0); + STATUS("Reciprocal axis length tolerance %f %%\n", ltl); STATUS("Reciprocal angle tolerance %f degrees\n", rad2deg(atl)); STATUS("This will take about 30 seconds. Please wait...\n"); @@ -387,7 +387,7 @@ int main(int argc, char *argv[]) char *cell_file = NULL; UnitCell *cell; char *toler = NULL; - float ltl = 5.0/100.0; + float ltl = 5.0; /* in percent */ float atl = deg2rad(1.5); char *sym_str = NULL; SymOpList *sym = NULL; @@ -495,7 +495,7 @@ int main(int argc, char *argv[]) ERROR("Invalid parameters for --tolerance\n"); return 1; } - ltl /= 100.0; /* Percent to fraction */ + /* ltl stays in percent */ atl = deg2rad(atl); free(toler); } -- cgit v1.2.3 From 50f27f725b3ce7cd636eb5c92c9f05fee8d6364b Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 21 Feb 2019 16:14:30 +0100 Subject: cell_tool --rings: Add --highres --- src/cell_tool.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 5aaa68a6..e8e60f30 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -64,6 +64,7 @@ static void show_help(const char *s) " -y Real point group of the structure.\n" " --tolerance= Set the tolerances for cell comparison.\n" " Default: 5,1.5 (axis percentage, angle deg).\n" +" --highres=n Resolution limit (Angstroms) for --rings\n" ); } @@ -164,22 +165,19 @@ static int cmpres(const void *av, const void *bv) } -static int all_rings(UnitCell *cell, SymOpList *sym) +static int all_rings(UnitCell *cell, SymOpList *sym, double mres) { double ax, ay, az; double bx, by, bz; double cx, cy, cz; int hmax, kmax, lmax; - double mres; signed int h, k, l; RefList *list; int i, n; RefListIterator *iter; Reflection *refl; struct sortmerefl *sortus; - double highres = 2.0; /* Angstroms */ - mres = 1.0/(highres*1e-10); cell_get_cartesian(cell, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz); hmax = mres * modulus(ax, ay, az); kmax = mres * modulus(bx, by, bz); @@ -240,7 +238,7 @@ static int all_rings(UnitCell *cell, SymOpList *sym) qsort(sortus, n, sizeof(struct sortmerefl), cmpres); - STATUS("\nAll powder rings up to %f Ångstrøms.\n", highres); + STATUS("\nAll powder rings up to %f Ångstrøms.\n", 1e+10/mres); STATUS("Note that screw axis or glide plane absences are not " "omitted from this list.\n"); STATUS("\n d (Å) 1/d (m^-1) h k l multiplicity\n"); @@ -394,6 +392,8 @@ int main(int argc, char *argv[]) int mode = CT_NOTHING; char *comparecell = NULL; char *out_file = NULL; + float highres; + double rmax = 1/(2.0e-10); /* Long options */ const struct option longopts[] = { @@ -444,6 +444,14 @@ int main(int argc, char *argv[]) mode = CT_COMPARE; break; + case 5 : + if ( sscanf(optarg, "%e", &highres) != 1 ) { + ERROR("Invalid value for --highres\n"); + return 1; + } + rmax = 1.0 / (highres/1e10); + break; + case 0 : break; @@ -521,7 +529,7 @@ int main(int argc, char *argv[]) if ( mode == CT_FINDAMBI ) return find_ambi(cell, sym, ltl, atl); if ( mode == CT_UNCENTER ) return uncenter(cell, out_file); - if ( mode == CT_RINGS ) return all_rings(cell, sym); + if ( mode == CT_RINGS ) return all_rings(cell, sym, rmax); if ( mode == CT_COMPARE ) return comparecells(cell, comparecell, ltl, atl); /* FIXME: Everything else */ -- cgit v1.2.3 From a9203226058dfd8ba35aa2e192ca51e030d3394a Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 18 Feb 2019 16:57:08 +0100 Subject: get_hkl --reindex: Check that the user provides only one reindexing operation --- src/get_hkl.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/get_hkl.c b/src/get_hkl.c index efd06c94..2a17aab5 100644 --- a/src/get_hkl.c +++ b/src/get_hkl.c @@ -580,6 +580,10 @@ int main(int argc, char *argv[]) if ( reindex_str != NULL ) { reindex = parse_symmetry_operations(reindex_str); if ( reindex == NULL ) return 1; + if ( num_equivs(reindex, NULL) != 1 ) { + ERROR("Please provide only ONE reindexing operation\n"); + return 1; + } set_symmetry_name(reindex, "Reindex"); } -- cgit v1.2.3 From 4337cafe052c4ad238c969dfa4cb7c7ac52f5e07 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 25 Oct 2018 16:48:36 +0200 Subject: Use IntegerMatrix for all unit cell transformations Get rid of UnitCellTransformation, a thin wrapper which didn't do anything. --- src/cell_tool.c | 18 ++++++------------ src/whirligig.c | 5 +---- 2 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index e8e60f30..12a00192 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -105,7 +105,6 @@ static int comparecells(UnitCell *cell, const char *comparecell, for ( i[7]=-maxorder; i[7]<=+maxorder; i[7]++ ) { for ( i[8]=-maxorder; i[8]<=+maxorder; i[8]++ ) { - UnitCellTransformation *tfn; UnitCell *nc; IntegerMatrix *m; int j, k; @@ -120,8 +119,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, if ( intmat_det(m) < 1 ) continue; - tfn = tfn_from_intmat(m); - nc = cell_transform(cell, tfn); + nc = cell_transform(cell, m); if ( compare_cell_parameters(cell2, nc, ltl, atl) ) { STATUS("-----------------------------------------------" @@ -131,7 +129,6 @@ static int comparecells(UnitCell *cell, const char *comparecell, } intmat_free(m); - tfn_free(tfn); cell_free(nc); } @@ -283,7 +280,6 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) for ( i[7]=-maxorder; i[7]<=+maxorder; i[7]++ ) { for ( i[8]=-maxorder; i[8]<=+maxorder; i[8]++ ) { - UnitCellTransformation *tfn; UnitCell *nc; IntegerMatrix *m; int j, k; @@ -298,8 +294,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) if ( intmat_det(m) != +1 ) continue; - tfn = tfn_from_intmat(m); - nc = cell_transform(cell, tfn); + nc = cell_transform(cell, m); if ( compare_cell_parameters(cell, nc, ltl, atl) ) { if ( !intmat_is_identity(m) ) add_symop(ops, m); @@ -311,7 +306,6 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) intmat_free(m); } - tfn_free(tfn); cell_free(nc); } @@ -345,15 +339,15 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) static int uncenter(UnitCell *cell, const char *out_file) { UnitCell *cnew; - UnitCellTransformation *trans; + IntegerMatrix *m; - cnew = uncenter_cell(cell, &trans); + cnew = uncenter_cell(cell, &m); STATUS("------------------> The primitive unit cell:\n"); cell_print(cnew); - STATUS("------------------> The decentering transformation:\n"); - tfn_print(trans); + STATUS("------------------> The centering transformation:\n"); + intmat_print(m); if ( out_file != NULL ) { FILE *fh = fopen(out_file, "w"); diff --git a/src/whirligig.c b/src/whirligig.c index 54ade40a..7d50141a 100644 --- a/src/whirligig.c +++ b/src/whirligig.c @@ -364,15 +364,12 @@ static int try_join(struct window *win, int sn) int j; Crystal *cr; UnitCell *ref; - UnitCellTransformation *tfn; const int sp = win->join_ptr - 1; /* Get the appropriately transformed cell from the last crystal in this * series */ - tfn = tfn_from_intmat(win->mat[sn][sp]); cr = win->img[sp].crystals[win->ser[sn][sp]]; - ref = cell_transform(crystal_get_cell(cr), tfn); - tfn_free(tfn); + ref = cell_transform(crystal_get_cell(cr), win->mat[sn][sp]); for ( j=0; jimg[win->join_ptr].n_crystals; j++ ) { Crystal *cr2; -- cgit v1.2.3 From 169e7c5677ffc9c296c0a7eeddb0b77e024a4a55 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 18 Feb 2019 16:04:28 +0100 Subject: Be clear about whether functions need rational or integer transformations --- src/cell_tool.c | 4 ++-- src/whirligig.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 12a00192..20e156a1 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -119,7 +119,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, if ( intmat_det(m) < 1 ) continue; - nc = cell_transform(cell, m); + nc = cell_transform_intmat(cell, m); if ( compare_cell_parameters(cell2, nc, ltl, atl) ) { STATUS("-----------------------------------------------" @@ -294,7 +294,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) if ( intmat_det(m) != +1 ) continue; - nc = cell_transform(cell, m); + nc = cell_transform_intmat(cell, m); if ( compare_cell_parameters(cell, nc, ltl, atl) ) { if ( !intmat_is_identity(m) ) add_symop(ops, m); diff --git a/src/whirligig.c b/src/whirligig.c index 7d50141a..209e7fbe 100644 --- a/src/whirligig.c +++ b/src/whirligig.c @@ -369,7 +369,7 @@ static int try_join(struct window *win, int sn) /* Get the appropriately transformed cell from the last crystal in this * series */ cr = win->img[sp].crystals[win->ser[sn][sp]]; - ref = cell_transform(crystal_get_cell(cr), win->mat[sn][sp]); + ref = cell_transform_intmat(crystal_get_cell(cr), win->mat[sn][sp]); for ( j=0; jimg[win->join_ptr].n_crystals; j++ ) { Crystal *cr2; -- cgit v1.2.3 From 68e620fe6dd73ef41327f7ebba1c40f9a9ae8b1b Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 22 Feb 2019 15:25:09 +0100 Subject: cell_tool --find-ambi: Work without -y It's not super-helpful, but the manual say it works, so... --- src/cell_tool.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 20e156a1..4a2e17f9 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -263,8 +263,7 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) set_symmetry_name(ops, "Observed"); if ( sym == NULL ) { - ERROR("Please specify the point group of the structure.\n"); - return 1; + sym = get_pointgroup("1"); } STATUS("Looking for ambiguities up to %ix each lattice length.\n", maxorder); -- cgit v1.2.3 From b8c79e07d8d84990122d56a053d822232590a9d5 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 26 Feb 2019 13:18:40 +0100 Subject: Consider fractional cell lengths during comparison This is WAY too slow. Need another algorithm. --- src/cell_tool.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 4a2e17f9..b48b538e 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -73,8 +73,10 @@ static int comparecells(UnitCell *cell, const char *comparecell, double ltl, double atl) { signed int i[9]; + int b[9]; const int maxorder = 2; UnitCell *cell2; + RationalMatrix *m; STATUS("Comparing with: %s\n", comparecell); @@ -95,6 +97,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, STATUS("Reciprocal angle tolerance %f degrees\n", rad2deg(atl)); STATUS("This will take about 30 seconds. Please wait...\n"); + m = rtnl_mtx_new(3, 3); for ( i[0]=-maxorder; i[0]<=+maxorder; i[0]++ ) { for ( i[1]=-maxorder; i[1]<=+maxorder; i[1]++ ) { for ( i[2]=-maxorder; i[2]<=+maxorder; i[2]++ ) { @@ -104,31 +107,40 @@ static int comparecells(UnitCell *cell, const char *comparecell, for ( i[6]=-maxorder; i[6]<=+maxorder; i[6]++ ) { for ( i[7]=-maxorder; i[7]<=+maxorder; i[7]++ ) { for ( i[8]=-maxorder; i[8]<=+maxorder; i[8]++ ) { + for ( b[0]=0; b[0]<=1; b[0]++ ) { + for ( b[1]=0; b[1]<=1; b[1]++ ) { + for ( b[2]=0; b[2]<=1; b[2]++ ) { + for ( b[3]=0; b[3]<=1; b[3]++ ) { + for ( b[4]=0; b[4]<=1; b[4]++ ) { + for ( b[5]=0; b[5]<=1; b[5]++ ) { + for ( b[6]=0; b[6]<=1; b[6]++ ) { + for ( b[7]=0; b[7]<=1; b[7]++ ) { + for ( b[8]=0; b[8]<=1; b[8]++ ) { UnitCell *nc; - IntegerMatrix *m; int j, k; int l = 0; - m = intmat_new(3, 3); for ( j=0; j<3; j++ ) { for ( k=0; k<3; k++ ) { - intmat_set(m, j, k, i[l++]); + if ( b[l] || i[l]==1 || i[l]==-1 ) { + rtnl_mtx_set(m, j, k, rtnl(i[l], 1)); + } else { + rtnl_mtx_set(m, j, k, rtnl(1, i[l])); + } + l++; } } - if ( intmat_det(m) < 1 ) continue; - - nc = cell_transform_intmat(cell, m); + nc = cell_transform_rational(cell, m); if ( compare_cell_parameters(cell2, nc, ltl, atl) ) { STATUS("-----------------------------------------------" "-------------------------------------------\n"); cell_print(nc); - intmat_print(m); + rtnl_mtx_print(m); } - intmat_free(m); cell_free(nc); } @@ -140,6 +152,16 @@ static int comparecells(UnitCell *cell, const char *comparecell, } } } + } + } + } + } + } + } + } + } + } + rtnl_mtx_free(m); return 0; } -- cgit v1.2.3 From 2dad9da2661389cf5c34a49e933dab20bd6d943c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 28 Feb 2019 10:53:11 +0100 Subject: Fix tolerances (again) --- src/cell_tool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index b48b538e..03c58f5e 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -400,8 +400,8 @@ int main(int argc, char *argv[]) char *cell_file = NULL; UnitCell *cell; char *toler = NULL; - float ltl = 5.0; /* in percent */ - float atl = deg2rad(1.5); + float ltl = 0.05; /* fraction */ + float atl = deg2rad(1.5); /* radians */ char *sym_str = NULL; SymOpList *sym = NULL; int mode = CT_NOTHING; @@ -518,7 +518,7 @@ int main(int argc, char *argv[]) ERROR("Invalid parameters for --tolerance\n"); return 1; } - /* ltl stays in percent */ + ltl /= 100.0; /* percent to fraction */ atl = deg2rad(atl); free(toler); } -- cgit v1.2.3 From 3e850c6c2ed2a3dbc0fe0be27d36c0d1e6b57614 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 28 Feb 2019 10:53:43 +0100 Subject: New way of doing cell comparisons, similar to match_cell() --- src/cell_tool.c | 80 +++++---------------------------------------------------- 1 file changed, 7 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 03c58f5e..d6c5b6cd 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -72,14 +72,9 @@ static void show_help(const char *s) static int comparecells(UnitCell *cell, const char *comparecell, double ltl, double atl) { - signed int i[9]; - int b[9]; - const int maxorder = 2; UnitCell *cell2; RationalMatrix *m; - STATUS("Comparing with: %s\n", comparecell); - cell2 = load_cell_from_file(comparecell); if ( cell2 == NULL ) { ERROR("Failed to load unit cell from '%s'\n", comparecell); @@ -92,75 +87,14 @@ static int comparecells(UnitCell *cell, const char *comparecell, STATUS("------------------> The reference unit cell:\n"); cell_print(cell2); - STATUS("Comparing cells up to %ix each lattice length.\n", maxorder); - STATUS("Reciprocal axis length tolerance %f %%\n", ltl); - STATUS("Reciprocal angle tolerance %f degrees\n", rad2deg(atl)); - STATUS("This will take about 30 seconds. Please wait...\n"); - - m = rtnl_mtx_new(3, 3); - for ( i[0]=-maxorder; i[0]<=+maxorder; i[0]++ ) { - for ( i[1]=-maxorder; i[1]<=+maxorder; i[1]++ ) { - for ( i[2]=-maxorder; i[2]<=+maxorder; i[2]++ ) { - for ( i[3]=-maxorder; i[3]<=+maxorder; i[3]++ ) { - for ( i[4]=-maxorder; i[4]<=+maxorder; i[4]++ ) { - for ( i[5]=-maxorder; i[5]<=+maxorder; i[5]++ ) { - for ( i[6]=-maxorder; i[6]<=+maxorder; i[6]++ ) { - for ( i[7]=-maxorder; i[7]<=+maxorder; i[7]++ ) { - for ( i[8]=-maxorder; i[8]<=+maxorder; i[8]++ ) { - for ( b[0]=0; b[0]<=1; b[0]++ ) { - for ( b[1]=0; b[1]<=1; b[1]++ ) { - for ( b[2]=0; b[2]<=1; b[2]++ ) { - for ( b[3]=0; b[3]<=1; b[3]++ ) { - for ( b[4]=0; b[4]<=1; b[4]++ ) { - for ( b[5]=0; b[5]<=1; b[5]++ ) { - for ( b[6]=0; b[6]<=1; b[6]++ ) { - for ( b[7]=0; b[7]<=1; b[7]++ ) { - for ( b[8]=0; b[8]<=1; b[8]++ ) { - - UnitCell *nc; - int j, k; - int l = 0; - - for ( j=0; j<3; j++ ) { - for ( k=0; k<3; k++ ) { - if ( b[l] || i[l]==1 || i[l]==-1 ) { - rtnl_mtx_set(m, j, k, rtnl(i[l], 1)); - } else { - rtnl_mtx_set(m, j, k, rtnl(1, i[l])); - } - l++; - } - } - - nc = cell_transform_rational(cell, m); - - if ( compare_cell_parameters(cell2, nc, ltl, atl) ) { - STATUS("-----------------------------------------------" - "-------------------------------------------\n"); - cell_print(nc); - rtnl_mtx_print(m); - } - - cell_free(nc); - - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } + STATUS("------------------> The comparison results:\n"); + if ( !compare_reindexed_cell_parameters(cell, cell2, ltl, atl, &m) ) { + STATUS("No relationship found between lattices.\n"); + return 0; + } else { + STATUS("Relationship found:\n"); } + rtnl_mtx_free(m); return 0; -- cgit v1.2.3 From 4f11a9f8530178cfb510f11c7bc4b1829bbd0be4 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 6 Mar 2019 11:40:37 +0100 Subject: Keep track of the "un-centering" matrix, as well as the "centering" This makes it easy to reverse the transformation, if required, which it is when comparing centered cells. --- src/cell_tool.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index d6c5b6cd..6d0c5f1e 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -92,7 +92,14 @@ static int comparecells(UnitCell *cell, const char *comparecell, STATUS("No relationship found between lattices.\n"); return 0; } else { + UnitCell *trans; STATUS("Relationship found:\n"); + rtnl_mtx_print(m); + STATUS("Transformed version of input unit cell:\n"); + trans = cell_transform_rational(cell, m); + cell_print(trans); + cell_free(trans); + } rtnl_mtx_free(m); @@ -294,15 +301,19 @@ static int find_ambi(UnitCell *cell, SymOpList *sym, double ltl, double atl) static int uncenter(UnitCell *cell, const char *out_file) { UnitCell *cnew; - IntegerMatrix *m; + IntegerMatrix *C; + RationalMatrix *Ci; - cnew = uncenter_cell(cell, &m); + cnew = uncenter_cell(cell, &C, &Ci); STATUS("------------------> The primitive unit cell:\n"); cell_print(cnew); STATUS("------------------> The centering transformation:\n"); - intmat_print(m); + intmat_print(C); + + STATUS("------------------> The un-centering transformation:\n"); + rtnl_mtx_print(Ci); if ( out_file != NULL ) { FILE *fh = fopen(out_file, "w"); -- cgit v1.2.3 From 3a098d01569348a9680fca45ba4786f3a15761a3 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 21 Feb 2019 16:15:06 +0100 Subject: cell_tool: Add --transform --- src/cell_tool.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 6d0c5f1e..9b7d6a6b 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -329,6 +329,30 @@ static int uncenter(UnitCell *cell, const char *out_file) } +static int transform(UnitCell *cell, const char *trans_str) +{ + RationalMatrix *trans; + UnitCell *nc; + + trans = parse_cell_transformation(trans_str); + if ( trans == NULL ) { + ERROR("Invalid cell transformation '%s'\n", trans_str); + return 1; + } + + nc = cell_transform_rational(cell, trans); + + STATUS("------------------> The transformation matrix:\n"); + rtnl_mtx_print(trans); + STATUS("Determinant = %s\n", rtnl_format(rtnl_mtx_det(trans))); + + STATUS("------------------> The transformed unit cell:\n"); + cell_print(nc); + + return 0; +} + + enum { CT_NOTHING, CT_FINDAMBI, @@ -336,6 +360,7 @@ enum { CT_RINGS, CT_COMPARE, CT_CHOICES, + CT_TRANSFORM, }; @@ -354,6 +379,7 @@ int main(int argc, char *argv[]) char *out_file = NULL; float highres; double rmax = 1/(2.0e-10); + char *trans_str = NULL; /* Long options */ const struct option longopts[] = { @@ -368,6 +394,8 @@ int main(int argc, char *argv[]) {"uncentre", 0, &mode, CT_UNCENTER}, {"rings", 0, &mode, CT_RINGS}, {"compare-cell", 1, NULL, 3}, + {"cell-choices", 0, &mode, CT_CHOICES}, + {"transform", 1, NULL, 4}, {"highres", 1, NULL, 5}, {0, 0, NULL, 0} @@ -404,6 +432,11 @@ int main(int argc, char *argv[]) mode = CT_COMPARE; break; + case 4 : + trans_str = strdup(optarg); + mode = CT_TRANSFORM; + break; + case 5 : if ( sscanf(optarg, "%e", &highres) != 1 ) { ERROR("Invalid value for --highres\n"); @@ -491,6 +524,7 @@ int main(int argc, char *argv[]) if ( mode == CT_UNCENTER ) return uncenter(cell, out_file); if ( mode == CT_RINGS ) return all_rings(cell, sym, rmax); if ( mode == CT_COMPARE ) return comparecells(cell, comparecell, ltl, atl); + if ( mode == CT_TRANSFORM ) return transform(cell, trans_str); /* FIXME: Everything else */ ERROR("Sorry, this mode of operation is not yet implemented.\n"); -- cgit v1.2.3 From afa301a4737178db4aa0b413c6c0a41f6ee5e4ec Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 22 Feb 2019 14:50:37 +0100 Subject: cell_tool: Implement --cell-choices --- src/cell_tool.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 9b7d6a6b..9f41afb7 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -60,6 +60,7 @@ static void show_help(const char *s) " --uncenter Calculate a primitive cell.\n" " --rings Calculate powder ring positions.\n" " --compare-cell Compare unit cell with cell from .\n" +" --cell-choices Calculate all three cell choices for monoclinic C cell.\n" "\n" " -y Real point group of the structure.\n" " --tolerance= Set the tolerances for cell comparison.\n" @@ -353,6 +354,25 @@ static int transform(UnitCell *cell, const char *trans_str) } +static int cell_choices(UnitCell *cell) +{ + if ( cell_get_lattice_type(cell) != L_MONOCLINIC ) { + ERROR("Cell must be monoclinic to use --cell-choices\n"); + return 1; + } + + if ( cell_get_unique_axis(cell) == 'b' ) { + transform(cell, "-a-c,b,a"); + transform(cell, "c,b,-a-c"); + } else { + ERROR("Sorry, --cell-choices only supports unique axis b.\n"); + return 1; + } + + return 0; +} + + enum { CT_NOTHING, CT_FINDAMBI, @@ -525,8 +545,7 @@ int main(int argc, char *argv[]) if ( mode == CT_RINGS ) return all_rings(cell, sym, rmax); if ( mode == CT_COMPARE ) return comparecells(cell, comparecell, ltl, atl); if ( mode == CT_TRANSFORM ) return transform(cell, trans_str); + if ( mode == CT_CHOICES ) return cell_choices(cell); - /* FIXME: Everything else */ - ERROR("Sorry, this mode of operation is not yet implemented.\n"); return 1; } -- cgit v1.2.3 From 2b7e52df98bdd1b651e25995a9450c44f0b975ee Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 6 Mar 2019 17:23:00 +0100 Subject: cell_tool: Add documentation for --transform --- src/cell_tool.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 9f41afb7..59500cbb 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -61,6 +61,7 @@ static void show_help(const char *s) " --rings Calculate powder ring positions.\n" " --compare-cell Compare unit cell with cell from .\n" " --cell-choices Calculate all three cell choices for monoclinic C cell.\n" +" --transform= Transform unit cell.\n" "\n" " -y Real point group of the structure.\n" " --tolerance= Set the tolerances for cell comparison.\n" -- cgit v1.2.3 From 5b5edcc2fb28c2ec166a44a5a821f138ef3ac4ef Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sat, 9 Mar 2019 11:39:14 +0100 Subject: cell_tool: Improve messages --- src/cell_tool.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 59500cbb..14faac3b 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -95,12 +95,16 @@ static int comparecells(UnitCell *cell, const char *comparecell, return 0; } else { UnitCell *trans; - STATUS("Relationship found:\n"); + STATUS("Relationship found. To become similar to the reference" + " cell, the input cell should be transformed by:\n"); rtnl_mtx_print(m); STATUS("Transformed version of input unit cell:\n"); trans = cell_transform_rational(cell, m); cell_print(trans); cell_free(trans); + STATUS("NB transformed cell might not really be triclinic, " + "it's just that I don't (yet) know how to work out what " + "it is.\n"); } @@ -350,6 +354,9 @@ static int transform(UnitCell *cell, const char *trans_str) STATUS("------------------> The transformed unit cell:\n"); cell_print(nc); + STATUS("NB transformed cell might not really be triclinic, " + "it's just that I don't (yet) know how to work out what " + "it is.\n"); return 0; } -- cgit v1.2.3 From 4fdfdfa0eef645e290a8ab98c9ff6507c2bc1f5f Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 12 Mar 2019 14:31:49 +0100 Subject: Rename intmat_intvec_mult to transform_indices --- src/whirligig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/whirligig.c b/src/whirligig.c index 209e7fbe..cc2b531e 100644 --- a/src/whirligig.c +++ b/src/whirligig.c @@ -84,7 +84,7 @@ static void do_op(const IntegerMatrix *op, v[0] = h; v[1] = k; v[2] = l; - ans = intmat_intvec_mult(op, v); + ans = transform_indices(op, v); assert(ans != NULL); *he = ans[0]; *ke = ans[1]; *le = ans[2]; -- cgit v1.2.3 From 4d6b5ac83e0bd4929661dfb2c5580da7a2aa4a63 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 13 Mar 2019 15:53:53 +0100 Subject: cell_tool: Accept unconventional cell --- src/cell_tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 14faac3b..5e11eddb 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -82,7 +82,7 @@ static int comparecells(UnitCell *cell, const char *comparecell, ERROR("Failed to load unit cell from '%s'\n", comparecell); return 1; } - if ( validate_cell(cell2) ) { + if ( validate_cell(cell2) > 1 ) { ERROR("Comparison cell is invalid.\n"); return 1; } @@ -532,7 +532,7 @@ int main(int argc, char *argv[]) STATUS("------------------> The input unit cell:\n"); cell_print(cell); - if ( validate_cell(cell) ) { + if ( validate_cell(cell) > 1 ) { ERROR("Cell is invalid.\n"); return 1; } -- cgit v1.2.3 From 611eb719079c150a5e8db8196c21a2a08b0c6d6a Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 13 Mar 2019 15:54:06 +0100 Subject: cell_tool --transform: Write output cell --- src/cell_tool.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 5e11eddb..95d5d3bc 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -335,7 +335,8 @@ static int uncenter(UnitCell *cell, const char *out_file) } -static int transform(UnitCell *cell, const char *trans_str) +static int transform(UnitCell *cell, const char *trans_str, + const char *out_file) { RationalMatrix *trans; UnitCell *nc; @@ -358,6 +359,16 @@ static int transform(UnitCell *cell, const char *trans_str) "it's just that I don't (yet) know how to work out what " "it is.\n"); + if ( out_file != NULL ) { + FILE *fh = fopen(out_file, "w"); + if ( fh == NULL ) { + ERROR("Failed to open '%s'\n", out_file); + return 1; + } + write_cell(nc, fh); + fclose(fh); + } + return 0; } @@ -370,8 +381,8 @@ static int cell_choices(UnitCell *cell) } if ( cell_get_unique_axis(cell) == 'b' ) { - transform(cell, "-a-c,b,a"); - transform(cell, "c,b,-a-c"); + transform(cell, "-a-c,b,a", NULL); + transform(cell, "c,b,-a-c", NULL); } else { ERROR("Sorry, --cell-choices only supports unique axis b.\n"); return 1; @@ -552,7 +563,7 @@ int main(int argc, char *argv[]) if ( mode == CT_UNCENTER ) return uncenter(cell, out_file); if ( mode == CT_RINGS ) return all_rings(cell, sym, rmax); if ( mode == CT_COMPARE ) return comparecells(cell, comparecell, ltl, atl); - if ( mode == CT_TRANSFORM ) return transform(cell, trans_str); + if ( mode == CT_TRANSFORM ) return transform(cell, trans_str, out_file); if ( mode == CT_CHOICES ) return cell_choices(cell); return 1; -- cgit v1.2.3 From 811e6b353ee6e560fe6bd26e22dad49e7386cd54 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 13 Mar 2019 15:56:17 +0100 Subject: cell_tool: Reject singular transformation matrix --- src/cell_tool.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cell_tool.c b/src/cell_tool.c index 95d5d3bc..652df885 100644 --- a/src/cell_tool.c +++ b/src/cell_tool.c @@ -339,6 +339,7 @@ static int transform(UnitCell *cell, const char *trans_str, const char *out_file) { RationalMatrix *trans; + Rational det; UnitCell *nc; trans = parse_cell_transformation(trans_str); @@ -351,7 +352,12 @@ static int transform(UnitCell *cell, const char *trans_str, STATUS("------------------> The transformation matrix:\n"); rtnl_mtx_print(trans); - STATUS("Determinant = %s\n", rtnl_format(rtnl_mtx_det(trans))); + det = rtnl_mtx_det(trans); + STATUS("Determinant = %s\n", rtnl_format(det)); + if ( rtnl_cmp(det, rtnl_zero()) == 0 ) { + ERROR("Singular transformation matrix - cannot transform.\n"); + return 1; + } STATUS("------------------> The transformed unit cell:\n"); cell_print(nc); -- cgit v1.2.3