Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
eed7ec3a
Unverified
Commit
eed7ec3a
authored
Apr 20, 2023
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop
parents
2b0b47d2
fdb057e0
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
234 additions
and
98 deletions
+234
-98
CMakeLists.txt
+4
-2
include/cif++/matrix.hpp
+1
-1
include/cif++/point.hpp
+1
-1
include/cif++/symmetry.hpp
+90
-71
src/symmetry.cpp
+61
-11
test/unit-3d-test.cpp
+77
-12
No files found.
CMakeLists.txt
View file @
eed7ec3a
...
@@ -168,6 +168,8 @@ if(MSVC)
...
@@ -168,6 +168,8 @@ if(MSVC)
endif
()
endif
()
find_package
(
ZLIB REQUIRED
)
find_package
(
ZLIB REQUIRED
)
find_package
(
Eigen3
)
include
(
FindFilesystem
)
include
(
FindFilesystem
)
list
(
APPEND CIFPP_REQUIRED_LIBRARIES
${
STDCPPFS_LIBRARY
}
)
list
(
APPEND CIFPP_REQUIRED_LIBRARIES
${
STDCPPFS_LIBRARY
}
)
...
@@ -277,7 +279,7 @@ target_include_directories(cifpp
...
@@ -277,7 +279,7 @@ target_include_directories(cifpp
"$<INSTALL_INTERFACE:
${
CMAKE_INSTALL_INCLUDEDIR
}
>"
"$<INSTALL_INTERFACE:
${
CMAKE_INSTALL_INCLUDEDIR
}
>"
)
)
target_link_libraries
(
cifpp PUBLIC Threads::Threads ZLIB::ZLIB
${
CIFPP_REQUIRED_LIBRARIES
}
)
target_link_libraries
(
cifpp PUBLIC Threads::Threads ZLIB::ZLIB
${
CIFPP_REQUIRED_LIBRARIES
}
Eigen3::Eigen
)
if
(
CMAKE_CXX_COMPILER_ID STREQUAL
"AppleClang"
)
if
(
CMAKE_CXX_COMPILER_ID STREQUAL
"AppleClang"
)
target_link_options
(
cifpp PRIVATE -undefined dynamic_lookup
)
target_link_options
(
cifpp PRIVATE -undefined dynamic_lookup
)
...
@@ -425,7 +427,7 @@ if(ENABLE_TESTING)
...
@@ -425,7 +427,7 @@ if(ENABLE_TESTING)
add_executable
(
${
CIFPP_TEST
}
${
CIFPP_TEST_SOURCE
}
)
add_executable
(
${
CIFPP_TEST
}
${
CIFPP_TEST_SOURCE
}
)
target_link_libraries
(
${
CIFPP_TEST
}
PRIVATE Threads::Threads cifpp::cifpp Boost::boost
)
target_link_libraries
(
${
CIFPP_TEST
}
PRIVATE Threads::Threads cifpp::cifpp Boost::boost
Eigen3::Eigen
)
if
(
MSVC
)
if
(
MSVC
)
# Specify unwind semantics so that MSVC knowns how to handle exceptions
# Specify unwind semantics so that MSVC knowns how to handle exceptions
...
...
include/cif++/matrix.hpp
View file @
eed7ec3a
...
@@ -518,7 +518,7 @@ auto eigen(const matrix_expression<M> &mat, bool sort)
...
@@ -518,7 +518,7 @@ auto eigen(const matrix_expression<M> &mat, bool sort)
value_type
h
=
ev
[
j
]
-
ev
[
i
];
value_type
h
=
ev
[
j
]
-
ev
[
i
];
value_type
t
;
value_type
t
;
if
(
a_ij
==
0
and
h
==
0
)
if
(
h
==
0
and
a_ij
==
0
)
t
=
1
;
t
=
1
;
else
if
(
std
::
fabs
(
a_ij
)
>
1.0e-12
*
std
::
fabs
(
h
))
else
if
(
std
::
fabs
(
a_ij
)
>
1.0e-12
*
std
::
fabs
(
h
))
{
{
...
...
include/cif++/point.hpp
View file @
eed7ec3a
...
@@ -320,7 +320,7 @@ class quaternion_type
...
@@ -320,7 +320,7 @@ class quaternion_type
constexpr
operator
bool
()
const
constexpr
operator
bool
()
const
{
{
return
operator
!=
({})
;
return
a
!=
0
or
b
!=
0
or
c
!=
0
or
d
!=
0
;
}
}
private
:
private
:
...
...
include/cif++/symmetry.hpp
View file @
eed7ec3a
...
@@ -182,34 +182,10 @@ class spacegroup;
...
@@ -182,34 +182,10 @@ class spacegroup;
class
rtop
;
class
rtop
;
class
sym_op
;
class
sym_op
;
// --------------------------------------------------------------------
// class cell
class
cell
{
public
:
cell
(
float
a
,
float
b
,
float
c
,
float
alpha
=
90.
f
,
float
beta
=
90.
f
,
float
gamma
=
90.
f
);
cell
(
const
datablock
&
db
);
float
get_a
()
const
{
return
m_a
;
}
float
get_b
()
const
{
return
m_b
;
}
float
get_c
()
const
{
return
m_c
;
}
float
get_alpha
()
const
{
return
m_alpha
;
}
float
get_beta
()
const
{
return
m_beta
;
}
float
get_gamma
()
const
{
return
m_gamma
;
}
matrix3x3
<
float
>
get_orthogonal_matrix
()
const
{
return
m_orthogonal
;
}
matrix3x3
<
float
>
get_fractional_matrix
()
const
{
return
m_fractional
;
}
private
:
void
init
();
float
m_a
,
m_b
,
m_c
,
m_alpha
,
m_beta
,
m_gamma
;
matrix3x3
<
float
>
m_orthogonal
,
m_fractional
;
};
/// @brief A class that encapsulates the symmetry operations as used in PDB files, i.e. a rotational number and a translation vector
/// @brief A class that encapsulates the symmetry operations as used in PDB files, i.e. a rotational number and a translation vector
/// The syntax in string format follows the syntax as used in mmCIF files, i.e. rotational number followed by underscore and the
/// three translations where 5 is no movement.
struct
sym_op
struct
sym_op
{
{
public
:
public
:
...
@@ -254,26 +230,28 @@ namespace literals
...
@@ -254,26 +230,28 @@ namespace literals
}
}
}
// namespace literals
}
// namespace literals
// --------------------------------------------------------------------
// The transformation class
class
transformation
class
transformation
{
{
public
:
public
:
transformation
(
const
symop_data
&
data
);
transformation
(
const
symop_data
&
data
);
transformation
(
const
matrix3x3
<
float
>
&
r
,
const
cif
::
point
&
t
)
transformation
(
const
matrix3x3
<
float
>
&
r
,
const
cif
::
point
&
t
);
:
m_rotation
(
r
)
,
m_translation
(
t
)
{
}
transformation
(
const
transformation
&
)
=
default
;
transformation
(
const
transformation
&
)
=
default
;
transformation
(
transformation
&&
)
=
default
;
transformation
(
transformation
&&
)
=
default
;
transformation
&
operator
=
(
const
transformation
&
)
=
default
;
transformation
&
operator
=
(
const
transformation
&
)
=
default
;
transformation
&
operator
=
(
transformation
&&
)
=
default
;
transformation
&
operator
=
(
transformation
&&
)
=
default
;
// point operator()(const cell &c, const point &pt) const;
point
operator
()(
point
pt
)
const
point
operator
()(
const
point
&
pt
)
const
{
{
return
m_rotation
*
pt
+
m_translation
;
if
(
m_q
)
pt
.
rotate
(
m_q
);
else
pt
=
m_rotation
*
pt
;
return
pt
+
m_translation
;
}
}
friend
transformation
operator
*
(
const
transformation
&
lhs
,
const
transformation
&
rhs
);
friend
transformation
operator
*
(
const
transformation
&
lhs
,
const
transformation
&
rhs
);
...
@@ -287,11 +265,46 @@ class transformation
...
@@ -287,11 +265,46 @@ class transformation
friend
class
spacegroup
;
friend
class
spacegroup
;
private
:
private
:
// Most rotation matrices provided by the International Tables
// are really rotation matrices, in those cases we can construct
// a quaternion. Unfortunately, that doesn't work for all of them
void
try_create_quaternion
();
matrix3x3
<
float
>
m_rotation
;
matrix3x3
<
float
>
m_rotation
;
quaternion
m_q
;
point
m_translation
;
point
m_translation
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// class cell
class
cell
{
public
:
cell
(
float
a
,
float
b
,
float
c
,
float
alpha
=
90.
f
,
float
beta
=
90.
f
,
float
gamma
=
90.
f
);
cell
(
const
datablock
&
db
);
float
get_a
()
const
{
return
m_a
;
}
float
get_b
()
const
{
return
m_b
;
}
float
get_c
()
const
{
return
m_c
;
}
float
get_alpha
()
const
{
return
m_alpha
;
}
float
get_beta
()
const
{
return
m_beta
;
}
float
get_gamma
()
const
{
return
m_gamma
;
}
matrix3x3
<
float
>
get_orthogonal_matrix
()
const
{
return
m_orthogonal
;
}
matrix3x3
<
float
>
get_fractional_matrix
()
const
{
return
m_fractional
;
}
private
:
void
init
();
float
m_a
,
m_b
,
m_c
,
m_alpha
,
m_beta
,
m_gamma
;
matrix3x3
<
float
>
m_orthogonal
,
m_fractional
;
};
// --------------------------------------------------------------------
int
get_space_group_number
(
const
datablock
&
db
);
int
get_space_group_number
(
const
datablock
&
db
);
int
get_space_group_number
(
std
::
string_view
spacegroup
);
int
get_space_group_number
(
std
::
string_view
spacegroup
);
...
@@ -331,15 +344,50 @@ class spacegroup : public std::vector<transformation>
...
@@ -331,15 +344,50 @@ class spacegroup : public std::vector<transformation>
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
//
Symmetry operations on points
//
A crystal combines a cell and a spacegroup.
template
<
typename
T
>
class
crystal
inline
point_type
<
T
>
operator
*
(
const
matrix3x3
<
T
>
&
m
,
const
point_type
<
T
>
&
pt
)
{
{
return
point_type
(
m
(
0
,
0
)
*
pt
.
m_x
+
m
(
0
,
1
)
*
pt
.
m_y
+
m
(
0
,
2
)
*
pt
.
m_z
,
public
:
m
(
1
,
0
)
*
pt
.
m_x
+
m
(
1
,
1
)
*
pt
.
m_y
+
m
(
1
,
2
)
*
pt
.
m_z
,
crystal
(
const
datablock
&
db
)
m
(
2
,
0
)
*
pt
.
m_x
+
m
(
2
,
1
)
*
pt
.
m_y
+
m
(
2
,
2
)
*
pt
.
m_z
);
:
m_cell
(
db
)
}
,
m_spacegroup
(
db
)
{
}
crystal
(
const
cell
&
c
,
const
spacegroup
&
sg
)
:
m_cell
(
c
)
,
m_spacegroup
(
sg
)
{
}
crystal
(
const
crystal
&
)
=
default
;
crystal
(
crystal
&&
)
=
default
;
crystal
&
operator
=
(
const
crystal
&
)
=
default
;
crystal
&
operator
=
(
crystal
&&
)
=
default
;
const
cell
&
get_cell
()
const
{
return
m_cell
;
}
const
spacegroup
&
get_spacegroup
()
const
{
return
m_spacegroup
;
}
point
symmetry_copy
(
const
point
&
pt
,
sym_op
symop
)
const
{
return
m_spacegroup
(
pt
,
m_cell
,
symop
);
}
point
inverse_symmetry_copy
(
const
point
&
pt
,
sym_op
symop
)
const
{
return
m_spacegroup
.
inverse
(
pt
,
m_cell
,
symop
);
}
std
::
tuple
<
float
,
point
,
sym_op
>
closest_symmetry_copy
(
point
a
,
point
b
)
const
;
private
:
cell
m_cell
;
spacegroup
m_spacegroup
;
};
// --------------------------------------------------------------------
// Symmetry operations on points
inline
point
orthogonal
(
const
point
&
pt
,
const
cell
&
c
)
inline
point
orthogonal
(
const
point
&
pt
,
const
cell
&
c
)
{
{
...
@@ -351,35 +399,6 @@ inline point fractional(const point &pt, const cell &c)
...
@@ -351,35 +399,6 @@ inline point fractional(const point &pt, const cell &c)
return
c
.
get_fractional_matrix
()
*
pt
;
return
c
.
get_fractional_matrix
()
*
pt
;
}
}
inline
transformation
orthogonal
(
const
transformation
&
t
,
const
cell
&
c
)
{
return
transformation
(
c
.
get_orthogonal_matrix
(),
{})
*
t
*
transformation
(
c
.
get_fractional_matrix
(),
{});
}
inline
transformation
fractional
(
const
transformation
&
t
,
const
cell
&
c
)
{
return
transformation
(
c
.
get_fractional_matrix
(),
{})
*
t
*
transformation
(
c
.
get_orthogonal_matrix
(),
{});
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
/// @brief Return the symmetry copy of a point based on spacegroup \a sg, cell \a c and symmetry operation \a symop
/// @param pt The point to transform
/// @param sg The spacegroup
/// @param c The cell
/// @param symop The symmetry operation
/// @return Newly calculated point
inline
point
symmetry_copy
(
const
point
&
pt
,
const
spacegroup
&
sg
,
const
cell
&
c
,
sym_op
symop
)
{
return
sg
(
pt
,
c
,
symop
);
}
/// @brief Return the point and symmetry operation required to move point \a b as close as possible to point \a a
/// @param sg The spacegroup
/// @param c The cell
/// @param a The point that acts as reference
/// @param b The point that needs to be moved
/// @return The calculated distance between the new point and \a a plus the symmetry operation required to operate on \a b
std
::
tuple
<
float
,
point
,
sym_op
>
closest_symmetry_copy
(
const
spacegroup
&
sg
,
const
cell
&
c
,
point
a
,
point
b
);
}
// namespace cif
}
// namespace cif
src/symmetry.cpp
View file @
eed7ec3a
...
@@ -32,6 +32,8 @@
...
@@ -32,6 +32,8 @@
#include "symop_table_data.hpp"
#include "symop_table_data.hpp"
#include <Eigen/Eigenvalues>
namespace
cif
namespace
cif
{
{
...
@@ -129,11 +131,60 @@ transformation::transformation(const symop_data &data)
...
@@ -129,11 +131,60 @@ transformation::transformation(const symop_data &data)
m_rotation
(
2
,
1
)
=
d
[
7
];
m_rotation
(
2
,
1
)
=
d
[
7
];
m_rotation
(
2
,
2
)
=
d
[
8
];
m_rotation
(
2
,
2
)
=
d
[
8
];
try_create_quaternion
();
m_translation
.
m_x
=
d
[
9
]
==
0
?
0
:
1.0
*
d
[
9
]
/
d
[
10
];
m_translation
.
m_x
=
d
[
9
]
==
0
?
0
:
1.0
*
d
[
9
]
/
d
[
10
];
m_translation
.
m_y
=
d
[
11
]
==
0
?
0
:
1.0
*
d
[
11
]
/
d
[
12
];
m_translation
.
m_y
=
d
[
11
]
==
0
?
0
:
1.0
*
d
[
11
]
/
d
[
12
];
m_translation
.
m_z
=
d
[
13
]
==
0
?
0
:
1.0
*
d
[
13
]
/
d
[
14
];
m_translation
.
m_z
=
d
[
13
]
==
0
?
0
:
1.0
*
d
[
13
]
/
d
[
14
];
}
}
transformation
::
transformation
(
const
matrix3x3
<
float
>
&
r
,
const
cif
::
point
&
t
)
:
m_rotation
(
r
)
,
m_translation
(
t
)
{
try_create_quaternion
();
}
void
transformation
::
try_create_quaternion
()
{
float
Qxx
=
m_rotation
(
0
,
0
);
float
Qxy
=
m_rotation
(
0
,
1
);
float
Qxz
=
m_rotation
(
0
,
2
);
float
Qyx
=
m_rotation
(
1
,
0
);
float
Qyy
=
m_rotation
(
1
,
1
);
float
Qyz
=
m_rotation
(
1
,
2
);
float
Qzx
=
m_rotation
(
2
,
0
);
float
Qzy
=
m_rotation
(
2
,
1
);
float
Qzz
=
m_rotation
(
2
,
2
);
Eigen
::
Matrix4f
em
;
em
<<
Qxx
-
Qyy
-
Qzz
,
Qyx
+
Qxy
,
Qzx
+
Qxz
,
Qzy
-
Qyz
,
Qyx
+
Qxy
,
Qyy
-
Qxx
-
Qzz
,
Qzy
+
Qyz
,
Qxz
-
Qzx
,
Qzx
+
Qxz
,
Qzy
+
Qyz
,
Qzz
-
Qxx
-
Qyy
,
Qyx
-
Qxy
,
Qzy
-
Qyz
,
Qxz
-
Qzx
,
Qyx
-
Qxy
,
Qxx
+
Qyy
+
Qzz
;
Eigen
::
EigenSolver
<
Eigen
::
Matrix4f
>
es
(
em
/
3
);
auto
ev
=
es
.
eigenvalues
();
for
(
size_t
j
=
0
;
j
<
4
;
++
j
)
{
if
(
std
::
abs
(
ev
[
j
].
real
()
-
1
)
>
0.01
)
continue
;
auto
col
=
es
.
eigenvectors
().
col
(
j
);
m_q
=
normalize
(
cif
::
quaternion
{
static_cast
<
float
>
(
col
(
3
).
real
()),
static_cast
<
float
>
(
col
(
0
).
real
()),
static_cast
<
float
>
(
col
(
1
).
real
()),
static_cast
<
float
>
(
col
(
2
).
real
())
});
break
;
}
}
transformation
operator
*
(
const
transformation
&
lhs
,
const
transformation
&
rhs
)
transformation
operator
*
(
const
transformation
&
lhs
,
const
transformation
&
rhs
)
{
{
auto
r
=
lhs
.
m_rotation
*
rhs
.
m_rotation
;
auto
r
=
lhs
.
m_rotation
*
rhs
.
m_rotation
;
...
@@ -141,8 +192,6 @@ transformation operator*(const transformation &lhs, const transformation &rhs)
...
@@ -141,8 +192,6 @@ transformation operator*(const transformation &lhs, const transformation &rhs)
t
=
t
+
lhs
.
m_translation
;
t
=
t
+
lhs
.
m_translation
;
return
transformation
(
r
,
t
);
return
transformation
(
r
,
t
);
// return transformation(lhs.m_rotation * rhs.m_rotation, lhs.m_rotation * rhs.m_translation + lhs.m_translation);
}
}
transformation
inverse
(
const
transformation
&
t
)
transformation
inverse
(
const
transformation
&
t
)
...
@@ -391,29 +440,29 @@ int get_space_group_number(const datablock &db)
...
@@ -391,29 +440,29 @@ int get_space_group_number(const datablock &db)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
std
::
tuple
<
float
,
point
,
sym_op
>
c
losest_symmetry_copy
(
const
spacegroup
&
sg
,
const
cell
&
c
,
point
a
,
point
b
)
std
::
tuple
<
float
,
point
,
sym_op
>
c
rystal
::
closest_symmetry_copy
(
point
a
,
point
b
)
const
{
{
if
(
c
.
get_a
()
==
0
or
c
.
get_b
()
==
0
or
c
.
get_c
()
==
0
)
if
(
m_cell
.
get_a
()
==
0
or
m_cell
.
get_b
()
==
0
or
m_cell
.
get_c
()
==
0
)
throw
std
::
runtime_error
(
"Invalid cell, contains a dimension that is zero"
);
throw
std
::
runtime_error
(
"Invalid cell, contains a dimension that is zero"
);
point
result_fsb
;
point
result_fsb
;
float
result_d
=
std
::
numeric_limits
<
float
>::
max
();
float
result_d
=
std
::
numeric_limits
<
float
>::
max
();
sym_op
result_s
;
sym_op
result_s
;
auto
fa
=
fractional
(
a
,
c
);
auto
fa
=
fractional
(
a
,
m_cell
);
auto
fb
=
fractional
(
b
,
c
);
auto
fb
=
fractional
(
b
,
m_cell
);
auto
o
=
offsetToOriginFractional
(
fa
);
auto
o
=
offsetToOriginFractional
(
fa
);
fa
=
fa
+
o
;
fa
=
fa
+
o
;
fb
=
fb
+
o
;
fb
=
fb
+
o
;
a
=
orthogonal
(
fa
,
c
);
a
=
orthogonal
(
fa
,
m_cell
);
for
(
size_t
i
=
0
;
i
<
sg
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
m_spacegroup
.
size
();
++
i
)
{
{
sym_op
s
(
i
+
1
);
sym_op
s
(
i
+
1
);
auto
&
t
=
sg
[
i
];
auto
&
t
=
m_spacegroup
[
i
];
auto
fsb
=
t
(
fb
);
auto
fsb
=
t
(
fb
);
...
@@ -453,8 +502,9 @@ std::tuple<float,point,sym_op> closest_symmetry_copy(const spacegroup &sg, const
...
@@ -453,8 +502,9 @@ std::tuple<float,point,sym_op> closest_symmetry_copy(const spacegroup &sg, const
s
.
m_tc
+=
1
;
s
.
m_tc
+=
1
;
}
}
auto
p
=
orthogonal
(
fsb
,
c
);
auto
p
=
orthogonal
(
fsb
,
m_cell
);
auto
dsq
=
distance_squared
(
a
,
p
);
auto
dsq
=
distance_squared
(
a
,
p
);
if
(
result_d
>
dsq
)
if
(
result_d
>
dsq
)
{
{
result_d
=
dsq
;
result_d
=
dsq
;
...
@@ -463,7 +513,7 @@ std::tuple<float,point,sym_op> closest_symmetry_copy(const spacegroup &sg, const
...
@@ -463,7 +513,7 @@ std::tuple<float,point,sym_op> closest_symmetry_copy(const spacegroup &sg, const
}
}
}
}
auto
p
=
orthogonal
(
result_fsb
-
o
,
c
);
auto
p
=
orthogonal
(
result_fsb
-
o
,
m_cell
);
return
{
std
::
sqrt
(
result_d
),
p
,
result_s
};
return
{
std
::
sqrt
(
result_d
),
p
,
result_s
};
}
}
...
...
test/unit-3d-test.cpp
View file @
eed7ec3a
...
@@ -31,6 +31,8 @@
...
@@ -31,6 +31,8 @@
#include <cif++.hpp>
#include <cif++.hpp>
#include <Eigen/Eigenvalues>
namespace
tt
=
boost
::
test_tools
;
namespace
tt
=
boost
::
test_tools
;
namespace
utf
=
boost
::
unit_test
;
namespace
utf
=
boost
::
unit_test
;
...
@@ -251,6 +253,72 @@ BOOST_AUTO_TEST_CASE(dh_q_1)
...
@@ -251,6 +253,72 @@ BOOST_AUTO_TEST_CASE(dh_q_1)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
m2q_0
,
*
utf
::
tolerance
(
0.001
f
))
{
for
(
size_t
i
=
0
;
i
<
cif
::
kSymopNrTableSize
;
++
i
)
{
auto
d
=
cif
::
kSymopNrTable
[
i
].
symop
().
data
();
cif
::
matrix3x3
<
float
>
rot
;
float
Qxx
=
rot
(
0
,
0
)
=
d
[
0
];
float
Qxy
=
rot
(
0
,
1
)
=
d
[
1
];
float
Qxz
=
rot
(
0
,
2
)
=
d
[
2
];
float
Qyx
=
rot
(
1
,
0
)
=
d
[
3
];
float
Qyy
=
rot
(
1
,
1
)
=
d
[
4
];
float
Qyz
=
rot
(
1
,
2
)
=
d
[
5
];
float
Qzx
=
rot
(
2
,
0
)
=
d
[
6
];
float
Qzy
=
rot
(
2
,
1
)
=
d
[
7
];
float
Qzz
=
rot
(
2
,
2
)
=
d
[
8
];
Eigen
::
Matrix4f
em
;
em
<<
Qxx
-
Qyy
-
Qzz
,
Qyx
+
Qxy
,
Qzx
+
Qxz
,
Qzy
-
Qyz
,
Qyx
+
Qxy
,
Qyy
-
Qxx
-
Qzz
,
Qzy
+
Qyz
,
Qxz
-
Qzx
,
Qzx
+
Qxz
,
Qzy
+
Qyz
,
Qzz
-
Qxx
-
Qyy
,
Qyx
-
Qxy
,
Qzy
-
Qyz
,
Qxz
-
Qzx
,
Qyx
-
Qxy
,
Qxx
+
Qyy
+
Qzz
;
Eigen
::
EigenSolver
<
Eigen
::
Matrix4f
>
es
(
em
/
3
);
auto
ev
=
es
.
eigenvalues
();
size_t
bestJ
=
0
;
float
bestEV
=
-
1
;
for
(
size_t
j
=
0
;
j
<
4
;
++
j
)
{
if
(
bestEV
<
ev
[
j
].
real
())
{
bestEV
=
ev
[
j
].
real
();
bestJ
=
j
;
}
}
if
(
std
::
abs
(
bestEV
-
1
)
>
0.01
)
continue
;
// not a rotation matrix
auto
col
=
es
.
eigenvectors
().
col
(
bestJ
);
auto
q
=
normalize
(
cif
::
quaternion
{
static_cast
<
float
>
(
col
(
3
).
real
()),
static_cast
<
float
>
(
col
(
0
).
real
()),
static_cast
<
float
>
(
col
(
1
).
real
()),
static_cast
<
float
>
(
col
(
2
).
real
())
});
cif
::
point
p1
{
1
,
1
,
1
};
cif
::
point
p2
=
p1
;
p2
.
rotate
(
q
);
cif
::
point
p3
=
rot
*
p1
;
BOOST_TEST
(
p2
.
m_x
==
p3
.
m_x
);
BOOST_TEST
(
p2
.
m_y
==
p3
.
m_y
);
BOOST_TEST
(
p2
.
m_z
==
p3
.
m_z
);
}
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
symm_1
)
BOOST_AUTO_TEST_CASE
(
symm_1
)
{
{
cif
::
cell
c
(
10
,
10
,
10
);
cif
::
cell
c
(
10
,
10
,
10
);
...
@@ -324,18 +392,17 @@ BOOST_AUTO_TEST_CASE(symm_4wvp_1, *utf::tolerance(0.1f))
...
@@ -324,18 +392,17 @@ BOOST_AUTO_TEST_CASE(symm_4wvp_1, *utf::tolerance(0.1f))
auto
&
db
=
f
.
front
();
auto
&
db
=
f
.
front
();
cif
::
mm
::
structure
s
(
db
);
cif
::
mm
::
structure
s
(
db
);
cif
::
spacegroup
sg
(
db
);
cif
::
crystal
c
(
db
);
cif
::
cell
c
(
db
);
cif
::
point
p
{
-
78.722
,
98.528
,
11.994
};
cif
::
point
p
{
-
78.722
,
98.528
,
11.994
};
auto
a
=
s
.
get_residue
(
"A"
,
10
,
""
).
get_atom_by_atom_id
(
"O"
);
auto
a
=
s
.
get_residue
(
"A"
,
10
,
""
).
get_atom_by_atom_id
(
"O"
);
auto
sp1
=
c
if
::
symmetry_copy
(
a
.
get_location
(),
sg
,
c
,
"2_565"
_symop
);
auto
sp1
=
c
.
symmetry_copy
(
a
.
get_location
()
,
"2_565"
_symop
);
BOOST_TEST
(
sp1
.
m_x
==
p
.
m_x
);
BOOST_TEST
(
sp1
.
m_x
==
p
.
m_x
);
BOOST_TEST
(
sp1
.
m_y
==
p
.
m_y
);
BOOST_TEST
(
sp1
.
m_y
==
p
.
m_y
);
BOOST_TEST
(
sp1
.
m_z
==
p
.
m_z
);
BOOST_TEST
(
sp1
.
m_z
==
p
.
m_z
);
const
auto
&
[
d
,
sp2
,
so
]
=
c
if
::
closest_symmetry_copy
(
sg
,
c
,
p
,
a
.
get_location
());
const
auto
&
[
d
,
sp2
,
so
]
=
c
.
closest_symmetry_copy
(
p
,
a
.
get_location
());
BOOST_TEST
(
d
<
1
);
BOOST_TEST
(
d
<
1
);
...
@@ -352,8 +419,7 @@ BOOST_AUTO_TEST_CASE(symm_2bi3_1, *utf::tolerance(0.1f))
...
@@ -352,8 +419,7 @@ BOOST_AUTO_TEST_CASE(symm_2bi3_1, *utf::tolerance(0.1f))
auto
&
db
=
f
.
front
();
auto
&
db
=
f
.
front
();
cif
::
mm
::
structure
s
(
db
);
cif
::
mm
::
structure
s
(
db
);
cif
::
spacegroup
sg
(
db
);
cif
::
crystal
c
(
db
);
cif
::
cell
c
(
db
);
auto
struct_conn
=
db
[
"struct_conn"
];
auto
struct_conn
=
db
[
"struct_conn"
];
for
(
const
auto
&
[
for
(
const
auto
&
[
...
@@ -375,14 +441,14 @@ BOOST_AUTO_TEST_CASE(symm_2bi3_1, *utf::tolerance(0.1f))
...
@@ -375,14 +441,14 @@ BOOST_AUTO_TEST_CASE(symm_2bi3_1, *utf::tolerance(0.1f))
auto
a1
=
r1
.
get_atom_by_atom_id
(
atomid1
);
auto
a1
=
r1
.
get_atom_by_atom_id
(
atomid1
);
auto
a2
=
r2
.
get_atom_by_atom_id
(
atomid2
);
auto
a2
=
r2
.
get_atom_by_atom_id
(
atomid2
);
auto
sa1
=
symmetry_copy
(
a1
.
get_location
(),
sg
,
c
,
cif
::
sym_op
(
symm1
));
auto
sa1
=
c
.
symmetry_copy
(
a1
.
get_location
()
,
cif
::
sym_op
(
symm1
));
auto
sa2
=
symmetry_copy
(
a2
.
get_location
(),
sg
,
c
,
cif
::
sym_op
(
symm2
));
auto
sa2
=
c
.
symmetry_copy
(
a2
.
get_location
()
,
cif
::
sym_op
(
symm2
));
BOOST_TEST
(
cif
::
distance
(
sa1
,
sa2
)
==
dist
);
BOOST_TEST
(
cif
::
distance
(
sa1
,
sa2
)
==
dist
);
auto
pa1
=
a1
.
get_location
();
auto
pa1
=
a1
.
get_location
();
const
auto
&
[
d
,
p
,
so
]
=
c
if
::
closest_symmetry_copy
(
sg
,
c
,
pa1
,
a2
.
get_location
());
const
auto
&
[
d
,
p
,
so
]
=
c
.
closest_symmetry_copy
(
pa1
,
a2
.
get_location
());
BOOST_TEST
(
p
.
m_x
==
sa2
.
m_x
);
BOOST_TEST
(
p
.
m_x
==
sa2
.
m_x
);
BOOST_TEST
(
p
.
m_y
==
sa2
.
m_y
);
BOOST_TEST
(
p
.
m_y
==
sa2
.
m_y
);
...
@@ -400,8 +466,7 @@ BOOST_AUTO_TEST_CASE(symm_3bwh_1, *utf::tolerance(0.1f))
...
@@ -400,8 +466,7 @@ BOOST_AUTO_TEST_CASE(symm_3bwh_1, *utf::tolerance(0.1f))
auto
&
db
=
f
.
front
();
auto
&
db
=
f
.
front
();
cif
::
spacegroup
sg
(
db
);
cif
::
crystal
c
(
db
);
cif
::
cell
c
(
db
);
cif
::
mm
::
structure
s
(
db
);
cif
::
mm
::
structure
s
(
db
);
for
(
auto
a1
:
s
.
atoms
())
for
(
auto
a1
:
s
.
atoms
())
...
@@ -411,7 +476,7 @@ BOOST_AUTO_TEST_CASE(symm_3bwh_1, *utf::tolerance(0.1f))
...
@@ -411,7 +476,7 @@ BOOST_AUTO_TEST_CASE(symm_3bwh_1, *utf::tolerance(0.1f))
if
(
a1
==
a2
)
if
(
a1
==
a2
)
continue
;
continue
;
const
auto
&
[
d
,
p
,
so
]
=
c
if
::
closest_symmetry_copy
(
sg
,
c
,
a1
.
get_location
(),
a2
.
get_location
());
const
auto
&
[
d
,
p
,
so
]
=
c
.
closest_symmetry_copy
(
a1
.
get_location
(),
a2
.
get_location
());
BOOST_TEST
(
d
==
distance
(
a1
.
get_location
(),
p
));
BOOST_TEST
(
d
==
distance
(
a1
.
get_location
(),
p
));
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment