aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2013-08-08 15:46:11 +0200
committerThomas White <taw@physics.org>2013-09-13 14:29:49 +0200
commit896ced2c5826b71cf270d75310b8ac0fd495063b (patch)
tree9646fcc0ad7611cdec07d2e5f81c4c9e715fb73f
parent333565a2b95c6e3aa24ef7c073ab779f3d7b992f (diff)
Fix incorrect handling of monoclinic C cells
-rw-r--r--libcrystfel/src/cell-utils.c111
-rw-r--r--libcrystfel/src/cell.c2
-rw-r--r--tests/centering_check.c48
3 files changed, 109 insertions, 52 deletions
diff --git a/libcrystfel/src/cell-utils.c b/libcrystfel/src/cell-utils.c
index 12443c8d..f3eb7c16 100644
--- a/libcrystfel/src/cell-utils.c
+++ b/libcrystfel/src/cell-utils.c
@@ -252,16 +252,19 @@ int bravais_lattice(UnitCell *cell)
case 'B' :
case 'C' :
if ( lattice == L_MONOCLINIC ) {
- if ( (ua=='a') && (centering=='A') ) return 1;
- if ( (ua=='b') && (centering=='B') ) return 1;
- if ( (ua=='c') && (centering=='C') ) return 1;
+ if ( (ua=='a') && (centering!='A') ) return 1;
+ if ( (ua=='b') && (centering!='B') ) return 1;
+ if ( (ua=='c') && (centering!='C') ) return 1;
} else if ( lattice == L_ORTHORHOMBIC) {
return 1;
}
return 0;
case 'I' :
- if ( (lattice == L_ORTHORHOMBIC)
+ /* We accept monoclinic I as "Bravais", even though it's
+ * unconventional */
+ if ( (lattice == L_MONOCLINIC)
+ || (lattice == L_ORTHORHOMBIC)
|| (lattice == L_TETRAGONAL)
|| (lattice == L_CUBIC) )
{
@@ -313,15 +316,31 @@ static UnitCellTransformation *uncentering_transformation(UnitCell *in,
if ( t == NULL ) return NULL;
if ( ua == 'a' ) {
- tfn_combine(t, tfn_vector(0,0,1),
- tfn_vector(0,1,0),
- tfn_vector(-1,0,0));
+ tfn_combine(t, tfn_vector(0,1,0),
+ tfn_vector(0,0,1),
+ tfn_vector(1,0,0));
+ if ( lt == L_MONOCLINIC ) {
+ assert(cen != 'A');
+ switch ( cen ) {
+ case 'B' : cen = 'A'; break;
+ case 'C' : cen = 'B'; break;
+ case 'I' : cen = 'I'; break;
+ }
+ }
}
if ( ua == 'b' ) {
- tfn_combine(t, tfn_vector(1,0,0),
- tfn_vector(0,0,1),
- tfn_vector(0,-1,0));
+ tfn_combine(t, tfn_vector(0,0,1),
+ tfn_vector(1,0,0),
+ tfn_vector(0,1,0));
+ if ( lt == L_MONOCLINIC ) {
+ assert(cen != 'B');
+ switch ( cen ) {
+ case 'C' : cen = 'A'; break;
+ case 'A' : cen = 'B'; break;
+ case 'I' : cen = 'I'; break;
+ }
+ }
}
switch ( cen ) {
@@ -365,12 +384,38 @@ static UnitCellTransformation *uncentering_transformation(UnitCell *in,
break;
case 'A' :
+ tfn_combine(t, tfn_vector( 1, 0, 0),
+ tfn_vector( 0, H, H),
+ tfn_vector( 0,-H, H));
+ if ( lt == L_ORTHORHOMBIC ) {
+ *new_latt = L_MONOCLINIC;
+ } else {
+ *new_latt = L_TRICLINIC;
+ }
+ *new_centering = 'P';
+ break;
+
case 'B' :
+ tfn_combine(t, tfn_vector( H, 0, H),
+ tfn_vector( 0, 1, 0),
+ tfn_vector(-H, 0, H));
+ if ( lt == L_ORTHORHOMBIC ) {
+ *new_latt = L_MONOCLINIC;
+ } else {
+ *new_latt = L_TRICLINIC;
+ }
+ *new_centering = 'P';
+ break;
+
case 'C' :
- tfn_combine(t, tfn_vector(H,H,0),
- tfn_vector(-H,H,0),
- tfn_vector(0,0,1));
- *new_latt = L_MONOCLINIC;
+ tfn_combine(t, tfn_vector( H, H, 0),
+ tfn_vector(-H, H, 0),
+ tfn_vector( 0, 0, 1));
+ if ( lt == L_ORTHORHOMBIC ) {
+ *new_latt = L_MONOCLINIC;
+ } else {
+ *new_latt = L_TRICLINIC;
+ }
*new_centering = 'P';
break;
@@ -394,15 +439,15 @@ static UnitCellTransformation *uncentering_transformation(UnitCell *in,
* transformation */
if ( !((cen=='H') && (*new_latt == L_RHOMBOHEDRAL)) ) {
if ( ua == 'a' ) {
- tfn_combine(t, tfn_vector(0,0,-1),
- tfn_vector(0,1,0),
- tfn_vector(1,0,0));
+ tfn_combine(t, tfn_vector(0,0,1),
+ tfn_vector(1,0,0),
+ tfn_vector(0,1,0));
}
if ( ua == 'b' ) {
- tfn_combine(t, tfn_vector(1,0,0),
- tfn_vector(0,0,-1),
- tfn_vector(0,1,0));
+ tfn_combine(t, tfn_vector(0,1,0),
+ tfn_vector(0,0,1),
+ tfn_vector(1,0,0));
}
}
@@ -933,6 +978,7 @@ static void determine_lattice(UnitCell *cell,
/* Orthorhombic. Unique axis irrelevant, but point group
* can have different orientations. */
cell_set_lattice_type(cell, L_ORTHORHOMBIC);
+ cell_set_unique_axis(cell, '*');
return;
}
@@ -1201,19 +1247,18 @@ int validate_cell(UnitCell *cell)
err = 1;
}
- cen = cell_get_centering(cell);
- ua = cell_get_unique_axis(cell);
- if ( (cen == 'A') && (ua != 'a') ) {
- ERROR("WARNING: centering doesn't match unique axis.\n");
- err = 1;
- }
- if ( (cen == 'B') && (ua != 'b') ) {
- ERROR("WARNING: centering doesn't match unique axis.\n");
- err = 1;
- }
- if ( (cen == 'C') && (ua != 'c') ) {
- ERROR("WARNING: centering doesn't match unique axis.\n");
- err = 1;
+ /* For monoclinic A, B or C centering, the unique axis must be something
+ * other than the centering. */
+ if ( cell_get_lattice_type(cell) == L_MONOCLINIC ) {
+ cen = cell_get_centering(cell);
+ ua = cell_get_unique_axis(cell);
+ if ( ((cen == 'A') && (ua == 'a'))
+ || ((cen == 'B') && (ua == 'b'))
+ || ((cen == 'C') && (ua == 'c')) ) {
+ ERROR("WARNING: A, B or C centering matches unique"
+ " axis.\n");
+ err = 1;
+ }
}
return err;
diff --git a/libcrystfel/src/cell.c b/libcrystfel/src/cell.c
index 8c14cce4..44c767f0 100644
--- a/libcrystfel/src/cell.c
+++ b/libcrystfel/src/cell.c
@@ -125,7 +125,7 @@ UnitCell *cell_new()
cell->pointgroup = strdup("1");
cell->lattice_type = L_TRICLINIC;
cell->centering = 'P';
- cell->unique_axis = 'c';
+ cell->unique_axis = '?';
return cell;
}
diff --git a/tests/centering_check.c b/tests/centering_check.c
index e17915d3..f4073072 100644
--- a/tests/centering_check.c
+++ b/tests/centering_check.c
@@ -212,17 +212,29 @@ int main(int argc, char *argv[])
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 100.0,
L_MONOCLINIC, 'P', 'c');
- /* Monoclinic A */
+ /* Monoclinic "C"-centered, unique axis a, three cell choices */
fail += check_centering(10e-10, 20e-10, 30e-10, 100.0, 90.0, 90.0,
- L_MONOCLINIC, 'A', 'a');
+ L_MONOCLINIC, 'B', 'a');
+ fail += check_centering(10e-10, 20e-10, 30e-10, 100.0, 90.0, 90.0,
+ L_MONOCLINIC, 'C', 'a');
+ fail += check_centering(10e-10, 20e-10, 30e-10, 100.0, 90.0, 90.0,
+ L_MONOCLINIC, 'I', 'a');
- /* Monoclinic B */
+ /* Monoclinic "C"-centered, unique axis b, three cell choices */
+ fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 100.0, 90.0,
+ L_MONOCLINIC, 'C', 'b');
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 100.0, 90.0,
- L_MONOCLINIC, 'B', 'b');
+ L_MONOCLINIC, 'A', 'b');
+ fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 100.0, 90.0,
+ L_MONOCLINIC, 'I', 'b');
- /* Monoclinic C */
+ /* Monoclinic "C"-centered, unique axis c, three cell choices */
+ fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 100.0,
+ L_MONOCLINIC, 'A', 'c');
+ fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 100.0,
+ L_MONOCLINIC, 'B', 'c');
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 100.0,
- L_MONOCLINIC, 'C', 'c');
+ L_MONOCLINIC, 'I', 'c');
/* Orthorhombic P */
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
@@ -230,15 +242,15 @@ int main(int argc, char *argv[])
/* Orthorhombic A */
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
- L_ORTHORHOMBIC, 'A', 'a');
+ L_ORTHORHOMBIC, 'A', '*');
/* Orthorhombic B */
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
- L_ORTHORHOMBIC, 'B', 'b');
+ L_ORTHORHOMBIC, 'B', '*');
/* Orthorhombic C */
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
- L_ORTHORHOMBIC, 'C', 'c');
+ L_ORTHORHOMBIC, 'C', '*');
/* Orthorhombic I */
fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
@@ -249,19 +261,19 @@ int main(int argc, char *argv[])
L_ORTHORHOMBIC, 'F', '*');
/* Tetragonal P */
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
+ fail += check_centering(10e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0,
L_TETRAGONAL, 'P', 'a');
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
+ fail += check_centering(30e-10, 10e-10, 30e-10, 90.0, 90.0, 90.0,
L_TETRAGONAL, 'P', 'b');
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
+ fail += check_centering(30e-10, 30e-10, 10e-10, 90.0, 90.0, 90.0,
L_TETRAGONAL, 'P', 'c');
/* Tetragonal I */
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
+ fail += check_centering(10e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0,
L_TETRAGONAL, 'I', 'a');
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
+ fail += check_centering(30e-10, 10e-10, 30e-10, 90.0, 90.0, 90.0,
L_TETRAGONAL, 'I', 'b');
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0,
+ fail += check_centering(30e-10, 30e-10, 10e-10, 90.0, 90.0, 90.0,
L_TETRAGONAL, 'I', 'c');
/* Rhombohedral R */
@@ -269,11 +281,11 @@ int main(int argc, char *argv[])
L_RHOMBOHEDRAL, 'R', '*');
/* Hexagonal P */
- fail += check_centering(10e-10, 20e-10, 30e-10, 120.0, 90.0, 90.0,
+ fail += check_centering(30e-10, 10e-10, 10e-10, 120.0, 90.0, 90.0,
L_HEXAGONAL, 'P', 'a');
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 120.0, 90.0,
+ fail += check_centering(10e-10, 30e-10, 10e-10, 90.0, 120.0, 90.0,
L_HEXAGONAL, 'P', 'b');
- fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 120.0,
+ fail += check_centering(10e-10, 10e-10, 30e-10, 90.0, 90.0, 120.0,
L_HEXAGONAL, 'P', 'c');
/* Hexagonal H (PDB-speak for rhombohedral) */