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
9aa8a223
Unverified
Commit
9aa8a223
authored
Apr 12, 2023
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
symmetry work
parent
fb59adcf
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
414 additions
and
275 deletions
+414
-275
include/cif++/matrix.hpp
+0
-0
include/cif++/point.hpp
+0
-1
include/cif++/symmetry.hpp
+196
-13
src/point.cpp
+8
-246
src/symmetry.cpp
+142
-13
src/symop-map-generator.cpp
+3
-0
src/symop_table_data.hpp
+0
-0
test/unit-3d-test.cpp
+65
-2
No files found.
include/cif++/matrix.hpp
0 → 100644
View file @
9aa8a223
This diff is collapsed.
Click to expand it.
include/cif++/point.hpp
View file @
9aa8a223
...
@@ -718,7 +718,6 @@ template <int N>
...
@@ -718,7 +718,6 @@ template <int N>
class
spherical_dots
class
spherical_dots
{
{
public
:
public
:
constexpr
static
int
P
=
2
*
N
*
1
;
constexpr
static
int
P
=
2
*
N
*
1
;
using
array_type
=
typename
std
::
array
<
point
,
P
>
;
using
array_type
=
typename
std
::
array
<
point
,
P
>
;
...
...
include/cif++/symmetry.hpp
View file @
9aa8a223
...
@@ -27,6 +27,8 @@
...
@@ -27,6 +27,8 @@
#pragma once
#pragma once
#include "cif++/exports.hpp"
#include "cif++/exports.hpp"
#include "cif++/matrix.hpp"
#include "cif++/point.hpp"
#include <array>
#include <array>
#include <cstdint>
#include <cstdint>
...
@@ -60,20 +62,20 @@ extern CIFPP_EXPORT const std::size_t kNrOfSpaceGroups;
...
@@ -60,20 +62,20 @@ extern CIFPP_EXPORT const std::size_t kNrOfSpaceGroups;
struct
symop_data
struct
symop_data
{
{
constexpr
symop_data
(
const
std
::
array
<
int
,
15
>
&
data
)
constexpr
symop_data
(
const
std
::
array
<
int
,
15
>
&
data
)
:
m_packed
((
data
[
0
]
bitand
0x03ULL
)
<<
34
bitor
:
m_packed
((
data
[
0
]
bitand
0x03ULL
)
<<
34
bitor
(
data
[
1
]
bitand
0x03ULL
)
<<
32
bitor
(
data
[
1
]
bitand
0x03ULL
)
<<
32
bitor
(
data
[
2
]
bitand
0x03ULL
)
<<
30
bitor
(
data
[
2
]
bitand
0x03ULL
)
<<
30
bitor
(
data
[
3
]
bitand
0x03ULL
)
<<
28
bitor
(
data
[
3
]
bitand
0x03ULL
)
<<
28
bitor
(
data
[
4
]
bitand
0x03ULL
)
<<
26
bitor
(
data
[
4
]
bitand
0x03ULL
)
<<
26
bitor
(
data
[
5
]
bitand
0x03ULL
)
<<
24
bitor
(
data
[
5
]
bitand
0x03ULL
)
<<
24
bitor
(
data
[
6
]
bitand
0x03ULL
)
<<
22
bitor
(
data
[
6
]
bitand
0x03ULL
)
<<
22
bitor
(
data
[
7
]
bitand
0x03ULL
)
<<
20
bitor
(
data
[
7
]
bitand
0x03ULL
)
<<
20
bitor
(
data
[
8
]
bitand
0x03ULL
)
<<
18
bitor
(
data
[
8
]
bitand
0x03ULL
)
<<
18
bitor
(
data
[
9
]
bitand
0x07ULL
)
<<
15
bitor
(
data
[
9
]
bitand
0x07ULL
)
<<
15
bitor
(
data
[
10
]
bitand
0x07ULL
)
<<
12
bitor
(
data
[
10
]
bitand
0x07ULL
)
<<
12
bitor
(
data
[
11
]
bitand
0x07ULL
)
<<
9
bitor
(
data
[
11
]
bitand
0x07ULL
)
<<
9
bitor
(
data
[
12
]
bitand
0x07ULL
)
<<
6
bitor
(
data
[
12
]
bitand
0x07ULL
)
<<
6
bitor
(
data
[
13
]
bitand
0x07ULL
)
<<
3
bitor
(
data
[
13
]
bitand
0x07ULL
)
<<
3
bitor
(
data
[
14
]
bitand
0x07ULL
)
<<
0
)
(
data
[
14
]
bitand
0x07ULL
)
<<
0
)
{
{
}
}
...
@@ -156,8 +158,189 @@ extern CIFPP_EXPORT const symop_datablock kSymopNrTable[];
...
@@ -156,8 +158,189 @@ extern CIFPP_EXPORT const symop_datablock kSymopNrTable[];
extern
CIFPP_EXPORT
const
std
::
size_t
kSymopNrTableSize
;
extern
CIFPP_EXPORT
const
std
::
size_t
kSymopNrTableSize
;
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Some more symmetry related stuff here.
class
datablock
;
class
cell
;
class
spacegroup
;
class
rtop
;
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
class
sym_op
{
public
:
sym_op
(
uint8_t
nr
=
1
,
uint8_t
ta
=
5
,
uint8_t
tb
=
5
,
uint8_t
tc
=
5
)
:
m_nr
(
nr
)
,
m_ta
(
ta
)
,
m_tb
(
tb
)
,
m_tc
(
tc
)
{
}
explicit
sym_op
(
std
::
string_view
s
);
sym_op
(
const
sym_op
&
)
=
default
;
sym_op
(
sym_op
&&
)
=
default
;
sym_op
&
operator
=
(
const
sym_op
&
)
=
default
;
sym_op
&
operator
=
(
sym_op
&&
)
=
default
;
constexpr
bool
is_identity
()
const
{
return
m_nr
==
1
and
m_ta
==
5
and
m_tb
==
5
and
m_tc
==
5
;
}
explicit
constexpr
operator
bool
()
const
{
return
not
is_identity
();
}
std
::
string
string
()
const
;
friend
class
spacegroup
;
private
:
uint8_t
m_nr
;
uint8_t
m_ta
,
m_tb
,
m_tc
;
};
namespace
literals
{
inline
sym_op
operator
""
_symop
(
const
char
*
text
,
size_t
length
)
{
return
sym_op
({
text
,
length
});
}
}
// namespace literals
class
transformation
{
public
:
transformation
(
const
symop_data
&
data
);
transformation
(
const
matrix3x3
<
float
>
&
r
,
const
cif
::
point
&
t
)
:
m_rotation
(
r
)
,
m_translation
(
t
)
{
}
transformation
(
const
transformation
&
)
=
default
;
transformation
(
transformation
&&
)
=
default
;
transformation
&
operator
=
(
const
transformation
&
)
=
default
;
transformation
&
operator
=
(
transformation
&&
)
=
default
;
point
operator
()(
const
cell
&
c
,
const
point
&
pt
)
const
;
private
:
matrix3x3
<
float
>
m_rotation
;
point
m_translation
;
};
// --------------------------------------------------------------------
int
get_space_group_number
(
std
::
string_view
spacegroup
);
// alternative for clipper's parsing code, using space_group_name::full
int
get_space_group_number
(
std
::
string_view
spacegroup
,
space_group_name
type
);
// alternative for clipper's parsing code
class
spacegroup
:
public
std
::
vector
<
transformation
>
{
public
:
spacegroup
(
std
::
string_view
name
)
:
spacegroup
(
get_space_group_number
(
name
))
{
}
spacegroup
(
std
::
string_view
name
,
space_group_name
type
)
:
spacegroup
(
get_space_group_number
(
name
,
type
))
{
}
spacegroup
(
int
nr
);
int
get_nr
()
const
{
return
m_nr
;
}
std
::
string
get_name
()
const
;
point
operator
()(
const
point
&
pt
,
const
cell
&
c
,
sym_op
symop
);
private
:
int
m_nr
;
size_t
m_index
;
};
// --------------------------------------------------------------------
int
get_space_group_number
(
std
::
string
spacegroup
);
// alternative for clipper's parsing code, using space_group_name::full
int
get_space_group_number
(
std
::
string
spacegroup
);
// alternative for clipper's parsing code, using space_group_name::full
int
get_space_group_number
(
std
::
string
spacegroup
,
space_group_name
type
);
// alternative for clipper's parsing code
int
get_space_group_number
(
std
::
string
spacegroup
,
space_group_name
type
);
// alternative for clipper's parsing code
// class rtop
// {
// public:
// rtop(const spacegroup &sg, const cell &c, int nr);
// friend rtop operator+(rtop rt, cif::point t);
// friend cif::point operator*(cif::point p, rtop rt);
// private:
// cell m_c;
// cif::quaternion m_q;
// cif::point m_t;
// };
// class spacegroup
// {
// public:
// spacegroup(const cif::datablock &db);
// private:
// std::vector<
// };
static_assert
(
sizeof
(
sym_op
)
==
4
,
"Sym_op should be four bytes"
);
// --------------------------------------------------------------------
// Symmetry operations on points
template
<
typename
T
>
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
,
m
(
1
,
0
)
*
pt
.
m_x
+
m
(
1
,
1
)
*
pt
.
m_y
+
m
(
1
,
2
)
*
pt
.
m_z
,
m
(
2
,
0
)
*
pt
.
m_x
+
m
(
2
,
1
)
*
pt
.
m_y
+
m
(
2
,
2
)
*
pt
.
m_z
);
}
inline
point
orthogonal
(
const
point
&
pt
,
const
cell
&
c
)
{
return
c
.
get_orthogonal_matrix
()
*
pt
;
}
inline
point
fractional
(
const
point
&
pt
,
const
cell
&
c
)
{
return
c
.
get_fractional_matrix
()
*
pt
;
}
}
// namespace cif
}
// namespace cif
src/point.cpp
View file @
9aa8a223
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
*/
*/
#include "cif++/point.hpp"
#include "cif++/point.hpp"
#include "cif++/matrix.hpp"
#include <cassert>
#include <cassert>
#include <random>
#include <random>
...
@@ -33,245 +34,6 @@ namespace cif
...
@@ -33,245 +34,6 @@ namespace cif
{
{
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// We're using expression templates here
template
<
typename
M
>
class
MatrixExpression
{
public
:
uint32_t
dim_m
()
const
{
return
static_cast
<
const
M
&>
(
*
this
).
dim_m
();
}
uint32_t
dim_n
()
const
{
return
static_cast
<
const
M
&>
(
*
this
).
dim_n
();
}
double
&
operator
()(
uint32_t
i
,
uint32_t
j
)
{
return
static_cast
<
M
&>
(
*
this
).
operator
()(
i
,
j
);
}
double
operator
()(
uint32_t
i
,
uint32_t
j
)
const
{
return
static_cast
<
const
M
&>
(
*
this
).
operator
()(
i
,
j
);
}
};
// --------------------------------------------------------------------
// matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
// element m i,j is mapped to [i * n + j] and thus storage is row major
class
Matrix
:
public
MatrixExpression
<
Matrix
>
{
public
:
template
<
typename
M2
>
Matrix
(
const
MatrixExpression
<
M2
>
&
m
)
:
m_m
(
m
.
dim_m
())
,
m_n
(
m
.
dim_n
())
,
m_data
(
m_m
*
m_n
)
{
for
(
uint32_t
i
=
0
;
i
<
m_m
;
++
i
)
{
for
(
uint32_t
j
=
0
;
j
<
m_n
;
++
j
)
operator
()(
i
,
j
)
=
m
(
i
,
j
);
}
}
Matrix
(
size_t
m
,
size_t
n
,
double
v
=
0
)
:
m_m
(
m
)
,
m_n
(
n
)
,
m_data
(
m_m
*
m_n
)
{
std
::
fill
(
m_data
.
begin
(),
m_data
.
end
(),
v
);
}
Matrix
()
=
default
;
Matrix
(
Matrix
&&
m
)
=
default
;
Matrix
(
const
Matrix
&
m
)
=
default
;
Matrix
&
operator
=
(
Matrix
&&
m
)
=
default
;
Matrix
&
operator
=
(
const
Matrix
&
m
)
=
default
;
size_t
dim_m
()
const
{
return
m_m
;
}
size_t
dim_n
()
const
{
return
m_n
;
}
double
operator
()(
size_t
i
,
size_t
j
)
const
{
assert
(
i
<
m_m
);
assert
(
j
<
m_n
);
return
m_data
[
i
*
m_n
+
j
];
}
double
&
operator
()(
size_t
i
,
size_t
j
)
{
assert
(
i
<
m_m
);
assert
(
j
<
m_n
);
return
m_data
[
i
*
m_n
+
j
];
}
private
:
size_t
m_m
=
0
,
m_n
=
0
;
std
::
vector
<
double
>
m_data
;
};
// --------------------------------------------------------------------
class
SymmetricMatrix
:
public
MatrixExpression
<
SymmetricMatrix
>
{
public
:
SymmetricMatrix
(
uint32_t
n
,
double
v
=
0
)
:
m_n
(
n
)
,
m_data
((
m_n
*
(
m_n
+
1
))
/
2
)
{
std
::
fill
(
m_data
.
begin
(),
m_data
.
end
(),
v
);
}
SymmetricMatrix
()
=
default
;
SymmetricMatrix
(
SymmetricMatrix
&&
m
)
=
default
;
SymmetricMatrix
(
const
SymmetricMatrix
&
m
)
=
default
;
SymmetricMatrix
&
operator
=
(
SymmetricMatrix
&&
m
)
=
default
;
SymmetricMatrix
&
operator
=
(
const
SymmetricMatrix
&
m
)
=
default
;
uint32_t
dim_m
()
const
{
return
m_n
;
}
uint32_t
dim_n
()
const
{
return
m_n
;
}
double
operator
()(
uint32_t
i
,
uint32_t
j
)
const
{
return
i
<
j
?
m_data
[(
j
*
(
j
+
1
))
/
2
+
i
]
:
m_data
[(
i
*
(
i
+
1
))
/
2
+
j
];
}
double
&
operator
()(
uint32_t
i
,
uint32_t
j
)
{
if
(
i
>
j
)
std
::
swap
(
i
,
j
);
assert
(
j
<
m_n
);
return
m_data
[(
j
*
(
j
+
1
))
/
2
+
i
];
}
private
:
uint32_t
m_n
;
std
::
vector
<
double
>
m_data
;
};
class
IdentityMatrix
:
public
MatrixExpression
<
IdentityMatrix
>
{
public
:
IdentityMatrix
(
uint32_t
n
)
:
m_n
(
n
)
{
}
uint32_t
dim_m
()
const
{
return
m_n
;
}
uint32_t
dim_n
()
const
{
return
m_n
;
}
double
operator
()(
uint32_t
i
,
uint32_t
j
)
const
{
return
i
==
j
?
1
:
0
;
}
private
:
uint32_t
m_n
;
};
// --------------------------------------------------------------------
// matrix functions, implemented as expression templates
template
<
typename
M1
,
typename
M2
>
class
MatrixSubtraction
:
public
MatrixExpression
<
MatrixSubtraction
<
M1
,
M2
>>
{
public
:
MatrixSubtraction
(
const
M1
&
m1
,
const
M2
&
m2
)
:
m_m1
(
m1
)
,
m_m2
(
m2
)
{
assert
(
m_m1
.
dim_m
()
==
m_m2
.
dim_m
());
assert
(
m_m1
.
dim_n
()
==
m_m2
.
dim_n
());
}
uint32_t
dim_m
()
const
{
return
m_m1
.
dim_m
();
}
uint32_t
dim_n
()
const
{
return
m_m1
.
dim_n
();
}
double
operator
()(
uint32_t
i
,
uint32_t
j
)
const
{
return
m_m1
(
i
,
j
)
-
m_m2
(
i
,
j
);
}
private
:
const
M1
&
m_m1
;
const
M2
&
m_m2
;
};
template
<
typename
M1
,
typename
M2
>
MatrixSubtraction
<
M1
,
M2
>
operator
-
(
const
MatrixExpression
<
M1
>
&
m1
,
const
MatrixExpression
<
M2
>
&
m2
)
{
return
MatrixSubtraction
(
*
static_cast
<
const
M1
*>
(
&
m1
),
*
static_cast
<
const
M2
*>
(
&
m2
));
}
template
<
typename
M
>
class
MatrixMultiplication
:
public
MatrixExpression
<
MatrixMultiplication
<
M
>>
{
public
:
MatrixMultiplication
(
const
M
&
m
,
double
v
)
:
m_m
(
m
)
,
m_v
(
v
)
{
}
uint32_t
dim_m
()
const
{
return
m_m
.
dim_m
();
}
uint32_t
dim_n
()
const
{
return
m_m
.
dim_n
();
}
double
operator
()(
uint32_t
i
,
uint32_t
j
)
const
{
return
m_m
(
i
,
j
)
*
m_v
;
}
private
:
const
M
&
m_m
;
double
m_v
;
};
template
<
typename
M
>
MatrixMultiplication
<
M
>
operator
*
(
const
MatrixExpression
<
M
>
&
m
,
double
v
)
{
return
MatrixMultiplication
(
*
static_cast
<
const
M
*>
(
&
m
),
v
);
}
// --------------------------------------------------------------------
template
<
class
M1
>
Matrix
Cofactors
(
const
M1
&
m
)
{
Matrix
cf
(
m
.
dim_m
(),
m
.
dim_m
());
const
size_t
ixs
[
4
][
3
]
=
{
{
1
,
2
,
3
},
{
0
,
2
,
3
},
{
0
,
1
,
3
},
{
0
,
1
,
2
}
};
for
(
size_t
x
=
0
;
x
<
4
;
++
x
)
{
const
size_t
*
ix
=
ixs
[
x
];
for
(
size_t
y
=
0
;
y
<
4
;
++
y
)
{
const
size_t
*
iy
=
ixs
[
y
];
cf
(
x
,
y
)
=
m
(
ix
[
0
],
iy
[
0
])
*
m
(
ix
[
1
],
iy
[
1
])
*
m
(
ix
[
2
],
iy
[
2
])
+
m
(
ix
[
0
],
iy
[
1
])
*
m
(
ix
[
1
],
iy
[
2
])
*
m
(
ix
[
2
],
iy
[
0
])
+
m
(
ix
[
0
],
iy
[
2
])
*
m
(
ix
[
1
],
iy
[
0
])
*
m
(
ix
[
2
],
iy
[
1
])
-
m
(
ix
[
0
],
iy
[
2
])
*
m
(
ix
[
1
],
iy
[
1
])
*
m
(
ix
[
2
],
iy
[
0
])
-
m
(
ix
[
0
],
iy
[
1
])
*
m
(
ix
[
1
],
iy
[
0
])
*
m
(
ix
[
2
],
iy
[
2
])
-
m
(
ix
[
0
],
iy
[
0
])
*
m
(
ix
[
1
],
iy
[
2
])
*
m
(
ix
[
2
],
iy
[
1
]);
if
((
x
+
y
)
%
2
==
1
)
cf
(
x
,
y
)
*=
-
1
;
}
}
return
cf
;
}
// --------------------------------------------------------------------
template
<
typename
T
>
template
<
typename
T
>
quaternion_type
<
T
>
normalize
(
quaternion_type
<
T
>
q
)
quaternion_type
<
T
>
normalize
(
quaternion_type
<
T
>
q
)
...
@@ -443,8 +205,8 @@ double LargestDepressedQuarticSolution(double a, double b, double c)
...
@@ -443,8 +205,8 @@ double LargestDepressedQuarticSolution(double a, double b, double c)
quaternion
align_points
(
const
std
::
vector
<
point
>
&
pa
,
const
std
::
vector
<
point
>
&
pb
)
quaternion
align_points
(
const
std
::
vector
<
point
>
&
pa
,
const
std
::
vector
<
point
>
&
pb
)
{
{
// First calculate M, a 3x3
M
atrix containing the sums of products of the coordinates of A and B
// First calculate M, a 3x3
m
atrix containing the sums of products of the coordinates of A and B
Matrix
M
(
3
,
3
,
0
)
;
matrix3x3
<
double
>
M
;
for
(
uint32_t
i
=
0
;
i
<
pa
.
size
();
++
i
)
for
(
uint32_t
i
=
0
;
i
<
pa
.
size
();
++
i
)
{
{
...
@@ -462,8 +224,8 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
...
@@ -462,8 +224,8 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
M
(
2
,
2
)
+=
a
.
m_z
*
b
.
m_z
;
M
(
2
,
2
)
+=
a
.
m_z
*
b
.
m_z
;
}
}
// Now calculate N, a symmetric 4x4
M
atrix
// Now calculate N, a symmetric 4x4
m
atrix
SymmetricMatrix
N
(
4
);
symmetric_matrix4x4
<
double
>
N
(
4
);
N
(
0
,
0
)
=
M
(
0
,
0
)
+
M
(
1
,
1
)
+
M
(
2
,
2
);
N
(
0
,
0
)
=
M
(
0
,
0
)
+
M
(
1
,
1
)
+
M
(
2
,
2
);
N
(
0
,
1
)
=
M
(
1
,
2
)
-
M
(
2
,
1
);
N
(
0
,
1
)
=
M
(
1
,
2
)
-
M
(
2
,
1
);
...
@@ -512,10 +274,10 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
...
@@ -512,10 +274,10 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
double
lambda
=
LargestDepressedQuarticSolution
(
C
,
D
,
E
);
double
lambda
=
LargestDepressedQuarticSolution
(
C
,
D
,
E
);
// calculate t = (N - λI)
// calculate t = (N - λI)
Matrix
t
=
N
-
IdentityMatrix
(
4
)
*
lambda
;
matrix
<
double
>
t
(
N
-
identity_matrix
(
4
)
*
lambda
)
;
// calculate a
M
atrix of cofactors for t
// calculate a
m
atrix of cofactors for t
Matrix
cf
=
C
ofactors
(
t
);
auto
cf
=
matrix_c
ofactors
(
t
);
int
maxR
=
0
;
int
maxR
=
0
;
for
(
int
r
=
1
;
r
<
4
;
++
r
)
for
(
int
r
=
1
;
r
<
4
;
++
r
)
...
...
src/symmetry.cpp
View file @
9aa8a223
/*-
/*-
* SPDX-License-Identifier: BSD-2-Clause
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
@@ -25,6 +25,8 @@
...
@@ -25,6 +25,8 @@
*/
*/
#include "cif++/symmetry.hpp"
#include "cif++/symmetry.hpp"
#include "cif++/datablock.hpp"
#include "cif++/point.hpp"
#include <stdexcept>
#include <stdexcept>
...
@@ -34,13 +36,140 @@ namespace cif
...
@@ -34,13 +36,140 @@ namespace cif
{
{
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Unfortunately, clipper has a different numbering scheme than CCP4
cell
::
cell
(
float
a
,
float
b
,
float
c
,
float
alpha
,
float
beta
,
float
gamma
)
:
m_a
(
a
)
,
m_b
(
b
)
,
m_c
(
c
)
,
m_alpha
(
alpha
)
,
m_beta
(
beta
)
,
m_gamma
(
gamma
)
{
init
();
}
cell
::
cell
(
const
datablock
&
db
)
{
auto
&
_cell
=
db
[
"cell"
];
cif
::
tie
(
m_a
,
m_b
,
m_c
,
m_alpha
,
m_beta
,
m_gamma
)
=
_cell
.
front
().
get
(
"length_a"
,
"length_b"
,
"length_c"
,
"angle_alpha"
,
"angle_beta"
,
"angle_gamma"
);
init
();
}
void
cell
::
init
()
{
auto
alpha
=
(
m_alpha
*
kPI
)
/
180
;
auto
beta
=
(
m_beta
*
kPI
)
/
180
;
auto
gamma
=
(
m_gamma
*
kPI
)
/
180
;
auto
alpha_star
=
std
::
acos
((
std
::
cos
(
gamma
)
*
std
::
cos
(
beta
)
-
std
::
cos
(
alpha
))
/
(
std
::
sin
(
beta
)
*
std
::
sin
(
gamma
)));
m_orthogonal
=
identity_matrix
(
3
);
m_orthogonal
(
0
,
0
)
=
m_a
;
m_orthogonal
(
0
,
1
)
=
m_b
*
std
::
cos
(
gamma
);
m_orthogonal
(
0
,
2
)
=
m_c
*
std
::
cos
(
beta
);
m_orthogonal
(
1
,
1
)
=
m_b
*
std
::
sin
(
gamma
);
m_orthogonal
(
1
,
2
)
=
-
m_c
*
std
::
sin
(
beta
)
*
std
::
cos
(
alpha_star
);
m_orthogonal
(
2
,
2
)
=
m_c
*
std
::
sin
(
beta
)
*
std
::
sin
(
alpha_star
);
m_fractional
=
inverse
(
m_orthogonal
);
}
// --------------------------------------------------------------------
sym_op
::
sym_op
(
std
::
string_view
s
)
{
auto
b
=
s
.
data
();
auto
e
=
b
+
s
.
length
();
int
rnri
;
auto
r
=
std
::
from_chars
(
b
,
e
,
rnri
);
m_nr
=
rnri
;
m_ta
=
r
.
ptr
[
1
]
-
'0'
;
m_tb
=
r
.
ptr
[
2
]
-
'0'
;
m_tc
=
r
.
ptr
[
3
]
-
'0'
;
if
(
r
.
ec
!=
std
::
errc
()
or
rnri
>
192
or
r
.
ptr
[
0
]
!=
'_'
or
m_ta
>
9
or
m_tb
>
9
or
m_tc
>
9
)
throw
std
::
invalid_argument
(
"Could not convert string into sym_op"
);
}
// --------------------------------------------------------------------
transformation
::
transformation
(
const
symop_data
&
data
)
{
const
auto
&
d
=
data
.
data
();
m_rotation
(
0
,
0
)
=
d
[
0
];
m_rotation
(
0
,
1
)
=
d
[
1
];
m_rotation
(
0
,
2
)
=
d
[
2
];
m_rotation
(
1
,
0
)
=
d
[
3
];
m_rotation
(
1
,
1
)
=
d
[
4
];
m_rotation
(
1
,
2
)
=
d
[
5
];
m_rotation
(
2
,
0
)
=
d
[
6
];
m_rotation
(
2
,
1
)
=
d
[
7
];
m_rotation
(
2
,
2
)
=
d
[
8
];
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
[
13
]
==
0
?
0
:
1.0
*
d
[
13
]
/
d
[
14
];
}
// --------------------------------------------------------------------
spacegroup
::
spacegroup
(
int
nr
)
:
m_nr
(
nr
)
{
const
size_t
N
=
cif
::
kSymopNrTableSize
;
int32_t
L
=
0
,
R
=
static_cast
<
int32_t
>
(
N
-
1
);
while
(
L
<=
R
)
{
int32_t
i
=
(
L
+
R
)
/
2
;
if
(
cif
::
kSymopNrTable
[
i
].
spacegroup
()
<
m_nr
)
L
=
i
+
1
;
else
R
=
i
-
1
;
}
m_index
=
L
;
for
(
size_t
i
=
L
;
i
<
N
and
cif
::
kSymopNrTable
[
i
].
spacegroup
()
==
m_nr
;
++
i
)
emplace_back
(
cif
::
kSymopNrTable
[
i
].
symop
().
data
());
}
std
::
string
spacegroup
::
get_name
()
const
{
for
(
auto
&
s
:
kSpaceGroups
)
{
if
(
s
.
nr
==
m_nr
)
return
s
.
name
;
}
throw
std
::
runtime_error
(
"Spacegroup has an invalid number: "
+
std
::
to_string
(
m_nr
));
}
point
spacegroup
::
operator
()(
const
point
&
pt
,
const
cell
&
c
,
sym_op
symop
)
{
if
(
symop
.
m_nr
<
1
or
symop
.
m_nr
>
size
())
throw
std
::
out_of_range
(
"symmetry operator number out of range"
);
transformation
t
=
at
(
symop
.
m_nr
-
1
);
return
pt
;
}
// --------------------------------------------------------------------
// Unfortunately, clipper has a different numbering scheme than PDB
// for rotation numbers. So we created a table to map those.
// for rotation numbers. So we created a table to map those.
// Perhaps a bit over the top, but hey....
// Perhaps a bit over the top, but hey....
// --------------------------------------------------------------------
// --------------------------------------------------------------------
int
get_space_group_number
(
std
::
string
spacegroup
)
int
get_space_group_number
(
std
::
string
_view
spacegroup
)
{
{
if
(
spacegroup
==
"P 21 21 2 A"
)
if
(
spacegroup
==
"P 21 21 2 A"
)
spacegroup
=
"P 21 21 2 (a)"
;
spacegroup
=
"P 21 21 2 (a)"
;
...
@@ -73,7 +202,7 @@ int get_space_group_number(std::string spacegroup)
...
@@ -73,7 +202,7 @@ int get_space_group_number(std::string spacegroup)
{
{
for
(
size_t
i
=
0
;
i
<
kNrOfSpaceGroups
;
++
i
)
for
(
size_t
i
=
0
;
i
<
kNrOfSpaceGroups
;
++
i
)
{
{
auto
&
sp
=
kSpaceGroups
[
i
];
auto
&
sp
=
kSpaceGroups
[
i
];
if
(
sp
.
xHM
==
spacegroup
)
if
(
sp
.
xHM
==
spacegroup
)
{
{
result
=
sp
.
nr
;
result
=
sp
.
nr
;
...
@@ -83,14 +212,14 @@ int get_space_group_number(std::string spacegroup)
...
@@ -83,14 +212,14 @@ int get_space_group_number(std::string spacegroup)
}
}
if
(
result
==
0
)
if
(
result
==
0
)
throw
std
::
runtime_error
(
"Spacegroup name "
+
s
pacegroup
+
" was not found in table"
);
throw
std
::
runtime_error
(
"Spacegroup name "
+
s
td
::
string
(
spacegroup
)
+
" was not found in table"
);
return
result
;
return
result
;
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
int
get_space_group_number
(
std
::
string
spacegroup
,
space_group_name
type
)
int
get_space_group_number
(
std
::
string
_view
spacegroup
,
space_group_name
type
)
{
{
if
(
spacegroup
==
"P 21 21 2 A"
)
if
(
spacegroup
==
"P 21 21 2 A"
)
spacegroup
=
"P 21 21 2 (a)"
;
spacegroup
=
"P 21 21 2 (a)"
;
...
@@ -145,9 +274,9 @@ int get_space_group_number(std::string spacegroup, space_group_name type)
...
@@ -145,9 +274,9 @@ int get_space_group_number(std::string spacegroup, space_group_name type)
// not found, see if we can find a match based on xHM name
// not found, see if we can find a match based on xHM name
if
(
result
==
0
)
if
(
result
==
0
)
throw
std
::
runtime_error
(
"Spacegroup name "
+
s
pacegroup
+
" was not found in table"
);
throw
std
::
runtime_error
(
"Spacegroup name "
+
s
td
::
string
(
spacegroup
)
+
" was not found in table"
);
return
result
;
return
result
;
}
}
}
}
// namespace cif
src/symop-map-generator.cpp
View file @
9aa8a223
...
@@ -315,7 +315,10 @@ int main(int argc, char* const argv[])
...
@@ -315,7 +315,10 @@ int main(int argc, char* const argv[])
{
{
case
State
:
:
skip
:
case
State
:
:
skip
:
if
(
line
==
"begin_spacegroup"
)
if
(
line
==
"begin_spacegroup"
)
{
state
=
State
::
spacegroup
;
state
=
State
::
spacegroup
;
cur
=
{};
}
break
;
break
;
case
State
:
:
spacegroup
:
case
State
:
:
spacegroup
:
...
...
src/symop_table_data.hpp
View file @
9aa8a223
This diff is collapsed.
Click to expand it.
test/unit-3d-test.cpp
View file @
9aa8a223
...
@@ -246,4 +246,68 @@ BOOST_AUTO_TEST_CASE(dh_q_1)
...
@@ -246,4 +246,68 @@ BOOST_AUTO_TEST_CASE(dh_q_1)
auto
dh
=
cif
::
dihedral_angle
(
pts
[
0
],
pts
[
1
],
pts
[
2
],
pts
[
3
]);
auto
dh
=
cif
::
dihedral_angle
(
pts
[
0
],
pts
[
1
],
pts
[
2
],
pts
[
3
]);
BOOST_TEST
(
dh
==
angle
,
tt
::
tolerance
(
0.1
f
));
BOOST_TEST
(
dh
==
angle
,
tt
::
tolerance
(
0.1
f
));
}
}
}
}
\ No newline at end of file
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
symm_1
)
{
cif
::
cell
c
(
10
,
10
,
10
);
cif
::
point
p
{
1
,
1
,
1
};
cif
::
point
f
=
fractional
(
p
,
c
);
BOOST_TEST
(
f
.
m_x
==
0.1
f
,
tt
::
tolerance
(
0.01
));
BOOST_TEST
(
f
.
m_y
==
0.1
f
,
tt
::
tolerance
(
0.01
));
BOOST_TEST
(
f
.
m_z
==
0.1
f
,
tt
::
tolerance
(
0.01
));
cif
::
point
o
=
orthogonal
(
f
,
c
);
BOOST_TEST
(
o
.
m_x
==
1.
f
,
tt
::
tolerance
(
0.01
));
BOOST_TEST
(
o
.
m_y
==
1.
f
,
tt
::
tolerance
(
0.01
));
BOOST_TEST
(
o
.
m_z
==
1.
f
,
tt
::
tolerance
(
0.01
));
}
BOOST_AUTO_TEST_CASE
(
symm_2
)
{
using
namespace
cif
::
literals
;
auto
symop
=
"1_555"
_symop
;
BOOST_TEST
(
symop
.
is_identity
()
==
true
);
}
BOOST_AUTO_TEST_CASE
(
symm_3
)
{
using
namespace
cif
::
literals
;
cif
::
spacegroup
sg
(
18
);
BOOST_TEST
(
sg
.
size
()
==
4
);
BOOST_TEST
(
sg
.
get_name
()
==
"P 21 21 2"
);
}
BOOST_AUTO_TEST_CASE
(
symm_4
)
{
using
namespace
cif
::
literals
;
// based on 2b8h
auto
sg
=
cif
::
spacegroup
(
154
);
// p 32 2 1
auto
c
=
cif
::
cell
(
107.516
,
107.516
,
338.487
,
90.00
,
90.00
,
120.00
);
cif
::
point
a
{
-
8.688
,
79.351
,
10.439
};
// O6 NAG A 500
cif
::
point
b
{
-
35.356
,
33.693
,
-
3.236
};
// CG2 THR D 400
cif
::
point
sb
(
-
6.916
,
79.34
,
3.236
);
// 4_565 copy of b
BOOST_TEST
(
distance
(
a
,
sg
(
a
,
c
,
"1_455"
_symop
))
==
static_cast
<
float
>
(
c
.
get_a
()));
BOOST_TEST
(
distance
(
a
,
sg
(
a
,
c
,
"1_545"
_symop
))
==
static_cast
<
float
>
(
c
.
get_b
()));
BOOST_TEST
(
distance
(
a
,
sg
(
a
,
c
,
"1_554"
_symop
))
==
static_cast
<
float
>
(
c
.
get_c
()));
auto
sb2
=
sg
(
b
,
c
,
"4_565"
_symop
);
BOOST_TEST
(
sb
.
m_x
==
sb2
.
m_x
);
BOOST_TEST
(
sb
.
m_y
==
sb2
.
m_y
);
BOOST_TEST
(
sb
.
m_z
==
sb2
.
m_z
);
BOOST_TEST
(
distance
(
a
,
sb2
)
==
7.42
f
);
}
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