mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 22:14:24 +08:00
Compare commits
673 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a82a8d5a8 | ||
|
|
11019a26f8 | ||
|
|
6f8909dce9 | ||
|
|
5525103aaf | ||
|
|
291ef737b1 | ||
|
|
af125bdd57 | ||
|
|
79089bbb8c | ||
|
|
1f08498d00 | ||
|
|
49ba714a03 | ||
|
|
85fd9296b2 | ||
|
|
1cda14867f | ||
|
|
2d2b26f7dc | ||
|
|
93b33af44a | ||
|
|
eb80490bcd | ||
|
|
ba2b06f5af | ||
|
|
fecc762db1 | ||
|
|
1e406253ab | ||
|
|
6e3b85f43d | ||
|
|
58f1b626e2 | ||
|
|
c104a08e16 | ||
|
|
dd0f6ca1e6 | ||
|
|
f02ea91b51 | ||
|
|
6768a501a3 | ||
|
|
879e15c759 | ||
|
|
89285b4abc | ||
|
|
c584714f91 | ||
|
|
f5016403b7 | ||
|
|
c8f66ae6bb | ||
|
|
858c967e71 | ||
|
|
f9ca5de5bf | ||
|
|
252c3476a1 | ||
|
|
19210df6db | ||
|
|
15c5730749 | ||
|
|
3764adb7ef | ||
|
|
9160adb1cf | ||
|
|
3ebf4338ab | ||
|
|
2eb4b7b39b | ||
|
|
c241e49b48 | ||
|
|
238c881132 | ||
|
|
49dc733536 | ||
|
|
755bd78f60 | ||
|
|
77f80cd51f | ||
|
|
3df6000635 | ||
|
|
5efee2b40d | ||
|
|
f3c2e59184 | ||
|
|
24ab660e6e | ||
|
|
6c0a418068 | ||
|
|
07a180991e | ||
|
|
4732004b67 | ||
|
|
faa9cd0431 | ||
|
|
e0c3c2394d | ||
|
|
2dec584f54 | ||
|
|
5ab2ccae40 | ||
|
|
1017d08626 | ||
|
|
32b1bbd943 | ||
|
|
1abf31ffa5 | ||
|
|
aec60829d2 | ||
|
|
888c3c38c2 | ||
|
|
e2c4648037 | ||
|
|
f7b98c0530 | ||
|
|
d4bd3faa16 | ||
|
|
c4f3b1cd7b | ||
|
|
74add69a83 | ||
|
|
a490b19d24 | ||
|
|
44cfa2c1a2 | ||
|
|
6dd9522b3f | ||
|
|
5e352cb8e4 | ||
|
|
2fad7315b8 | ||
|
|
520759dfe8 | ||
|
|
577b44ae11 | ||
|
|
66f742d6c0 | ||
|
|
7ba9f688c7 | ||
|
|
883f0307a2 | ||
|
|
c9719f873f | ||
|
|
123d25f853 | ||
|
|
56da42db84 | ||
|
|
7f820449ca | ||
|
|
ecb2cf5f11 | ||
|
|
7f27da9b3b | ||
|
|
01eb499c69 | ||
|
|
1ff6f70682 | ||
|
|
ddde996e10 | ||
|
|
1c9212c7e0 | ||
|
|
a568143991 | ||
|
|
2b6f1bd9ee | ||
|
|
2527aa5ea6 | ||
|
|
4c28091ecd | ||
|
|
d49725423e | ||
|
|
fcb4dc61b5 | ||
|
|
b7330c074f | ||
|
|
e8f4123030 | ||
|
|
975057c4c4 | ||
|
|
a0e01668d1 | ||
|
|
2c77491416 | ||
|
|
be19e4a9cb | ||
|
|
61ce91a9d7 | ||
|
|
18f1d07e85 | ||
|
|
b596976194 | ||
|
|
1f6b86d516 | ||
|
|
31499b977d | ||
|
|
f83850e380 | ||
|
|
1a4ccd86fe | ||
|
|
5c3c6fec09 | ||
|
|
f97e742daa | ||
|
|
7f39d401e2 | ||
|
|
af412c284d | ||
|
|
874cd3bae5 | ||
|
|
ea28ebdd13 | ||
|
|
3ba468933f | ||
|
|
45f33e4bea | ||
|
|
021487ed16 | ||
|
|
cb3443ffb1 | ||
|
|
6b2c9dc3e3 | ||
|
|
7513cc1947 | ||
|
|
c98b8ae5c9 | ||
|
|
ab2dd4b75f | ||
|
|
be77316545 | ||
|
|
cdfb0d9497 | ||
|
|
71f7e7c741 | ||
|
|
cff099596e | ||
|
|
e182604455 | ||
|
|
45a7defb7e | ||
|
|
906f6ac1ea | ||
|
|
8d96e513bd | ||
|
|
cdefd063e2 | ||
|
|
8bbcba76cf | ||
|
|
c767e89a5d | ||
|
|
b78a603dca | ||
|
|
18088457d3 | ||
|
|
056697d901 | ||
|
|
2681cfad50 | ||
|
|
8aaa7925a3 | ||
|
|
d4f73e471b | ||
|
|
750be0c4a4 | ||
|
|
0f4a2a26fc | ||
|
|
6adb56341d | ||
|
|
4524357cd3 | ||
|
|
0b05b6f6e3 | ||
|
|
6382170157 | ||
|
|
c2eeb69dcc | ||
|
|
f32261fc59 | ||
|
|
90c967c8c6 | ||
|
|
4ac90128db | ||
|
|
3d71db1bb7 | ||
|
|
5e35ea5168 | ||
|
|
2fc88d52eb | ||
|
|
567b0f3b57 | ||
|
|
8f29386998 | ||
|
|
d2427d57d9 | ||
|
|
14a9499962 | ||
|
|
0fafb80d44 | ||
|
|
b5454f0943 | ||
|
|
b698260d73 | ||
|
|
ccdd1b74a0 | ||
|
|
298fe20a1b | ||
|
|
12a7c45452 | ||
|
|
02a28c2fd6 | ||
|
|
68e182b0bd | ||
|
|
b0ec88f469 | ||
|
|
4feee6ac22 | ||
|
|
ee8a85ec2f | ||
|
|
0245d4a881 | ||
|
|
e8f0058956 | ||
|
|
9c75dbaae0 | ||
|
|
5bd39b598e | ||
|
|
25a43abffd | ||
|
|
9a7ca022e2 | ||
|
|
46fe0d7caf | ||
|
|
0371cec415 | ||
|
|
2b1020cbb9 | ||
|
|
8c3ce2a87d | ||
|
|
d633622e27 | ||
|
|
19b652f615 | ||
|
|
37f7dd0631 | ||
|
|
4c99710fb3 | ||
|
|
59865cdb44 | ||
|
|
c3434507da | ||
|
|
79ecf20b85 | ||
|
|
1de9681bb7 | ||
|
|
345c4778e6 | ||
|
|
0ccb2f88ca | ||
|
|
f7bef8b0e9 | ||
|
|
9da8608f8f | ||
|
|
496cb0b909 | ||
|
|
583cafa91e | ||
|
|
01da665243 | ||
|
|
e900cd1e3d | ||
|
|
a8a838b33e | ||
|
|
072be25335 | ||
|
|
5f50429cdb | ||
|
|
db3fb04172 | ||
|
|
839385c3fb | ||
|
|
d508b7b2df | ||
|
|
b1456b87c0 | ||
|
|
58d2dcaef2 | ||
|
|
a9468d1cbb | ||
|
|
a29e3e8da3 | ||
|
|
dd5df1bb2a | ||
|
|
d5d6f3a7b3 | ||
|
|
9d2f2b3026 | ||
|
|
74717a3047 | ||
|
|
c13ee92f1e | ||
|
|
0ca04bed4f | ||
|
|
89850de660 | ||
|
|
8bb4ebd897 | ||
|
|
6a67208d24 | ||
|
|
139f32c3e8 | ||
|
|
81c0d01944 | ||
|
|
1d2f997efb | ||
|
|
f126b1dac3 | ||
|
|
bbc38262ce | ||
|
|
caeafd3189 | ||
|
|
98e3c47cdf | ||
|
|
390b230cac | ||
|
|
c5c3950c91 | ||
|
|
2aea0b3b1f | ||
|
|
6b16e02b34 | ||
|
|
bb2f81318a | ||
|
|
ec91d0fb22 | ||
|
|
760e23693e | ||
|
|
cfba00ae46 | ||
|
|
dc1cfb60ff | ||
|
|
92148304ee | ||
|
|
9329c0c0f6 | ||
|
|
de3ac001fc | ||
|
|
b1047154a4 | ||
|
|
c361af3792 | ||
|
|
73487fc24b | ||
|
|
73513fd700 | ||
|
|
6b7723eb2a | ||
|
|
7056c15366 | ||
|
|
8539e050ae | ||
|
|
5d4c2641f6 | ||
|
|
bc32071576 | ||
|
|
3b2c57314f | ||
|
|
36351a0608 | ||
|
|
047b454c1d | ||
|
|
3f5e620102 | ||
|
|
851a43ba4b | ||
|
|
47ae50f704 | ||
|
|
33bdd6ae82 | ||
|
|
433021727e | ||
|
|
7f23c84287 | ||
|
|
74bd2585e7 | ||
|
|
ebb27638ff | ||
|
|
3eb7e4c5bf | ||
|
|
112f859b19 | ||
|
|
fd08678ff6 | ||
|
|
2e2fc11fe1 | ||
|
|
d44ed57cf9 | ||
|
|
aa31acb056 | ||
|
|
232003cb2e | ||
|
|
db21dd1659 | ||
|
|
2f3279a5ff | ||
|
|
ab21317156 | ||
|
|
43cb312225 | ||
|
|
ce28cb7a48 | ||
|
|
1e47fa557c | ||
|
|
1ae3cf7b99 | ||
|
|
915d6504a2 | ||
|
|
5e63ca7a82 | ||
|
|
e0777e74c2 | ||
|
|
cf465134fd | ||
|
|
873ac70d18 | ||
|
|
9ca3c50c83 | ||
|
|
cc1c7c39b1 | ||
|
|
2c6222984d | ||
|
|
58d7e17165 | ||
|
|
57618095bf | ||
|
|
492a1ad8ec | ||
|
|
71da0ce345 | ||
|
|
7dc574b534 | ||
|
|
ff8a7a1bfd | ||
|
|
0f963eeab1 | ||
|
|
8f02665e6d | ||
|
|
8604c3ab03 | ||
|
|
7a61129388 | ||
|
|
516db3d8be | ||
|
|
34bdc5056a | ||
|
|
9402fd5cf3 | ||
|
|
a6faa5ce0c | ||
|
|
5735a70e47 | ||
|
|
8f997658d7 | ||
|
|
5069316326 | ||
|
|
143f17fb2a | ||
|
|
900d7fa07a | ||
|
|
a4389542fd | ||
|
|
b7f4e40917 | ||
|
|
a0447ba91c | ||
|
|
17c9d208ad | ||
|
|
e89311fcff | ||
|
|
bab750fa6c | ||
|
|
0caaf23767 | ||
|
|
c5676f1dfb | ||
|
|
86854581f8 | ||
|
|
ef81944826 | ||
|
|
b3b53ebcc0 | ||
|
|
3bc0384100 | ||
|
|
24b1c2ae58 | ||
|
|
c996bfcfaf | ||
|
|
3814635aa0 | ||
|
|
2b6c09cfad | ||
|
|
9ee474081e | ||
|
|
5bab298f74 | ||
|
|
fd42b7f443 | ||
|
|
edcea220f6 | ||
|
|
a92e85f8db | ||
|
|
6fbe8bb192 | ||
|
|
5f45fd9b5b | ||
|
|
46925331c7 | ||
|
|
84123df996 | ||
|
|
641b446195 | ||
|
|
34bbf06793 | ||
|
|
53a88e236b | ||
|
|
c2069a12b4 | ||
|
|
791ab245ca | ||
|
|
43287736bb | ||
|
|
34ee3321d8 | ||
|
|
6e433ae784 | ||
|
|
cd370275da | ||
|
|
7ed0f4c8ae | ||
|
|
ea7d8ce766 | ||
|
|
f12e877251 | ||
|
|
57ce90ce7c | ||
|
|
b61321e360 | ||
|
|
6416056958 | ||
|
|
4fdfd03c04 | ||
|
|
a1d2438341 | ||
|
|
952aa15d6e | ||
|
|
b3e45eb0b6 | ||
|
|
a548b39677 | ||
|
|
d5d96c58e4 | ||
|
|
9b61a06ef1 | ||
|
|
3dbf19ac0b | ||
|
|
7dc999ef39 | ||
|
|
697028b706 | ||
|
|
c260fccdb5 | ||
|
|
d9bf7c941b | ||
|
|
af64151c60 | ||
|
|
da94d65c6b | ||
|
|
d51340000f | ||
|
|
6f93fa3758 | ||
|
|
598f953cc1 | ||
|
|
c39304281d | ||
|
|
5e5e5c21ed | ||
|
|
299e270594 | ||
|
|
bd8a4e3639 | ||
|
|
b3b5d05bfc | ||
|
|
268cefcb51 | ||
|
|
f4e860bc2c | ||
|
|
b65aa46daa | ||
|
|
faef95a84d | ||
|
|
25dfdd2ff6 | ||
|
|
88879a5de9 | ||
|
|
52919f96a7 | ||
|
|
402505098a | ||
|
|
e8d8b8be60 | ||
|
|
5ff7d01bd2 | ||
|
|
3f8849680b | ||
|
|
e450fee020 | ||
|
|
d7c162c71c | ||
|
|
f211fa4b5e | ||
|
|
c3963bc453 | ||
|
|
23bd51ac9c | ||
|
|
9e200b947e | ||
|
|
2e661d5ff4 | ||
|
|
766d5a4d7e | ||
|
|
1f24937e65 | ||
|
|
aba35c3440 | ||
|
|
3a8fd0ebb1 | ||
|
|
69a2d53277 | ||
|
|
0b66d67ef3 | ||
|
|
1f22326db6 | ||
|
|
b4dfdb5515 | ||
|
|
25512340c8 | ||
|
|
d2d322ba30 | ||
|
|
96a26eae4a | ||
|
|
71a46cd10e | ||
|
|
013af6af46 | ||
|
|
1d79a9e915 | ||
|
|
28b4deaf32 | ||
|
|
694d93f50b | ||
|
|
8fed9a1302 | ||
|
|
4fa2d84374 | ||
|
|
0e43b81c34 | ||
|
|
eaf38e6353 | ||
|
|
4012a71f6c | ||
|
|
5a71dbecdc | ||
|
|
6675768ab4 | ||
|
|
63256f09ad | ||
|
|
be54866ca4 | ||
|
|
7329009fff | ||
|
|
bb5d72a40e | ||
|
|
85d68b93eb | ||
|
|
360d970033 | ||
|
|
87d87fe5b0 | ||
|
|
bdfde18728 | ||
|
|
1d0b2b8c6e | ||
|
|
7e91ae334f | ||
|
|
515d16fe79 | ||
|
|
896a8ebbdc | ||
|
|
ae23938aa4 | ||
|
|
4db05c20ae | ||
|
|
8bb0663313 | ||
|
|
83b2c651f1 | ||
|
|
e65a782f45 | ||
|
|
43f418ae67 | ||
|
|
4b4757ee74 | ||
|
|
ac088dd0a4 | ||
|
|
31c86d9c8a | ||
|
|
85b08f9d77 | ||
|
|
d50529c6b9 | ||
|
|
bb9d81616b | ||
|
|
024607002e | ||
|
|
31ce161543 | ||
|
|
359538e170 | ||
|
|
d45ce5060d | ||
|
|
6aebf8408f | ||
|
|
5ce8d87b19 | ||
|
|
f815b8588a | ||
|
|
e812e2e092 | ||
|
|
43eda65dd8 | ||
|
|
3a94384775 | ||
|
|
7c5bf01090 | ||
|
|
3f421f34a2 | ||
|
|
c7f67525ec | ||
|
|
71a78813e1 | ||
|
|
62face74ee | ||
|
|
1cbfbd8f4f | ||
|
|
3928be4939 | ||
|
|
a967154625 | ||
|
|
78dd9a3c02 | ||
|
|
52d6b2eace | ||
|
|
2ef9e6b843 | ||
|
|
48d9d22d70 | ||
|
|
a3d9bc01a0 | ||
|
|
52ea0bc7fc | ||
|
|
ba804abb34 | ||
|
|
6835a9808b | ||
|
|
77fc4080c5 | ||
|
|
599d0cb537 | ||
|
|
59a7ff68e0 | ||
|
|
80bb24f347 | ||
|
|
34c7fd3f54 | ||
|
|
fac1eb915a | ||
|
|
3a84a8e6e8 | ||
|
|
dd02b3633d | ||
|
|
54728d49be | ||
|
|
2afddc23ff | ||
|
|
700c1d408d | ||
|
|
e3297d0de6 | ||
|
|
e4ced4caef | ||
|
|
14e32bed28 | ||
|
|
a3cf3343c9 | ||
|
|
188fa4e59c | ||
|
|
d053492a7c | ||
|
|
8d9f4f007b | ||
|
|
5084e7185a | ||
|
|
11b4c1d399 | ||
|
|
a56b6b136d | ||
|
|
b6e8f79c1a | ||
|
|
eda40b8eb6 | ||
|
|
c0c4be78f2 | ||
|
|
513dbb6bfd | ||
|
|
77e0b3f776 | ||
|
|
a7249eb2ca | ||
|
|
51aebf844a | ||
|
|
38121e20f5 | ||
|
|
dbd826867f | ||
|
|
fe519e71a5 | ||
|
|
072882e005 | ||
|
|
3ab625cb2b | ||
|
|
2583975afd | ||
|
|
9ec0eae41f | ||
|
|
f2449abb79 | ||
|
|
4a5312a648 | ||
|
|
9c636544b3 | ||
|
|
19714ecb0b | ||
|
|
9fbd41aef9 | ||
|
|
c432ac4d7c | ||
|
|
267302429c | ||
|
|
db164a2045 | ||
|
|
9b1e935628 | ||
|
|
f1dfe12c24 | ||
|
|
0bdda4610a | ||
|
|
530d1110d9 | ||
|
|
d170c8da78 | ||
|
|
fe6d7a11ca | ||
|
|
6082b11959 | ||
|
|
01dbe675c8 | ||
|
|
a825cfc687 | ||
|
|
9f81a4ef89 | ||
|
|
c9f37c74b4 | ||
|
|
ffd82dfee0 | ||
|
|
6ef927cfa1 | ||
|
|
13a38fd011 | ||
|
|
f90990507a | ||
|
|
55b1c56647 | ||
|
|
1c009d481d | ||
|
|
42c72958a8 | ||
|
|
13109f767a | ||
|
|
72e6708076 | ||
|
|
aaf25de2d0 | ||
|
|
0cbb927b0f | ||
|
|
59f2387b68 | ||
|
|
6d07611e49 | ||
|
|
f7b12dedc0 | ||
|
|
2cce9e5379 | ||
|
|
5e1fe8211a | ||
|
|
29ebdcf7d2 | ||
|
|
4206f26699 | ||
|
|
dd7a4f1189 | ||
|
|
d1b3f08d5b | ||
|
|
9a7aeed632 | ||
|
|
963d51bbcb | ||
|
|
ef7a6f8f9d | ||
|
|
85aed9fb40 | ||
|
|
603a0eca6b | ||
|
|
cccbfe025d | ||
|
|
778fa86410 | ||
|
|
b4da5aeda3 | ||
|
|
4ddfe65734 | ||
|
|
95d0d55715 | ||
|
|
ec09e7ba57 | ||
|
|
74750a7940 | ||
|
|
0de2ae3673 | ||
|
|
a236547a54 | ||
|
|
8f12d15439 | ||
|
|
535ea566de | ||
|
|
e095d3bf67 | ||
|
|
bb0562ebc1 | ||
|
|
ec4ea697dd | ||
|
|
4918f572b4 | ||
|
|
0119c93aa0 | ||
|
|
03c95609dd | ||
|
|
3650bc9269 | ||
|
|
25e2c38076 | ||
|
|
a265b97058 | ||
|
|
fa7a0de6db | ||
|
|
996710728a | ||
|
|
b5f159c345 | ||
|
|
958d1fb32c | ||
|
|
28620841e0 | ||
|
|
e0d2c1328c | ||
|
|
9a54b6b990 | ||
|
|
e27908b9ee | ||
|
|
63fa06d656 | ||
|
|
9856d0de35 | ||
|
|
a2a1e63e06 | ||
|
|
a83fb55961 | ||
|
|
83965b9a7f | ||
|
|
e5bd42b4c7 | ||
|
|
602c770a45 | ||
|
|
64e2793c51 | ||
|
|
51b6c7eb3f | ||
|
|
1cf8e7b72a | ||
|
|
bc50f86836 | ||
|
|
909a33c01a | ||
|
|
f66bd7fdaa | ||
|
|
7f23427272 | ||
|
|
4f2427e95c | ||
|
|
1546cedb63 | ||
|
|
d3bc435a2e | ||
|
|
4436ad4358 | ||
|
|
5af0296028 | ||
|
|
b450cdf16d | ||
|
|
f96499cdd8 | ||
|
|
274120c9fc | ||
|
|
0d50305679 | ||
|
|
6999b7a12a | ||
|
|
8118c073c4 | ||
|
|
27bda1c6a0 | ||
|
|
7927a7c0dd | ||
|
|
39ead681b0 | ||
|
|
9c05120753 | ||
|
|
91abdc568b | ||
|
|
b1a6180a67 | ||
|
|
a789367ee8 | ||
|
|
61dbb7c137 | ||
|
|
834a3a50f9 | ||
|
|
7a423aecf7 | ||
|
|
91f7f9c238 | ||
|
|
af930b23a1 | ||
|
|
8047cda02d | ||
|
|
773137e852 | ||
|
|
efd96f18b4 | ||
|
|
deeac050f9 | ||
|
|
0ab408e1b3 | ||
|
|
521fafdd32 | ||
|
|
66fa88ec88 | ||
|
|
4738d97948 | ||
|
|
cc2f705a21 | ||
|
|
3d9200f990 | ||
|
|
0af4eca14f | ||
|
|
26dc7eaa08 | ||
|
|
9b5ef7548f | ||
|
|
41b2231ee5 | ||
|
|
4a81e814c1 | ||
|
|
ef6643122f | ||
|
|
00742f65af | ||
|
|
1da97e6ebb | ||
|
|
38a852ca20 | ||
|
|
a5b64ec805 | ||
|
|
6dc402263a | ||
|
|
54b8cb5c85 | ||
|
|
8bf1f01926 | ||
|
|
791d8bd98a | ||
|
|
5b963bf62f | ||
|
|
0dc6531395 | ||
|
|
07617dcdac | ||
|
|
2a2172a9eb | ||
|
|
065ba540b2 | ||
|
|
e19fc4f7b6 | ||
|
|
db5540cfc6 | ||
|
|
8aaf0d8813 | ||
|
|
e53c77cb7f | ||
|
|
1a8d585b9c | ||
|
|
d4de02a229 | ||
|
|
b60face9af | ||
|
|
91f8ac9edd | ||
|
|
6d12375691 | ||
|
|
924d37b603 | ||
|
|
6105c1f6fd | ||
|
|
93a96960f1 | ||
|
|
53091a321a | ||
|
|
eccf6c8855 | ||
|
|
2a2fefa80d | ||
|
|
65f17a7b26 | ||
|
|
d2716b4ea2 | ||
|
|
9af1dabbe6 | ||
|
|
1e4e0638b7 | ||
|
|
724c834656 | ||
|
|
ef4120fd72 | ||
|
|
3a9688089c | ||
|
|
eb4f2f778f | ||
|
|
a793eb4c51 | ||
|
|
6f1a592cc9 | ||
|
|
1242ce1d29 | ||
|
|
7dedb46d08 | ||
|
|
0d18d47775 | ||
|
|
4664c0bbe0 | ||
|
|
4543e34c00 | ||
|
|
b85f340cc7 | ||
|
|
c73e18fc26 | ||
|
|
17034d3bff | ||
|
|
4632a41763 | ||
|
|
16492f6f5b | ||
|
|
4362fd9d6e | ||
|
|
3b44209b15 | ||
|
|
679a15b637 | ||
|
|
b4a52806e6 | ||
|
|
311961e80b | ||
|
|
0e31a9b17f | ||
|
|
d3194f8cc0 | ||
|
|
2a9bb5752a | ||
|
|
821c1ef94f | ||
|
|
ba0e39c0da | ||
|
|
371c2aa876 | ||
|
|
05ec536059 | ||
|
|
b0272a1cd5 | ||
|
|
caf80a0efe | ||
|
|
032138c4d3 | ||
|
|
e0dc9f1c95 | ||
|
|
c5d277fb43 | ||
|
|
d0b7e21c77 | ||
|
|
b1de54f8b1 | ||
|
|
141764edf5 | ||
|
|
00fe32b76f | ||
|
|
bfd74e6f01 | ||
|
|
edf132c4bd | ||
|
|
f3878b3760 | ||
|
|
6c93599687 | ||
|
|
ca881b82b5 |
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
build/
|
||||
.vscode/
|
||||
.vs/
|
||||
.pc/
|
||||
tools/symop-map-generator
|
||||
test/unit-test
|
||||
test/pdb2cif-test
|
||||
test/rename-compound-test
|
||||
tools/update-libcifpp-data
|
||||
data/components.cif*
|
||||
CMakeSettings.json
|
||||
msvc/
|
||||
Testing/
|
||||
rsrc/feature-request.txt
|
||||
test/1cbs.cif
|
||||
33
.travis.yml
Normal file
33
.travis.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
language: cpp
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
dist: focal
|
||||
|
||||
osx_image:
|
||||
- xcode12
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libboost-all-dev
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install make; fi
|
||||
|
||||
script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./configure --disable-shared --disable-revision --disable-download-ccd ; else ./configure --disable-revision --disable-download-ccd ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then gmake ; else make ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then gmake test ; else make test ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then sudo gmake install ; else sudo make install; fi
|
||||
|
||||
# jobs:
|
||||
# allow_failures:
|
||||
# - os: osx
|
||||
|
||||
462
CMakeLists.txt
Normal file
462
CMakeLists.txt
Normal file
@@ -0,0 +1,462 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# 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
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# set the project name
|
||||
project(cifpp VERSION 4.0.0 LANGUAGES CXX)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
enable_testing()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(Dart)
|
||||
include(GenerateExportHeader)
|
||||
|
||||
set(CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
|
||||
elseif(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
|
||||
# Building shared libraries?
|
||||
option(BUILD_SHARED_LIBS "Build a shared library instead of a static one" OFF)
|
||||
|
||||
# We do not want to write an export file for all our symbols...
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
|
||||
# Optionally build a version to be installed inside CCP4
|
||||
option(BUILD_FOR_CCP4 "Build a version to be installed in CCP4" OFF)
|
||||
if(BUILD_FOR_CCP4)
|
||||
if("$ENV{CCP4}" STREQUAL "" OR NOT EXISTS $ENV{CCP4})
|
||||
message(FATAL_ERROR "A CCP4 built was requested but CCP4 was not sourced")
|
||||
else()
|
||||
list(APPEND CMAKE_MODULE_PATH "$ENV{CCP4}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{CCP4}")
|
||||
set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}")
|
||||
|
||||
# This is the only option:
|
||||
if(WIN32)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
endif()
|
||||
endif("$ENV{CCP4}" STREQUAL "" OR NOT EXISTS $ENV{CCP4})
|
||||
|
||||
add_definitions(-DCCP4=1)
|
||||
endif()
|
||||
|
||||
# Check if CCP4 is available
|
||||
if(EXISTS "$ENV{CCP4}")
|
||||
set(CCP4 $ENV{CCP4})
|
||||
set(CLIBD ${CCP4}/lib/data)
|
||||
endif()
|
||||
if(CCP4 AND NOT CLIBD)
|
||||
set(CLIBD ${CCP4}/lib/data)
|
||||
endif()
|
||||
|
||||
# When CCP4 is sourced in the environment, we can recreate the symmetry operations table
|
||||
if(EXISTS "${CCP4}")
|
||||
if(CIFPP_RECREATE_SYMOP_DATA AND NOT EXISTS "${CLIBD}/syminfo.lib")
|
||||
message(WARNING "Symop data table recreation requested, but file syminfo.lib was not found in ${CLIBD}")
|
||||
set(CIFPP_RECREATE_SYMOP_DATA OFF)
|
||||
else()
|
||||
option(CIFPP_RECREATE_SYMOP_DATA "Recreate SymOp data table in case it is out of date" ON)
|
||||
endif()
|
||||
else()
|
||||
set(CIFPP_RECREATE_SYMOP_DATA OFF)
|
||||
message("Not trying to recreate SymOpTable_data.hpp since CCP4 is not defined")
|
||||
endif()
|
||||
|
||||
# set(CMAKE_DEBUG_POSTFIX d)
|
||||
|
||||
if(MSVC)
|
||||
# make msvc standards compliant...
|
||||
add_compile_options(/permissive-)
|
||||
|
||||
macro(get_WIN32_WINNT version)
|
||||
if (WIN32 AND CMAKE_SYSTEM_VERSION)
|
||||
set(ver ${CMAKE_SYSTEM_VERSION})
|
||||
string(REPLACE "." "" ver ${ver})
|
||||
string(REGEX REPLACE "([0-9])" "0\\1" ver ${ver})
|
||||
|
||||
set(${version} "0x${ver}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
get_WIN32_WINNT(ver)
|
||||
add_definitions(-D_WIN32_WINNT=${ver})
|
||||
|
||||
# On Windows, do not install in the system location
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND NOT BUILD_FOR_CCP4)
|
||||
message(STATUS "The library and auxiliary files will be installed in $ENV{LOCALAPPDATA}/${PROJECT_NAME}")
|
||||
set(CMAKE_INSTALL_PREFIX "$ENV{LOCALAPPDATA}/${PROJECT_NAME}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT BUILD_FOR_CCP4 AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
# On Linux, install in the $HOME/.local folder by default
|
||||
message(STATUS "The library and auxiliary files will be installed in $ENV{HOME}/.local")
|
||||
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
# Optionally use mrc to create resources
|
||||
|
||||
if(WIN32 AND BUILD_SHARED_LIBS)
|
||||
message("Not using resources when building shared libraries for Windows")
|
||||
else()
|
||||
find_package(Mrc)
|
||||
|
||||
if(MRC_FOUND)
|
||||
option(USE_RSRC "Use mrc to create resources" ON)
|
||||
else()
|
||||
message(WARNING "Not using resources since mrc was not found")
|
||||
endif()
|
||||
|
||||
if(CIFPP_USE_RSRC STREQUAL "ON")
|
||||
set(CIFPP_USE_RSRC 1)
|
||||
|
||||
message("Using resources compiled with ${MRC}")
|
||||
add_compile_definitions(CIFPP_USE_RSRC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Libraries
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG)
|
||||
find_package(Threads)
|
||||
|
||||
find_package(Boost 1.70.0 REQUIRED COMPONENTS system iostreams regex program_options)
|
||||
|
||||
if(NOT MSVC AND Boost_USE_STATIC_LIBS)
|
||||
find_package(ZLIB REQUIRED)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ZLIB::ZLIB)
|
||||
endif()
|
||||
|
||||
include(FindFilesystem)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
|
||||
|
||||
include(FindAtomic)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
|
||||
|
||||
# Create a revision file, containing the current git version info
|
||||
include(VersionString)
|
||||
write_version_header("LibCIFPP")
|
||||
|
||||
# SymOp data table
|
||||
if(CIFPP_RECREATE_SYMOP_DATA)
|
||||
# The tool to create the table
|
||||
|
||||
add_executable(symop-map-generator "${CMAKE_SOURCE_DIR}/tools/symop-map-generator.cpp")
|
||||
|
||||
target_link_libraries(symop-map-generator Threads::Threads ${Boost_LIBRARIES} ${CIFPP_REQUIRED_LIBRARIES})
|
||||
if(Boost_INCLUDE_DIR)
|
||||
target_include_directories(symop-map-generator PUBLIC ${Boost_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
set($ENV{CLIBD} ${CLIBD})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/src/SymOpTable_data.hpp
|
||||
COMMAND $<TARGET_FILE:symop-map-generator> ${CLIBD}/syminfo.lib ${CMAKE_SOURCE_DIR}/src/SymOpTable_data.hpp
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/src/SymOpTable_data.hpp
|
||||
DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Sources
|
||||
|
||||
set(project_sources
|
||||
${PROJECT_SOURCE_DIR}/src/AtomType.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/BondMap.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Cif++.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Cif2PDB.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/CifParser.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/CifUtils.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/CifValidator.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Compound.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/PDB2Cif.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/PDB2CifRemark3.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Point.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Secondary.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Structure.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Symmetry.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/TlsParser.cpp
|
||||
)
|
||||
|
||||
set(project_headers
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/AtomType.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/BondMap.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Cif++.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Cif2PDB.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/CifParser.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/CifUtils.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/CifValidator.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Compound.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/PDB2Cif.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/PDB2CifRemark3.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Point.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Secondary.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Structure.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/Symmetry.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/TlsParser.hpp
|
||||
)
|
||||
|
||||
add_library(cifpp ${project_sources} ${project_headers} ${CMAKE_SOURCE_DIR}/src/SymOpTable_data.hpp)
|
||||
set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_include_directories(cifpp
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
${Boost_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_include_directories(cifpp
|
||||
PRIVATE
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(cifpp PUBLIC Threads::Threads Boost::regex Boost::iostreams ${CIFPP_REQUIRED_LIBRARIES})
|
||||
# target_link_libraries(cifpp PRIVATE)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
target_link_options(cifpp PRIVATE -undefined dynamic_lookup)
|
||||
endif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
|
||||
option(CIFPP_DOWNLOAD_CCD "Download the CCD file components.cif during installation" OFF)
|
||||
if(CIFPP_DOWNLOAD_CCD)
|
||||
# download the components.cif file from CCD
|
||||
set(COMPONENTS_CIF ${PROJECT_SOURCE_DIR}/data/components.cif)
|
||||
|
||||
if (NOT EXISTS ${COMPONENTS_CIF})
|
||||
|
||||
if (NOT EXISTS ${PROJECT_SOURCE_DIR}/data)
|
||||
file(MAKE_DIRECTORY ${PROJECT_SOURCE_DIR}/data/)
|
||||
endif()
|
||||
|
||||
find_program(GUNZIP gunzip)
|
||||
|
||||
if(GUNZIP)
|
||||
file(DOWNLOAD ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz ${COMPONENTS_CIF}.gz
|
||||
SHOW_PROGRESS)
|
||||
add_custom_command(OUTPUT ${COMPONENTS_CIF}
|
||||
COMMAND ${GUNZIP} ${COMPONENTS_CIF}.gz
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/data/)
|
||||
else()
|
||||
file(DOWNLOAD ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif ${COMPONENTS_CIF}
|
||||
SHOW_PROGRESS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
option(CIFPP_INSTALL_UPDATE_SCRIPT "Install the script to update CCD and dictionary files" OFF)
|
||||
set(CIFPP_CACHE_DIR "/var/cache/libcifpp" CACHE STRING "The cache directory to use")
|
||||
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
|
||||
endif()
|
||||
|
||||
generate_export_header(cifpp
|
||||
EXPORT_FILE_NAME cif++/Cif++Export.hpp)
|
||||
|
||||
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} )
|
||||
set(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} )
|
||||
set(SHARE_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/libcifpp)
|
||||
|
||||
set(CIFPP_DATA_DIR "${CMAKE_INSTALL_PREFIX}/${SHARE_INSTALL_DIR}" CACHE STRING "The directory containing the provided data files")
|
||||
|
||||
target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}")
|
||||
|
||||
# Install rules
|
||||
|
||||
install(TARGETS cifpp
|
||||
EXPORT cifppTargets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
if(MSVC AND BUILD_SHARED_LIBS)
|
||||
install(
|
||||
FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OPTIONAL)
|
||||
endif()
|
||||
|
||||
install(EXPORT cifppTargets
|
||||
FILE "cifppTargets.cmake"
|
||||
NAMESPACE cifpp::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY include/cif++
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/cif++/Cif++Export.hpp"
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cif++
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install(FILES
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx_v50.dic
|
||||
${COMPONENTS_CIF}
|
||||
DESTINATION ${SHARE_INSTALL_DIR}
|
||||
)
|
||||
|
||||
configure_package_config_file(Config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
|
||||
PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR SHARE_INSTALL_DIR
|
||||
)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
set(cifpp_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR})
|
||||
set_target_properties(cifpp PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${cifpp_MAJOR_VERSION}
|
||||
INTERFACE_cifpp_MAJOR_VERSION ${cifpp_MAJOR_VERSION})
|
||||
|
||||
set_property(TARGET cifpp APPEND PROPERTY
|
||||
COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
|
||||
# pkgconfig support
|
||||
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libcifpp.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc.in @ONLY)
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc.in)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
||||
# Unit tests
|
||||
|
||||
option(CIFPP_BUILD_TESTS "Build test exectuables" OFF)
|
||||
|
||||
if(CIFPP_BUILD_TESTS)
|
||||
|
||||
list(APPEND CIFPP_tests
|
||||
# pdb2cif
|
||||
rename-compound
|
||||
structure
|
||||
sugar
|
||||
unit)
|
||||
|
||||
foreach(CIFPP_TEST IN LISTS CIFPP_tests)
|
||||
set(CIFPP_TEST "${CIFPP_TEST}-test")
|
||||
set(CIFPP_TEST_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/test/${CIFPP_TEST}.cpp")
|
||||
|
||||
add_executable(${CIFPP_TEST} ${CIFPP_TEST_SOURCE})
|
||||
|
||||
target_include_directories(${CIFPP_TEST} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_BINARY_DIR} # for config.h
|
||||
)
|
||||
|
||||
target_link_libraries(${CIFPP_TEST} PRIVATE Threads::Threads cifpp )
|
||||
|
||||
if(CIFPP_USE_RSRC)
|
||||
mrc_target_resources(${CIFPP_TEST} ${CMAKE_SOURCE_DIR}/rsrc/mmcif_pdbx_v50.dic)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Specify unwind semantics so that MSVC knowns how to handle exceptions
|
||||
target_compile_options(${CIFPP_TEST} PRIVATE /EHsc)
|
||||
endif()
|
||||
|
||||
add_custom_target("run-${CIFPP_TEST}" DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch ${CIFPP_TEST})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch
|
||||
COMMAND $<TARGET_FILE:${CIFPP_TEST}> -- ${CMAKE_SOURCE_DIR}/test)
|
||||
|
||||
add_test(NAME ${CIFPP_TEST}
|
||||
COMMAND $<TARGET_FILE:${CIFPP_TEST}> -- ${CMAKE_SOURCE_DIR}/test)
|
||||
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
message("Will install in ${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
# Optionally install the update scripts for CCD and dictionary files
|
||||
|
||||
if(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
set(CIFPP_CRON_DIR "$ENV{DESTDIR}/etc/cron.weekly")
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/tools/update-libcifpp-data.in update-libcifpp-data @ONLY)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
|
||||
DESTINATION ${CIFPP_CRON_DIR}
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
|
||||
)
|
||||
|
||||
install(DIRECTORY DESTINATION ${CIFPP_CACHE_DIR})
|
||||
install(DIRECTORY DESTINATION "$ENV{DESTDIR}/etc/libcifpp/cache-update.d")
|
||||
|
||||
# a config to, to make it complete
|
||||
if(NOT EXISTS "$ENV{DESTDIR}/etc/libcifpp.conf")
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf [[# Uncomment the next line to enable automatic updates
|
||||
# update=true
|
||||
]])
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf DESTINATION "$ENV{DESTDIR}/etc")
|
||||
install(CODE "message(\"A configuration file has been written to $ENV{DESTDIR}/etc/libcifpp.conf, please edit this file to enable automatic updates\")")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
|
||||
endif()
|
||||
|
||||
16
Config.cmake.in
Normal file
16
Config.cmake.in
Normal file
@@ -0,0 +1,16 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Threads)
|
||||
find_dependency(Boost 1.70.0 REQUIRED COMPONENTS system iostreams regex)
|
||||
if(NOT WIN32)
|
||||
find_dependency(ZLIB)
|
||||
endif()
|
||||
|
||||
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
|
||||
|
||||
set_and_check(CIFPP_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
set_and_check(CIFPP_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@")
|
||||
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_SHARE_INSTALL_DIR@")
|
||||
|
||||
check_required_components(cifpp)
|
||||
23
LICENSE
Normal file
23
LICENSE
Normal file
@@ -0,0 +1,23 @@
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
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
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
libcifpp
|
||||
========
|
||||
|
||||
This library contains code to work with mmCIF and PDB files.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
The code for this library was written in C++17. You therefore need a
|
||||
recent compiler to build it. For the development gcc 9.3 and clang 9.0
|
||||
have been used as well as MSVC version 2019.
|
||||
|
||||
Other requirements are:
|
||||
|
||||
- Boost libraries, at least version 1.70
|
||||
- [mrc](https://github.com/mhekkel/mrc), a resource compiler that
|
||||
allows including data files into the executable making them easier to
|
||||
install. Strictly this is optional, but at the expense of functionality.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
This library uses [cmake](https://cmake.org). The usual way of building
|
||||
and installing is to create a `build` directory and run cmake there.
|
||||
|
||||
On linux e.g. you would issue the following commands:
|
||||
|
||||
```
|
||||
git clone https://github.com/PDB-REDO/libcifpp.git
|
||||
cd libcifpp
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
ctest -C Release
|
||||
cmake --install .
|
||||
```
|
||||
This checks out the source code from github, creates a new directory
|
||||
where cmake stores its files. Run a configure, build the code and run
|
||||
tests. And then it installs the library and auxiliary files.
|
||||
|
||||
The default is to install everything in `$HOME/.local` on Linux and
|
||||
`%LOCALAPPDATA%` on Windows (the AppData/Local folder in your home directory).
|
||||
You can change this by specifying the prefix with the
|
||||
[CMAKE_INSTALL_PREFIX](https://cmake.org/cmake/help/v3.21/variable/CMAKE_INSTALL_PREFIX.html)
|
||||
variable.
|
||||
|
||||
69
changelog
Normal file
69
changelog
Normal file
@@ -0,0 +1,69 @@
|
||||
Version 4.0.0
|
||||
- getResidue in mmcif::Structure now requires both a
|
||||
sequence ID and an auth sequence ID. As a result the code was cleaned
|
||||
up considerably.
|
||||
|
||||
Version 3.0.5
|
||||
- mmcif::Structure redesign. It is now a wrapper around a cif::Datablock.
|
||||
|
||||
Version 3.0.4
|
||||
- Fix in mmCIF parser, now correctly handles the unquoted
|
||||
string ??
|
||||
|
||||
Version 3.0.3
|
||||
- Better configuration checks, for atomic e.g.
|
||||
- Fixed a problem introduced in refactoring mmcif::Atom
|
||||
- Version string creation
|
||||
|
||||
Version 3.0.2
|
||||
- refactored mmcif::Atom for performance reasons
|
||||
|
||||
Version 3.0.1
|
||||
- Fixed processing of proline restraints file from CCP4, proline
|
||||
is a peptide, really.
|
||||
- Added code to facilitate DSSP
|
||||
|
||||
Version 3.0.0
|
||||
- Replaced many strings in the API with string_view for
|
||||
performance reasons.
|
||||
- Upgraded mmcif::Structure
|
||||
- various other small fixes
|
||||
|
||||
Version 2.0.5
|
||||
- Backporting updated CMakeLists.txt file
|
||||
|
||||
Version 2.0.4
|
||||
- Reverted a too strict test when reading cif files.
|
||||
|
||||
Version 2.0.3
|
||||
- Fixed reading mmCIF files where model numbers are used and
|
||||
model number 1 is missing.
|
||||
|
||||
Version 2.0.2
|
||||
- Added configuration flag to disable downloading CCD data during build
|
||||
Note that there are now two flags for CCD data:
|
||||
DOWNLOAD_CCD to enable downloading during build
|
||||
INSTALL_UPDATE_SCRIPT to install an update mechanism for this file
|
||||
- Updated unit tests to work even if no CCD data is available
|
||||
|
||||
Version 2.0.1
|
||||
- Fixed the generator for the symmetry operator table
|
||||
|
||||
Version 2.0.0
|
||||
- New API interface for accessing query results
|
||||
- Removed bzip2 support
|
||||
- improved makefiles
|
||||
|
||||
Version 1.1.1
|
||||
- Now with full support for MS Windows
|
||||
|
||||
Version 1.1.0
|
||||
- Changed from GNU configure to CMake.
|
||||
- Loading compound information from CCD file
|
||||
|
||||
Version 1.0.1
|
||||
- Changed the way resources are looked up, local dir first,
|
||||
then /var/cache and finally compiled in resources (with mrc).
|
||||
|
||||
Version 1.0.0
|
||||
- First public release
|
||||
64
cmake/FindAtomic.cmake
Normal file
64
cmake/FindAtomic.cmake
Normal file
@@ -0,0 +1,64 @@
|
||||
# Simple check to see if we need a library for std::atomic
|
||||
|
||||
if(TARGET std::atomic)
|
||||
return()
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckCXXSourceRuns)
|
||||
|
||||
cmake_push_check_state()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
check_include_file_cxx("atomic" _CXX_ATOMIC_HAVE_HEADER)
|
||||
mark_as_advanced(_CXX_ATOMIC_HAVE_HEADER)
|
||||
|
||||
set(code [[
|
||||
#include <atomic>
|
||||
int main(int argc, char** argv) {
|
||||
std::atomic<long long> s;
|
||||
++s;
|
||||
return 0;
|
||||
}
|
||||
]])
|
||||
|
||||
check_cxx_source_runs("${code}" _CXX_ATOMIC_BUILTIN)
|
||||
|
||||
if(_CXX_ATOMIC_BUILTIN)
|
||||
set(_found 1)
|
||||
else()
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
|
||||
list(APPEND FOLLY_LINK_LIBRARIES atomic)
|
||||
|
||||
check_cxx_source_runs("${code}" _CXX_ATOMIC_LIB_NEEDED)
|
||||
if (NOT _CXX_ATOMIC_LIB_NEEDED)
|
||||
message(FATAL_ERROR "unable to link C++ std::atomic code: you may need \
|
||||
to install GNU libatomic")
|
||||
else()
|
||||
set(_found 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_found)
|
||||
add_library(std::atomic INTERFACE IMPORTED)
|
||||
set_property(TARGET std::atomic APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_14)
|
||||
|
||||
if(_CXX_ATOMIC_BUILTIN)
|
||||
# Nothing to add...
|
||||
elseif(_CXX_ATOMIC_LIB_NEEDED)
|
||||
set_target_properties(std::atomic PROPERTIES IMPORTED_LIBNAME atomic)
|
||||
set(STDCPPATOMIC_LIBRARY atomic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
set(Atomic_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::atomic" FORCE)
|
||||
|
||||
if(Atomic_FIND_REQUIRED AND NOT Atomic_FOUND)
|
||||
message(FATAL_ERROR "Cannot run simple program using std::atomic")
|
||||
endif()
|
||||
76
cmake/FindFilesystem.cmake
Normal file
76
cmake/FindFilesystem.cmake
Normal file
@@ -0,0 +1,76 @@
|
||||
# Simplistic reimplementation of https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake
|
||||
|
||||
if(TARGET std::filesystem)
|
||||
return()
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
cmake_push_check_state()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
|
||||
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||
|
||||
set(code [[
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
|
||||
int main() {
|
||||
auto cwd = std::filesystem::current_path();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
]])
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 8.4.0)
|
||||
# >> https://stackoverflow.com/questions/63902528/program-crashes-when-filesystempath-is-destroyed
|
||||
set(CXX_FILESYSTEM_NO_LINK_NEEDED 0)
|
||||
else()
|
||||
# Check a simple filesystem program without any linker flags
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
endif()
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
set(_found 1)
|
||||
else()
|
||||
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
|
||||
# Add the libstdc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set(_found ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
|
||||
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
# Try the libc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set(_found ${CXX_FILESYSTEM_CPPFS_NEEDED})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_found)
|
||||
add_library(std::filesystem INTERFACE IMPORTED)
|
||||
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
# Nothing to add...
|
||||
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME stdc++fs)
|
||||
set(STDCPPFS_LIBRARY stdc++fs)
|
||||
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME c++fs)
|
||||
set(STDCPPFS_LIBRARY c++fs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
|
||||
|
||||
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
|
||||
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
||||
endif()
|
||||
|
||||
284
cmake/GetGitRevisionDescription.cmake
Normal file
284
cmake/GetGitRevisionDescription.cmake
Normal file
@@ -0,0 +1,284 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the working tree (--dirty option),
|
||||
# and adjusting the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
#
|
||||
# Copyright 2009-2013, Iowa State University.
|
||||
# Copyright 2013-2020, Ryan Pavlik
|
||||
# Copyright 2013-2020, Contributors
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||
# that is part of any directory in the path defined by _start_dir.
|
||||
# The result is returned in the parent scope variable whose name is passed
|
||||
# as variable _git_dir_var. If no .git directory can be found, the
|
||||
# function returns an empty string via _git_dir_var.
|
||||
#
|
||||
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||
# neither foo nor bar contain a file/directory .git. This wil return
|
||||
# C:/bla/.git
|
||||
#
|
||||
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||
set(cur_dir "${_start_dir}")
|
||||
set(git_dir "${_start_dir}/.git")
|
||||
while(NOT EXISTS "${git_dir}")
|
||||
# .git dir not found, search parent directories
|
||||
set(git_previous_parent "${cur_dir}")
|
||||
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||
if(cur_dir STREQUAL git_previous_parent)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_git_dir_var}
|
||||
""
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(git_dir "${cur_dir}/.git")
|
||||
endwhile()
|
||||
set(${_git_dir_var}
|
||||
"${git_dir}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||
|
||||
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
|
||||
else()
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
|
||||
endif()
|
||||
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||
"${GIT_DIR}")
|
||||
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||||
# We've gone above the CMake root dir.
|
||||
set(GIT_DIR "")
|
||||
endif()
|
||||
endif()
|
||||
if("${GIT_DIR}" STREQUAL "")
|
||||
set(${_refspecvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if the current source dir is a git submodule or a worktree.
|
||||
# In both cases .git is a file instead of a directory.
|
||||
#
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
# The following git command will return a non empty string that
|
||||
# points to the super project working tree if the current
|
||||
# source dir is inside a git submodule.
|
||||
# Otherwise the command will return an empty string.
|
||||
#
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||
--show-superproject-working-tree
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT "${out}" STREQUAL "")
|
||||
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||
${submodule})
|
||||
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||
ABSOLUTE)
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
else()
|
||||
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||
file(READ ${GIT_DIR} worktree_ref)
|
||||
# The .git directory contains a path to the worktree information directory
|
||||
# inside the parent git repo of the worktree.
|
||||
#
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||
${worktree_ref})
|
||||
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||
endif()
|
||||
else()
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar}
|
||||
"${HEAD_REF}"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"${HEAD_HASH}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe_working_tree _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var}
|
||||
"CLEAN"
|
||||
PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var}
|
||||
"DIRTY"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
43
cmake/GetGitRevisionDescription.cmake.in
Normal file
43
cmake/GetGitRevisionDescription.cmake.in
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright 2009-2012, Iowa State University
|
||||
# Copyright 2011-2015, Contributors
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
77
cmake/VersionString.cmake
Normal file
77
cmake/VersionString.cmake
Normal file
@@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# 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
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# Create a revision file, containing the current git version info, if any
|
||||
function(write_version_header)
|
||||
include(GetGitRevisionDescription)
|
||||
if(NOT(GIT-NOTFOUND OR HEAD-HASH-NOTFOUND))
|
||||
git_describe_working_tree(BUILD_VERSION_STRING --match=build --dirty)
|
||||
|
||||
if(BUILD_VERSION_STRING MATCHES "build-([0-9]+)-g([0-9a-f]+)(-dirty)?")
|
||||
set(BUILD_GIT_TAGREF "${CMAKE_MATCH_2}")
|
||||
if(CMAKE_MATCH_3)
|
||||
set(BUILD_VERSION_STRING "${CMAKE_MATCH_1}*")
|
||||
else()
|
||||
set(BUILD_VERSION_STRING "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(BUILD_VERSION_STRING "no git info available")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_BINARY_DIR} PRIVATE)
|
||||
string(TIMESTAMP BUILD_DATE_TIME "%Y-%m-%dT%H:%M:%SZ" UTC)
|
||||
|
||||
if(ARGC GREATER 0)
|
||||
set(VAR_PREFIX "${ARGV0}")
|
||||
endif()
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/revision.hpp.in" [[// Generated revision file
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
|
||||
const char k@VAR_PREFIX@ProjectName[] = "@PROJECT_NAME@";
|
||||
const char k@VAR_PREFIX@VersionNumber[] = "@PROJECT_VERSION@";
|
||||
const char k@VAR_PREFIX@VersionGitTag[] = "@BUILD_GIT_TAGREF@";
|
||||
const char k@VAR_PREFIX@BuildInfo[] = "@BUILD_VERSION_STRING@";
|
||||
const char k@VAR_PREFIX@BuildDate[] = "@BUILD_DATE_TIME@";
|
||||
|
||||
inline void write_version_string(std::ostream &os, bool verbose)
|
||||
{
|
||||
os << k@VAR_PREFIX@ProjectName << " version " << k@VAR_PREFIX@VersionNumber << std::endl;
|
||||
if (verbose)
|
||||
{
|
||||
os << "build: " << k@VAR_PREFIX@BuildInfo << ' ' << k@VAR_PREFIX@BuildDate << std::endl;
|
||||
if (k@VAR_PREFIX@VersionGitTag[0] != 0)
|
||||
os << "git tag: " << k@VAR_PREFIX@VersionGitTag << std::endl;
|
||||
}
|
||||
}
|
||||
]])
|
||||
configure_file("${CMAKE_BINARY_DIR}/revision.hpp.in" "${CMAKE_BINARY_DIR}/revision.hpp" @ONLY)
|
||||
endfunction()
|
||||
|
||||
2582
data/ccd-subset.cif
Normal file
2582
data/ccd-subset.cif
Normal file
File diff suppressed because it is too large
Load Diff
BIN
examples/1cbs.cif.gz
Normal file
BIN
examples/1cbs.cif.gz
Normal file
Binary file not shown.
31
examples/example.cpp
Normal file
31
examples/example.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
|
||||
#include <cif++/Cif++.hpp>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
int main()
|
||||
{
|
||||
fs::path in("1cbs.cif.gz");
|
||||
|
||||
cif::File file;
|
||||
|
||||
file.loadDictionary("mmcif_pdbx_v50");
|
||||
|
||||
file.load("1cbs.cif.gz");
|
||||
|
||||
auto& db = file.firstDatablock()["atom_site"];
|
||||
auto n = db.find(cif::Key("label_atom_id") == "OXT").size();
|
||||
|
||||
std::cout << "File contains " << db.size() << " atoms of which " << n << (n == 1 ? " is" : " are") << " OXT" << std::endl
|
||||
<< "residues with an OXT are:" << std::endl;
|
||||
|
||||
for (const auto& [asym, comp, seqnr]: db.find<std::string,std::string,int>(
|
||||
cif::Key("label_atom_id") == "OXT", "label_asym_id", "label_comp_id", "label_seq_id"))
|
||||
{
|
||||
std::cout << asym << ' ' << comp << ' ' << seqnr << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
examples/makefile
Normal file
8
examples/makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
CXX = c++ -std=c++17
|
||||
CXXFLAGS = $(shell pkg-config --cflags libcifpp)
|
||||
LIBS = $(shell pkg-config --libs libcifpp)
|
||||
|
||||
all: example
|
||||
|
||||
example: example.cpp
|
||||
$(CXX) -o $@ $? $(CXXFLAGS) $(LIBS)
|
||||
277
include/cif++/AtomType.hpp
Normal file
277
include/cif++/AtomType.hpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Lib for working with structures as contained in mmCIF and PDB files
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
enum AtomType : uint8_t
|
||||
{
|
||||
Nn = 0, // Unknown
|
||||
|
||||
H = 1, // Hydrogen
|
||||
He = 2, // Helium
|
||||
|
||||
Li = 3, // Lithium
|
||||
Be = 4, // Beryllium
|
||||
B = 5, // Boron
|
||||
C = 6, // Carbon
|
||||
N = 7, // Nitrogen
|
||||
O = 8, // Oxygen
|
||||
F = 9, // Fluorine
|
||||
Ne = 10, // Neon
|
||||
|
||||
Na = 11, // Sodium
|
||||
Mg = 12, // Magnesium
|
||||
Al = 13, // Aluminium
|
||||
Si = 14, // Silicon
|
||||
P = 15, // Phosphorus
|
||||
S = 16, // Sulfur
|
||||
Cl = 17, // Chlorine
|
||||
Ar = 18, // Argon
|
||||
|
||||
K = 19, // Potassium
|
||||
Ca = 20, // Calcium
|
||||
Sc = 21, // Scandium
|
||||
Ti = 22, // Titanium
|
||||
V = 23, // Vanadium
|
||||
Cr = 24, // Chromium
|
||||
Mn = 25, // Manganese
|
||||
Fe = 26, // Iron
|
||||
Co = 27, // Cobalt
|
||||
Ni = 28, // Nickel
|
||||
Cu = 29, // Copper
|
||||
Zn = 30, // Zinc
|
||||
Ga = 31, // Gallium
|
||||
Ge = 32, // Germanium
|
||||
As = 33, // Arsenic
|
||||
Se = 34, // Selenium
|
||||
Br = 35, // Bromine
|
||||
Kr = 36, // Krypton
|
||||
|
||||
Rb = 37, // Rubidium
|
||||
Sr = 38, // Strontium
|
||||
Y = 39, // Yttrium
|
||||
Zr = 40, // Zirconium
|
||||
Nb = 41, // Niobium
|
||||
Mo = 42, // Molybdenum
|
||||
Tc = 43, // Technetium
|
||||
Ru = 44, // Ruthenium
|
||||
Rh = 45, // Rhodium
|
||||
Pd = 46, // Palladium
|
||||
Ag = 47, // Silver
|
||||
Cd = 48, // Cadmium
|
||||
In = 49, // Indium
|
||||
Sn = 50, // Tin
|
||||
Sb = 51, // Antimony
|
||||
Te = 52, // Tellurium
|
||||
I = 53, // Iodine
|
||||
Xe = 54, // Xenon
|
||||
Cs = 55, // Caesium
|
||||
Ba = 56, // Barium
|
||||
La = 57, // Lanthanum
|
||||
|
||||
Hf = 72, // Hafnium
|
||||
Ta = 73, // Tantalum
|
||||
W = 74, // Tungsten
|
||||
Re = 75, // Rhenium
|
||||
Os = 76, // Osmium
|
||||
Ir = 77, // Iridium
|
||||
Pt = 78, // Platinum
|
||||
Au = 79, // Gold
|
||||
Hg = 80, // Mercury
|
||||
Tl = 81, // Thallium
|
||||
Pb = 82, // Lead
|
||||
Bi = 83, // Bismuth
|
||||
Po = 84, // Polonium
|
||||
At = 85, // Astatine
|
||||
Rn = 86, // Radon
|
||||
Fr = 87, // Francium
|
||||
Ra = 88, // Radium
|
||||
Ac = 89, // Actinium
|
||||
|
||||
Rf = 104, // Rutherfordium
|
||||
Db = 105, // Dubnium
|
||||
Sg = 106, // Seaborgium
|
||||
Bh = 107, // Bohrium
|
||||
Hs = 108, // Hassium
|
||||
Mt = 109, // Meitnerium
|
||||
Ds = 110, // Darmstadtium
|
||||
Rg = 111, // Roentgenium
|
||||
Cn = 112, // Copernicium
|
||||
Nh = 113, // Nihonium
|
||||
Fl = 114, // Flerovium
|
||||
Mc = 115, // Moscovium
|
||||
Lv = 116, // Livermorium
|
||||
Ts = 117, // Tennessine
|
||||
Og = 118, // Oganesson
|
||||
|
||||
Ce = 58, // Cerium
|
||||
Pr = 59, // Praseodymium
|
||||
Nd = 60, // Neodymium
|
||||
Pm = 61, // Promethium
|
||||
Sm = 62, // Samarium
|
||||
Eu = 63, // Europium
|
||||
Gd = 64, // Gadolinium
|
||||
Tb = 65, // Terbium
|
||||
Dy = 66, // Dysprosium
|
||||
Ho = 67, // Holmium
|
||||
Er = 68, // Erbium
|
||||
Tm = 69, // Thulium
|
||||
Yb = 70, // Ytterbium
|
||||
Lu = 71, // Lutetium
|
||||
|
||||
Th = 90, // Thorium
|
||||
Pa = 91, // Protactinium
|
||||
U = 92, // Uranium
|
||||
Np = 93, // Neptunium
|
||||
Pu = 94, // Plutonium
|
||||
Am = 95, // Americium
|
||||
Cm = 96, // Curium
|
||||
Bk = 97, // Berkelium
|
||||
Cf = 98, // Californium
|
||||
Es = 99, // Einsteinium
|
||||
Fm = 100, // Fermium
|
||||
Md = 101, // Mendelevium
|
||||
No = 102, // Nobelium
|
||||
Lr = 103, // Lawrencium
|
||||
|
||||
D = 129, // Deuterium
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// AtomTypeInfo
|
||||
|
||||
enum class RadiusType
|
||||
{
|
||||
Calculated,
|
||||
Empirical,
|
||||
CovalentEmpirical,
|
||||
|
||||
SingleBond,
|
||||
DoubleBond,
|
||||
TripleBond,
|
||||
|
||||
VanderWaals,
|
||||
|
||||
TypeCount
|
||||
};
|
||||
|
||||
constexpr size_t RadiusTypeCount = static_cast<size_t>(RadiusType::TypeCount);
|
||||
|
||||
enum class IonicRadiusType
|
||||
{
|
||||
Effective, Crystal
|
||||
};
|
||||
|
||||
struct AtomTypeInfo
|
||||
{
|
||||
AtomType type;
|
||||
std::string name;
|
||||
std::string symbol;
|
||||
float weight;
|
||||
bool metal;
|
||||
float radii[RadiusTypeCount];
|
||||
};
|
||||
|
||||
extern const AtomTypeInfo kKnownAtoms[];
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// AtomTypeTraits
|
||||
|
||||
class AtomTypeTraits
|
||||
{
|
||||
public:
|
||||
AtomTypeTraits(AtomType a);
|
||||
AtomTypeTraits(const std::string &symbol);
|
||||
|
||||
AtomType type() const { return mInfo->type; }
|
||||
std::string name() const { return mInfo->name; }
|
||||
std::string symbol() const { return mInfo->symbol; }
|
||||
float weight() const { return mInfo->weight; }
|
||||
|
||||
bool isMetal() const { return mInfo->metal; }
|
||||
|
||||
static bool isElement(const std::string &symbol);
|
||||
static bool isMetal(const std::string &symbol);
|
||||
|
||||
float radius(RadiusType type = RadiusType::SingleBond) const
|
||||
{
|
||||
if (type >= RadiusType::TypeCount)
|
||||
throw std::invalid_argument("invalid radius requested");
|
||||
return mInfo->radii[static_cast<size_t>(type)] / 100.f;
|
||||
}
|
||||
|
||||
/// \brief Return the radius for a charged version of this atom in a solid crystal
|
||||
///
|
||||
/// \param charge The charge of the ion
|
||||
/// \return The radius of the ion
|
||||
float crystal_ionic_radius(int charge) const;
|
||||
|
||||
/// \brief Return the radius for a charged version of this atom in a non-solid environment
|
||||
///
|
||||
/// \param charge The charge of the ion
|
||||
/// \return The radius of the ion
|
||||
float effective_ionic_radius(int charge) const;
|
||||
|
||||
/// \brief Return the radius for a charged version of this atom, returns the effective radius by default
|
||||
///
|
||||
/// \param charge The charge of the ion
|
||||
/// \return The radius of the ion
|
||||
float ionic_radius(int charge, IonicRadiusType type = IonicRadiusType::Effective) const
|
||||
{
|
||||
return type == IonicRadiusType::Effective ? effective_ionic_radius(charge) : crystal_ionic_radius(charge);
|
||||
}
|
||||
|
||||
// data type encapsulating the Waasmaier & Kirfel scattering factors
|
||||
// in a simplified form (only a and b).
|
||||
// Added the electrion scattering factors as well
|
||||
struct SFData
|
||||
{
|
||||
double a[6], b[6];
|
||||
};
|
||||
|
||||
// to get the Cval and Siva values, use this constant as charge:
|
||||
enum
|
||||
{
|
||||
kWKSFVal = -99
|
||||
};
|
||||
|
||||
const SFData &wksf(int charge = 0) const;
|
||||
const SFData &elsf() const;
|
||||
|
||||
private:
|
||||
const struct AtomTypeInfo *mInfo;
|
||||
};
|
||||
|
||||
} // namespace mmcif
|
||||
101
include/cif++/BondMap.hpp
Normal file
101
include/cif++/BondMap.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "cif++/Structure.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
class BondMapException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
BondMapException(const std::string &msg)
|
||||
: runtime_error(msg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class BondMap
|
||||
{
|
||||
public:
|
||||
BondMap(const Structure &p);
|
||||
|
||||
BondMap(const BondMap &) = delete;
|
||||
BondMap &operator=(const BondMap &) = delete;
|
||||
|
||||
bool operator()(const Atom &a, const Atom &b) const
|
||||
{
|
||||
return isBonded(index.at(a.id()), index.at(b.id()));
|
||||
}
|
||||
|
||||
bool is1_4(const Atom &a, const Atom &b) const
|
||||
{
|
||||
uint32_t ixa = index.at(a.id());
|
||||
uint32_t ixb = index.at(b.id());
|
||||
|
||||
return bond_1_4.count(key(ixa, ixb));
|
||||
}
|
||||
|
||||
// links coming from the struct_conn records:
|
||||
std::vector<std::string> linked(const Atom &a) const;
|
||||
|
||||
// This list of atomID's is comming from either CCD or the CCP4 dictionaries loaded
|
||||
static std::vector<std::string> atomIDsForCompound(const std::string &compoundID);
|
||||
|
||||
private:
|
||||
bool isBonded(uint32_t ai, uint32_t bi) const
|
||||
{
|
||||
return bond.count(key(ai, bi)) != 0;
|
||||
}
|
||||
|
||||
uint64_t key(uint32_t a, uint32_t b) const
|
||||
{
|
||||
if (a > b)
|
||||
std::swap(a, b);
|
||||
return static_cast<uint64_t>(a) | (static_cast<uint64_t>(b) << 32);
|
||||
}
|
||||
|
||||
std::tuple<uint32_t, uint32_t> dekey(uint64_t k) const
|
||||
{
|
||||
return std::make_tuple(
|
||||
static_cast<uint32_t>(k >> 32),
|
||||
static_cast<uint32_t>(k));
|
||||
}
|
||||
|
||||
uint32_t dim;
|
||||
std::unordered_map<std::string, uint32_t> index;
|
||||
std::set<uint64_t> bond, bond_1_4;
|
||||
|
||||
std::map<std::string, std::set<std::string>> link;
|
||||
};
|
||||
|
||||
} // namespace mmcif
|
||||
2444
include/cif++/Cif++.hpp
Normal file
2444
include/cif++/Cif++.hpp
Normal file
File diff suppressed because it is too large
Load Diff
39
include/cif++/Cif2PDB.hpp
Normal file
39
include/cif++/Cif2PDB.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
|
||||
void WritePDBFile(std::ostream& pdbFile, cif::File& cifFile);
|
||||
|
||||
/// \brief Just the HEADER, COMPND, SOURCE and AUTHOR lines
|
||||
void WritePDBHeaderLines(std::ostream& os, cif::File& cifFile);
|
||||
|
||||
std::string GetPDBHEADERLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
|
||||
std::string GetPDBCOMPNDLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
|
||||
std::string GetPDBSOURCELine(cif::File& cifFile, std::string::size_type truncate_at = 127);
|
||||
std::string GetPDBAUTHORLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
|
||||
233
include/cif++/CifParser.hpp
Normal file
233
include/cif++/CifParser.hpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class CifParserError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
CifParserError(uint32_t lineNr, const std::string &message);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
extern const uint32_t kMaxLineLength;
|
||||
|
||||
extern const uint8_t kCharTraitsTable[128];
|
||||
|
||||
enum CharTraitsMask : uint8_t
|
||||
{
|
||||
kOrdinaryMask = 1 << 0,
|
||||
kNonBlankMask = 1 << 1,
|
||||
kTextLeadMask = 1 << 2,
|
||||
kAnyPrintMask = 1 << 3
|
||||
};
|
||||
|
||||
inline bool isWhite(int ch)
|
||||
{
|
||||
return std::isspace(ch) or ch == '#';
|
||||
}
|
||||
|
||||
inline bool isOrdinary(int ch)
|
||||
{
|
||||
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kOrdinaryMask) != 0;
|
||||
}
|
||||
|
||||
inline bool isNonBlank(int ch)
|
||||
{
|
||||
return ch > 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kNonBlankMask) != 0;
|
||||
}
|
||||
|
||||
inline bool isTextLead(int ch)
|
||||
{
|
||||
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0;
|
||||
}
|
||||
|
||||
inline bool isAnyPrint(int ch)
|
||||
{
|
||||
return ch == '\t' or
|
||||
(ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0);
|
||||
}
|
||||
|
||||
bool isUnquotedString(const char *s);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
using DatablockIndex = std::map<std::string, std::size_t>;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// sac Parser, analogous to SAX Parser (simple api for xml)
|
||||
|
||||
class SacParser
|
||||
{
|
||||
public:
|
||||
SacParser(std::istream &is, bool init = true);
|
||||
virtual ~SacParser() {}
|
||||
|
||||
enum CIFToken
|
||||
{
|
||||
eCIFTokenUnknown,
|
||||
|
||||
eCIFTokenEOF,
|
||||
|
||||
eCIFTokenDATA,
|
||||
eCIFTokenLOOP,
|
||||
eCIFTokenGLOBAL,
|
||||
eCIFTokenSAVE,
|
||||
eCIFTokenSTOP,
|
||||
eCIFTokenTag,
|
||||
eCIFTokenValue,
|
||||
};
|
||||
|
||||
static const char *kTokenName[];
|
||||
|
||||
enum CIFValueType
|
||||
{
|
||||
eCIFValueInt,
|
||||
eCIFValueFloat,
|
||||
eCIFValueNumeric,
|
||||
eCIFValueString,
|
||||
eCIFValueTextField,
|
||||
eCIFValueInapplicable,
|
||||
eCIFValueUnknown
|
||||
};
|
||||
|
||||
static const char *kValueName[];
|
||||
|
||||
int getNextChar();
|
||||
|
||||
void retract();
|
||||
int restart(int start);
|
||||
|
||||
CIFToken getNextToken();
|
||||
void match(CIFToken token);
|
||||
|
||||
bool parseSingleDatablock(const std::string &datablock);
|
||||
|
||||
DatablockIndex indexDatablocks();
|
||||
bool parseSingleDatablock(const std::string &datablock, const DatablockIndex &index);
|
||||
|
||||
void parseFile();
|
||||
void parseGlobal();
|
||||
void parseDataBlock();
|
||||
|
||||
virtual void parseSaveFrame();
|
||||
|
||||
void parseDictionary();
|
||||
|
||||
void error(const std::string &msg);
|
||||
|
||||
// production methods, these are pure virtual here
|
||||
|
||||
virtual void produceDatablock(const std::string &name) = 0;
|
||||
virtual void produceCategory(const std::string &name) = 0;
|
||||
virtual void produceRow() = 0;
|
||||
virtual void produceItem(const std::string &category, const std::string &item, const std::string &value) = 0;
|
||||
|
||||
protected:
|
||||
enum State
|
||||
{
|
||||
eStateStart,
|
||||
eStateWhite,
|
||||
eStateComment,
|
||||
eStateQuestionMark,
|
||||
eStateDot,
|
||||
eStateQuotedString,
|
||||
eStateQuotedStringQuote,
|
||||
eStateUnquotedString,
|
||||
eStateTag,
|
||||
eStateTextField,
|
||||
eStateFloat = 100,
|
||||
eStateInt = 110,
|
||||
eStateValue = 300,
|
||||
eStateDATA,
|
||||
eStateSAVE
|
||||
};
|
||||
|
||||
std::istream &mData;
|
||||
|
||||
// Parser state
|
||||
bool mValidate;
|
||||
uint32_t mLineNr;
|
||||
bool mBol;
|
||||
CIFToken mLookahead;
|
||||
std::string mTokenValue;
|
||||
CIFValueType mTokenType;
|
||||
std::stack<int> mBuffer;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Parser : public SacParser
|
||||
{
|
||||
public:
|
||||
Parser(std::istream &is, File &f, bool init = true);
|
||||
|
||||
virtual void produceDatablock(const std::string &name);
|
||||
virtual void produceCategory(const std::string &name);
|
||||
virtual void produceRow();
|
||||
virtual void produceItem(const std::string &category, const std::string &item, const std::string &value);
|
||||
|
||||
protected:
|
||||
File &mFile;
|
||||
Datablock *mDataBlock;
|
||||
Datablock::iterator mCat;
|
||||
Row mRow;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class DictParser : public Parser
|
||||
{
|
||||
public:
|
||||
DictParser(Validator &validator, std::istream &is);
|
||||
~DictParser();
|
||||
|
||||
void loadDictionary();
|
||||
|
||||
private:
|
||||
virtual void parseSaveFrame();
|
||||
|
||||
bool collectItemTypes();
|
||||
void linkItems();
|
||||
|
||||
Validator &mValidator;
|
||||
File mFile;
|
||||
struct DictParserDataImpl *mImpl;
|
||||
bool mCollectedItemTypes = false;
|
||||
};
|
||||
|
||||
} // namespace cif
|
||||
235
include/cif++/CifUtils.hpp
Normal file
235
include/cif++/CifUtils.hpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
#include <io.h>
|
||||
#define isatty _isatty
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "cif++/Cif++Export.hpp"
|
||||
|
||||
#if _MSC_VER
|
||||
#pragma warning(disable : 4996) // unsafe function or variable (strcpy e.g.)
|
||||
#pragma warning(disable : 4068) // unknown pragma
|
||||
#pragma warning(disable : 4100) // unreferenced formal parameter
|
||||
#pragma warning(disable : 4101) // unreferenced local variable
|
||||
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING 1
|
||||
#endif
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
// the git 'build' number
|
||||
std::string get_version_nr();
|
||||
// std::string get_version_date();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// some basic utilities: Since we're using ASCII input only, we define for optimisation
|
||||
// our own case conversion routines.
|
||||
|
||||
bool iequals(std::string_view a, std::string_view b);
|
||||
int icompare(std::string_view a, std::string_view b);
|
||||
|
||||
bool iequals(const char *a, const char *b);
|
||||
int icompare(const char *a, const char *b);
|
||||
|
||||
void toLower(std::string &s);
|
||||
std::string toLowerCopy(const std::string &s);
|
||||
|
||||
// To make life easier, we also define iless and iset using iequals
|
||||
|
||||
struct iless
|
||||
{
|
||||
bool operator()(const std::string &a, const std::string &b) const
|
||||
{
|
||||
return icompare(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::set<std::string, iless> iset;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// This really makes a difference, having our own tolower routines
|
||||
|
||||
extern const uint8_t kCharToLowerMap[256];
|
||||
|
||||
inline char tolower(int ch)
|
||||
{
|
||||
return static_cast<char>(kCharToLowerMap[static_cast<uint8_t>(ch)]);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::tuple<std::string, std::string> splitTagName(std::string_view tag);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// generate a cif name, mainly used to generate asym_id's
|
||||
|
||||
std::string cifIdForNumber(int number);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// custom wordwrapping routine
|
||||
|
||||
std::vector<std::string> wordWrap(const std::string &text, size_t width);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Code helping with terminal i/o
|
||||
|
||||
uint32_t get_terminal_width();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Path of the current executable
|
||||
|
||||
std::string get_executable_path();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// some manipulators to write coloured text to terminals
|
||||
|
||||
enum StringColour
|
||||
{
|
||||
scBLACK = 0,
|
||||
scRED,
|
||||
scGREEN,
|
||||
scYELLOW,
|
||||
scBLUE,
|
||||
scMAGENTA,
|
||||
scCYAN,
|
||||
scWHITE,
|
||||
scNONE = 9
|
||||
};
|
||||
|
||||
template <typename String, typename CharT>
|
||||
struct ColouredString
|
||||
{
|
||||
static_assert(std::is_reference<String>::value or std::is_pointer<String>::value, "String type must be pointer or reference");
|
||||
|
||||
ColouredString(String s, StringColour fore, StringColour back, bool bold = true)
|
||||
: m_s(s)
|
||||
, m_fore(fore)
|
||||
, m_back(back)
|
||||
, m_bold(bold)
|
||||
{
|
||||
}
|
||||
|
||||
ColouredString &operator=(const ColouredString &) = delete;
|
||||
|
||||
String m_s;
|
||||
StringColour m_fore, m_back;
|
||||
bool m_bold;
|
||||
};
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, const ColouredString<const CharT *, CharT> &s)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO))
|
||||
{
|
||||
std::basic_ostringstream<CharT, Traits> ostr;
|
||||
ostr << "\033[" << (30 + s.m_fore) << ';' << (s.m_bold ? "1" : "22") << ';' << (40 + s.m_back) << 'm'
|
||||
<< s.m_s
|
||||
<< "\033[0m";
|
||||
|
||||
return os << ostr.str();
|
||||
}
|
||||
else
|
||||
return os << s.m_s;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits, typename String>
|
||||
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, const ColouredString<String, CharT> &s)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO))
|
||||
{
|
||||
std::basic_ostringstream<CharT, Traits> ostr;
|
||||
ostr << "\033[" << (30 + s.m_fore) << ';' << (s.m_bold ? "1" : "22") << ';' << (40 + s.m_back) << 'm'
|
||||
<< s.m_s
|
||||
<< "\033[0m";
|
||||
|
||||
return os << ostr.str();
|
||||
}
|
||||
else
|
||||
return os << s.m_s;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
inline auto coloured(const CharT *s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
|
||||
{
|
||||
return ColouredString<const CharT *, CharT>(s, fore, back, bold);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits, typename Alloc>
|
||||
inline auto coloured(const std::basic_string<CharT, Traits, Alloc> &s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
|
||||
{
|
||||
return ColouredString<const std::basic_string<CharT, Traits, Alloc>, CharT>(s, fore, back, bold);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits, typename Alloc>
|
||||
inline auto coloured(std::basic_string<CharT, Traits, Alloc> &s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
|
||||
{
|
||||
return ColouredString<std::basic_string<CharT, Traits, Alloc>, CharT>(s, fore, back, bold);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// A progress bar
|
||||
|
||||
class Progress
|
||||
{
|
||||
public:
|
||||
Progress(int64_t inMax, const std::string &inAction);
|
||||
virtual ~Progress();
|
||||
|
||||
void consumed(int64_t inConsumed); // consumed is relative
|
||||
void progress(int64_t inProgress); // progress is absolute
|
||||
|
||||
void message(const std::string &inMessage);
|
||||
|
||||
private:
|
||||
Progress(const Progress &) = delete;
|
||||
Progress &operator=(const Progress &) = delete;
|
||||
|
||||
struct ProgressImpl *mImpl;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Resources
|
||||
|
||||
std::unique_ptr<std::istream> loadResource(std::filesystem::path name);
|
||||
void addFileResource(const std::string &name, std::filesystem::path dataFile);
|
||||
void addDataDirectory(std::filesystem::path dataDir);
|
||||
|
||||
} // namespace cif
|
||||
226
include/cif++/CifValidator.hpp
Normal file
226
include/cif++/CifValidator.hpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
|
||||
// duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
|
||||
// #include <regex>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
struct ValidateCategory;
|
||||
class ValidatorFactory;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class ValidationError : public std::exception
|
||||
{
|
||||
public:
|
||||
ValidationError(const std::string &msg);
|
||||
ValidationError(const std::string &cat, const std::string &item,
|
||||
const std::string &msg);
|
||||
const char *what() const noexcept { return mMsg.c_str(); }
|
||||
std::string mMsg;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
enum class DDL_PrimitiveType
|
||||
{
|
||||
Char,
|
||||
UChar,
|
||||
Numb
|
||||
};
|
||||
|
||||
DDL_PrimitiveType mapToPrimitiveType(std::string_view s);
|
||||
|
||||
struct ValidateType
|
||||
{
|
||||
std::string mName;
|
||||
DDL_PrimitiveType mPrimitiveType;
|
||||
// std::regex mRx;
|
||||
boost::regex mRx;
|
||||
|
||||
bool operator<(const ValidateType &rhs) const
|
||||
{
|
||||
return icompare(mName, rhs.mName) < 0;
|
||||
}
|
||||
|
||||
// compare values based on type
|
||||
// int compare(const std::string& a, const std::string& b) const
|
||||
// {
|
||||
// return compare(a.c_str(), b.c_str());
|
||||
// }
|
||||
|
||||
int compare(const char *a, const char *b) const;
|
||||
};
|
||||
|
||||
struct ValidateItem
|
||||
{
|
||||
std::string mTag;
|
||||
bool mMandatory;
|
||||
const ValidateType *mType;
|
||||
cif::iset mEnums;
|
||||
std::string mDefault;
|
||||
bool mDefaultIsNull;
|
||||
ValidateCategory *mCategory = nullptr;
|
||||
|
||||
// ItemLinked is used for non-key links
|
||||
struct ItemLinked
|
||||
{
|
||||
ValidateItem *mParent;
|
||||
std::string mParentItem;
|
||||
std::string mChildItem;
|
||||
};
|
||||
|
||||
std::vector<ItemLinked> mLinked;
|
||||
|
||||
bool operator<(const ValidateItem &rhs) const
|
||||
{
|
||||
return icompare(mTag, rhs.mTag) < 0;
|
||||
}
|
||||
|
||||
bool operator==(const ValidateItem &rhs) const
|
||||
{
|
||||
return iequals(mTag, rhs.mTag);
|
||||
}
|
||||
|
||||
void operator()(std::string value) const;
|
||||
};
|
||||
|
||||
struct ValidateCategory
|
||||
{
|
||||
std::string mName;
|
||||
std::vector<std::string> mKeys;
|
||||
cif::iset mGroups;
|
||||
cif::iset mMandatoryFields;
|
||||
std::set<ValidateItem> mItemValidators;
|
||||
|
||||
bool operator<(const ValidateCategory &rhs) const
|
||||
{
|
||||
return icompare(mName, rhs.mName) < 0;
|
||||
}
|
||||
|
||||
void addItemValidator(ValidateItem &&v);
|
||||
|
||||
const ValidateItem *getValidatorForItem(std::string_view tag) const;
|
||||
|
||||
const std::set<ValidateItem> &itemValidators() const
|
||||
{
|
||||
return mItemValidators;
|
||||
}
|
||||
};
|
||||
|
||||
struct ValidateLink
|
||||
{
|
||||
int mLinkGroupID;
|
||||
std::string mParentCategory;
|
||||
std::vector<std::string> mParentKeys;
|
||||
std::string mChildCategory;
|
||||
std::vector<std::string> mChildKeys;
|
||||
std::string mLinkGroupLabel;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Validator
|
||||
{
|
||||
public:
|
||||
|
||||
Validator(std::string_view name, std::istream &is);
|
||||
~Validator();
|
||||
|
||||
Validator(const Validator &rhs) = delete;
|
||||
Validator &operator=(const Validator &rhs) = delete;
|
||||
|
||||
Validator(Validator &&rhs);
|
||||
Validator &operator=(Validator &&rhs);
|
||||
|
||||
friend class DictParser;
|
||||
friend class ValidatorFactory;
|
||||
|
||||
void addTypeValidator(ValidateType &&v);
|
||||
const ValidateType *getValidatorForType(std::string_view typeCode) const;
|
||||
|
||||
void addCategoryValidator(ValidateCategory &&v);
|
||||
const ValidateCategory *getValidatorForCategory(std::string_view category) const;
|
||||
|
||||
void addLinkValidator(ValidateLink &&v);
|
||||
std::vector<const ValidateLink *> getLinksForParent(std::string_view category) const;
|
||||
std::vector<const ValidateLink *> getLinksForChild(std::string_view category) const;
|
||||
|
||||
void reportError(const std::string &msg, bool fatal) const;
|
||||
|
||||
std::string dictName() const { return mName; }
|
||||
void dictName(const std::string &name) { mName = name; }
|
||||
|
||||
std::string dictVersion() const { return mVersion; }
|
||||
void dictVersion(const std::string &version) { mVersion = version; }
|
||||
|
||||
private:
|
||||
|
||||
// name is fully qualified here:
|
||||
ValidateItem *getValidatorForItem(std::string_view name) const;
|
||||
|
||||
std::string mName;
|
||||
std::string mVersion;
|
||||
bool mStrict = false;
|
||||
// std::set<uint32_t> mSubCategories;
|
||||
std::set<ValidateType> mTypeValidators;
|
||||
std::set<ValidateCategory> mCategoryValidators;
|
||||
std::vector<ValidateLink> mLinkValidators;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class ValidatorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
static ValidatorFactory &instance()
|
||||
{
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
const Validator &operator[](std::string_view dictionary);
|
||||
|
||||
private:
|
||||
|
||||
static ValidatorFactory sInstance;
|
||||
|
||||
ValidatorFactory();
|
||||
|
||||
std::mutex mMutex;
|
||||
std::list<Validator> mValidators;
|
||||
};
|
||||
|
||||
} // namespace cif
|
||||
197
include/cif++/Compound.hpp
Normal file
197
include/cif++/Compound.hpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/// \file This file contains the definition for the class Compound, encapsulating
|
||||
/// the information found for compounds in the CCD.
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "cif++/AtomType.hpp"
|
||||
#include "cif++/Cif++.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Compound;
|
||||
struct CompoundAtom;
|
||||
class CompoundFactoryImpl;
|
||||
|
||||
/// \brief The bond type as defined in the CCD, possible values taken from the mmcif_pdbx_v50 file
|
||||
enum class BondType
|
||||
{
|
||||
sing, // 'single bond'
|
||||
doub, // 'double bond'
|
||||
trip, // 'triple bond'
|
||||
quad, // 'quadruple bond'
|
||||
arom, // 'aromatic bond'
|
||||
poly, // 'polymeric bond'
|
||||
delo, // 'delocalized double bond'
|
||||
pi, // 'pi bond'
|
||||
};
|
||||
|
||||
std::string to_string(BondType bondType);
|
||||
BondType from_string(const std::string& bondType);
|
||||
|
||||
/// --------------------------------------------------------------------
|
||||
/// \brief struct containing information about an atom in a chemical compound.
|
||||
/// This is a subset of the available information. Contact the author if you need more fields.
|
||||
|
||||
struct CompoundAtom
|
||||
{
|
||||
std::string id;
|
||||
AtomType typeSymbol;
|
||||
int charge = 0;
|
||||
bool aromatic = false;
|
||||
bool leavingAtom = false;
|
||||
bool stereoConfig = false;
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
/// --------------------------------------------------------------------
|
||||
/// \brief struct containing information about the bonds
|
||||
|
||||
struct CompoundBond
|
||||
{
|
||||
std::string atomID[2];
|
||||
BondType type;
|
||||
bool aromatic = false, stereoConfig = false;
|
||||
};
|
||||
|
||||
/// --------------------------------------------------------------------
|
||||
/// \brief a class that contains information about a chemical compound.
|
||||
/// This information is derived from the CDD by default.
|
||||
///
|
||||
/// To create compounds, you use the factory method. You can add your own
|
||||
/// compound definitions by calling the addExtraComponents function and
|
||||
/// pass it a valid CCD formatted file.
|
||||
|
||||
class Compound
|
||||
{
|
||||
public:
|
||||
|
||||
// accessors
|
||||
|
||||
std::string id() const { return mID; }
|
||||
std::string name() const { return mName; }
|
||||
std::string type() const { return mType; }
|
||||
std::string group() const { return mGroup; }
|
||||
std::string formula() const { return mFormula; }
|
||||
float formulaWeight() const { return mFormulaWeight; }
|
||||
int formalCharge() const { return mFormalCharge; }
|
||||
|
||||
const std::vector<CompoundAtom> &atoms() const { return mAtoms; }
|
||||
const std::vector<CompoundBond> &bonds() const { return mBonds; }
|
||||
|
||||
CompoundAtom getAtomByID(const std::string &atomID) const;
|
||||
|
||||
bool atomsBonded(const std::string &atomId_1, const std::string &atomId_2) const;
|
||||
// float atomBondValue(const std::string &atomId_1, const std::string &atomId_2) const;
|
||||
// float bondAngle(const std::string &atomId_1, const std::string &atomId_2, const std::string &atomId_3) const;
|
||||
// float chiralVolume(const std::string ¢reID) const;
|
||||
|
||||
bool isWater() const
|
||||
{
|
||||
return mID == "HOH" or mID == "H2O" or mID == "WAT";
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class CompoundFactoryImpl;
|
||||
friend class CCDCompoundFactoryImpl;
|
||||
friend class CCP4CompoundFactoryImpl;
|
||||
|
||||
Compound(cif::Datablock &db);
|
||||
Compound(cif::Datablock &db, const std::string &id, const std::string &name, const std::string &type, const std::string &group);
|
||||
|
||||
std::string mID;
|
||||
std::string mName;
|
||||
std::string mType;
|
||||
std::string mGroup;
|
||||
std::string mFormula;
|
||||
float mFormulaWeight = 0;
|
||||
int mFormalCharge = 0;
|
||||
std::vector<CompoundAtom> mAtoms;
|
||||
std::vector<CompoundBond> mBonds;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Factory class for Compound and Link objects
|
||||
|
||||
CIFPP_EXPORT extern const std::map<std::string, char> kAAMap, kBaseMap;
|
||||
|
||||
class CompoundFactory
|
||||
{
|
||||
public:
|
||||
|
||||
/// \brief Initialise a singleton instance.
|
||||
///
|
||||
/// If you have a multithreaded application and want to have different
|
||||
/// compounds in each thread (e.g. a web service processing user requests
|
||||
/// with different sets of compounds) you can set the \a useThreadLocalInstanceOnly
|
||||
/// flag to true.
|
||||
|
||||
static void init(bool useThreadLocalInstanceOnly);
|
||||
static CompoundFactory &instance();
|
||||
static void clear();
|
||||
|
||||
void setDefaultDictionary(const std::filesystem::path &inDictFile);
|
||||
void pushDictionary(const std::filesystem::path &inDictFile);
|
||||
void popDictionary();
|
||||
|
||||
bool isKnownPeptide(const std::string &res_name) const;
|
||||
bool isKnownBase(const std::string &res_name) const;
|
||||
|
||||
/// \brief Create the Compound object for \a id
|
||||
///
|
||||
/// This will create the Compound instance for \a id if it doesn't exist already.
|
||||
/// The result is owned by this factory and should not be deleted by the user.
|
||||
/// \param id The Compound ID, a three letter code usually
|
||||
/// \result The compound, or nullptr if it could not be created (missing info)
|
||||
const Compound *create(std::string id);
|
||||
|
||||
~CompoundFactory();
|
||||
|
||||
private:
|
||||
CompoundFactory();
|
||||
|
||||
CompoundFactory(const CompoundFactory &) = delete;
|
||||
CompoundFactory &operator=(const CompoundFactory &) = delete;
|
||||
|
||||
static std::unique_ptr<CompoundFactory> sInstance;
|
||||
static thread_local std::unique_ptr<CompoundFactory> tlInstance;
|
||||
static bool sUseThreadLocalInstance;
|
||||
|
||||
std::shared_ptr<CompoundFactoryImpl> mImpl;
|
||||
};
|
||||
|
||||
} // namespace mmcif
|
||||
60
include/cif++/PDB2Cif.hpp
Normal file
60
include/cif++/PDB2Cif.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct PDBRecord
|
||||
{
|
||||
PDBRecord *mNext;
|
||||
uint32_t mLineNr;
|
||||
char mName[11];
|
||||
size_t mVlen;
|
||||
char mValue[1];
|
||||
|
||||
PDBRecord(uint32_t lineNr, const std::string &name, const std::string &value);
|
||||
~PDBRecord();
|
||||
|
||||
void *operator new(size_t);
|
||||
void *operator new(size_t size, size_t vLen);
|
||||
|
||||
void operator delete(void *p);
|
||||
void operator delete(void *p, size_t vLen);
|
||||
|
||||
bool is(const char *name) const;
|
||||
|
||||
char vC(size_t column);
|
||||
std::string vS(size_t columnFirst, size_t columnLast = std::numeric_limits<size_t>::max());
|
||||
int vI(int columnFirst, int columnLast);
|
||||
std::string vF(size_t columnFirst, size_t columnLast);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void ReadPDBFile(std::istream &pdbFile, cif::File &cifFile);
|
||||
73
include/cif++/PDB2CifRemark3.hpp
Normal file
73
include/cif++/PDB2CifRemark3.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cif++/PDB2Cif.hpp"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct TemplateLine;
|
||||
|
||||
class Remark3Parser
|
||||
{
|
||||
public:
|
||||
virtual ~Remark3Parser() {}
|
||||
|
||||
static bool parse(const std::string& expMethod, PDBRecord* r, cif::Datablock& db);
|
||||
|
||||
virtual std::string program();
|
||||
virtual std::string version();
|
||||
|
||||
protected:
|
||||
|
||||
Remark3Parser(const std::string& name, const std::string& expMethod, PDBRecord* r, cif::Datablock& db,
|
||||
const TemplateLine templatelines[], uint32_t templateLineCount, std::regex programVersion);
|
||||
|
||||
virtual float parse();
|
||||
std::string nextLine();
|
||||
|
||||
bool match(const char* expr, int nextState);
|
||||
void storeCapture(const char* category, std::initializer_list<const char*> items, bool createNew = false);
|
||||
void storeRefineLsRestr(const char* type, std::initializer_list<const char*> values);
|
||||
void updateRefineLsRestr(const char* type, std::initializer_list<const char*> values);
|
||||
|
||||
virtual void fixup() {}
|
||||
|
||||
std::string mName;
|
||||
std::string mExpMethod;
|
||||
PDBRecord* mRec;
|
||||
cif::Datablock mDb;
|
||||
std::string mLine;
|
||||
std::smatch mM;
|
||||
uint32_t mState;
|
||||
|
||||
const TemplateLine* mTemplate;
|
||||
uint32_t mTemplateCount;
|
||||
std::regex mProgramVersion;
|
||||
};
|
||||
|
||||
|
||||
456
include/cif++/Point.hpp
Normal file
456
include/cif++/Point.hpp
Normal file
@@ -0,0 +1,456 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#if HAVE_LIBCLIPPER
|
||||
#include <clipper/core/coords.h>
|
||||
#endif
|
||||
|
||||
#include <boost/math/quaternion.hpp>
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
typedef boost::math::quaternion<float> Quaternion;
|
||||
|
||||
const double
|
||||
kPI = 3.141592653589793238462643383279502884;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Point, a location with x, y and z coordinates as floating point.
|
||||
// This one is derived from a tuple<float,float,float> so
|
||||
// you can do things like:
|
||||
//
|
||||
// float x, y, z;
|
||||
// tie(x, y, z) = atom.loc();
|
||||
|
||||
template <typename F>
|
||||
struct PointF
|
||||
{
|
||||
typedef F FType;
|
||||
|
||||
FType mX, mY, mZ;
|
||||
|
||||
PointF()
|
||||
: mX(0)
|
||||
, mY(0)
|
||||
, mZ(0)
|
||||
{
|
||||
}
|
||||
PointF(FType x, FType y, FType z)
|
||||
: mX(x)
|
||||
, mY(y)
|
||||
, mZ(z)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename PF>
|
||||
PointF(const PointF<PF> &pt)
|
||||
: mX(static_cast<F>(pt.mX))
|
||||
, mY(static_cast<F>(pt.mY))
|
||||
, mZ(static_cast<F>(pt.mZ))
|
||||
{
|
||||
}
|
||||
|
||||
#if HAVE_LIBCLIPPER
|
||||
PointF(const clipper::Coord_orth &pt)
|
||||
: mX(pt[0])
|
||||
, mY(pt[1])
|
||||
, mZ(pt[2])
|
||||
{
|
||||
}
|
||||
|
||||
PointF &operator=(const clipper::Coord_orth &rhs)
|
||||
{
|
||||
mX = rhs[0];
|
||||
mY = rhs[1];
|
||||
mZ = rhs[2];
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename PF>
|
||||
PointF &operator=(const PointF<PF> &rhs)
|
||||
{
|
||||
mX = static_cast<F>(rhs.mX);
|
||||
mY = static_cast<F>(rhs.mY);
|
||||
mZ = static_cast<F>(rhs.mZ);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FType &getX() { return mX; }
|
||||
FType getX() const { return mX; }
|
||||
void setX(FType x) { mX = x; }
|
||||
|
||||
FType &getY() { return mY; }
|
||||
FType getY() const { return mY; }
|
||||
void setY(FType y) { mY = y; }
|
||||
|
||||
FType &getZ() { return mZ; }
|
||||
FType getZ() const { return mZ; }
|
||||
void setZ(FType z) { mZ = z; }
|
||||
|
||||
PointF &operator+=(const PointF &rhs)
|
||||
{
|
||||
mX += rhs.mX;
|
||||
mY += rhs.mY;
|
||||
mZ += rhs.mZ;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointF &operator+=(FType d)
|
||||
{
|
||||
mX += d;
|
||||
mY += d;
|
||||
mZ += d;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointF &operator-=(const PointF &rhs)
|
||||
{
|
||||
mX -= rhs.mX;
|
||||
mY -= rhs.mY;
|
||||
mZ -= rhs.mZ;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointF &operator-=(FType d)
|
||||
{
|
||||
mX -= d;
|
||||
mY -= d;
|
||||
mZ -= d;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointF &operator*=(FType rhs)
|
||||
{
|
||||
mX *= rhs;
|
||||
mY *= rhs;
|
||||
mZ *= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointF &operator/=(FType rhs)
|
||||
{
|
||||
mX /= rhs;
|
||||
mY /= rhs;
|
||||
mZ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FType normalize()
|
||||
{
|
||||
auto length = mX * mX + mY * mY + mZ * mZ;
|
||||
if (length > 0)
|
||||
{
|
||||
length = std::sqrt(length);
|
||||
operator/=(length);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void rotate(const boost::math::quaternion<FType> &q)
|
||||
{
|
||||
boost::math::quaternion<FType> p(0, mX, mY, mZ);
|
||||
|
||||
p = q * p * boost::math::conj(q);
|
||||
|
||||
mX = p.R_component_2();
|
||||
mY = p.R_component_3();
|
||||
mZ = p.R_component_4();
|
||||
}
|
||||
|
||||
#if HAVE_LIBCLIPPER
|
||||
operator clipper::Coord_orth() const
|
||||
{
|
||||
return clipper::Coord_orth(mX, mY, mZ);
|
||||
}
|
||||
#endif
|
||||
|
||||
operator std::tuple<const FType &, const FType &, const FType &>() const
|
||||
{
|
||||
return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ));
|
||||
}
|
||||
|
||||
operator std::tuple<FType &, FType &, FType &>()
|
||||
{
|
||||
return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ));
|
||||
}
|
||||
|
||||
bool operator==(const PointF &rhs) const
|
||||
{
|
||||
return mX == rhs.mX and mY == rhs.mY and mZ == rhs.mZ;
|
||||
}
|
||||
|
||||
// consider point as a vector... perhaps I should rename Point?
|
||||
FType lengthsq() const
|
||||
{
|
||||
return mX * mX + mY * mY + mZ * mZ;
|
||||
}
|
||||
|
||||
FType length() const
|
||||
{
|
||||
return std::sqrt(mX * mX + mY * mY + mZ * mZ);
|
||||
}
|
||||
};
|
||||
|
||||
typedef PointF<float> Point;
|
||||
typedef PointF<double> DPoint;
|
||||
|
||||
template <typename F>
|
||||
inline std::ostream &operator<<(std::ostream &os, const PointF<F> &pt)
|
||||
{
|
||||
os << '(' << pt.mX << ',' << pt.mY << ',' << pt.mZ << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> operator+(const PointF<F> &lhs, const PointF<F> &rhs)
|
||||
{
|
||||
return PointF<F>(lhs.mX + rhs.mX, lhs.mY + rhs.mY, lhs.mZ + rhs.mZ);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> operator-(const PointF<F> &lhs, const PointF<F> &rhs)
|
||||
{
|
||||
return PointF<F>(lhs.mX - rhs.mX, lhs.mY - rhs.mY, lhs.mZ - rhs.mZ);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> operator-(const PointF<F> &pt)
|
||||
{
|
||||
return PointF<F>(-pt.mX, -pt.mY, -pt.mZ);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> operator*(const PointF<F> &pt, F f)
|
||||
{
|
||||
return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> operator*(F f, const PointF<F> &pt)
|
||||
{
|
||||
return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> operator/(const PointF<F> &pt, F f)
|
||||
{
|
||||
return PointF<F>(pt.mX / f, pt.mY / f, pt.mZ / f);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// several standard 3d operations
|
||||
|
||||
template <typename F>
|
||||
inline double DistanceSquared(const PointF<F> &a, const PointF<F> &b)
|
||||
{
|
||||
return (a.mX - b.mX) * (a.mX - b.mX) +
|
||||
(a.mY - b.mY) * (a.mY - b.mY) +
|
||||
(a.mZ - b.mZ) * (a.mZ - b.mZ);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline double Distance(const PointF<F> &a, const PointF<F> &b)
|
||||
{
|
||||
return std::sqrt(
|
||||
(a.mX - b.mX) * (a.mX - b.mX) +
|
||||
(a.mY - b.mY) * (a.mY - b.mY) +
|
||||
(a.mZ - b.mZ) * (a.mZ - b.mZ));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline F DotProduct(const PointF<F> &a, const PointF<F> &b)
|
||||
{
|
||||
return a.mX * b.mX + a.mY * b.mY + a.mZ * b.mZ;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline PointF<F> CrossProduct(const PointF<F> &a, const PointF<F> &b)
|
||||
{
|
||||
return PointF<F>(a.mY * b.mZ - b.mY * a.mZ,
|
||||
a.mZ * b.mX - b.mZ * a.mX,
|
||||
a.mX * b.mY - b.mX * a.mY);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
double Angle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p3)
|
||||
{
|
||||
PointF<F> v1 = p1 - p2;
|
||||
PointF<F> v2 = p3 - p2;
|
||||
|
||||
return std::acos(DotProduct(v1, v2) / (v1.length() * v2.length())) * 180 / kPI;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
double DihedralAngle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p3, const PointF<F> &p4)
|
||||
{
|
||||
PointF<F> v12 = p1 - p2; // vector from p2 to p1
|
||||
PointF<F> v43 = p4 - p3; // vector from p3 to p4
|
||||
|
||||
PointF<F> z = p2 - p3; // vector from p3 to p2
|
||||
|
||||
PointF<F> p = CrossProduct(z, v12);
|
||||
PointF<F> x = CrossProduct(z, v43);
|
||||
PointF<F> y = CrossProduct(z, x);
|
||||
|
||||
double u = DotProduct(x, x);
|
||||
double v = DotProduct(y, y);
|
||||
|
||||
double result = 360;
|
||||
if (u > 0 and v > 0)
|
||||
{
|
||||
u = DotProduct(p, x) / std::sqrt(u);
|
||||
v = DotProduct(p, y) / std::sqrt(v);
|
||||
if (u != 0 or v != 0)
|
||||
result = std::atan2(v, u) * 180 / kPI;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
double CosinusAngle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p3, const PointF<F> &p4)
|
||||
{
|
||||
PointF<F> v12 = p1 - p2;
|
||||
PointF<F> v34 = p3 - p4;
|
||||
|
||||
double result = 0;
|
||||
|
||||
double x = DotProduct(v12, v12) * DotProduct(v34, v34);
|
||||
if (x > 0)
|
||||
result = DotProduct(v12, v34) / std::sqrt(x);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
auto DistancePointToLine(const PointF<F> &l1, const PointF<F> &l2, const PointF<F> &p)
|
||||
{
|
||||
auto line = l2 - l1;
|
||||
auto p_to_l1 = p - l1;
|
||||
auto p_to_l2 = p - l2;
|
||||
auto cross = CrossProduct(p_to_l1, p_to_l2);
|
||||
return cross.length() / line.length();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// For e.g. simulated annealing, returns a new point that is moved in
|
||||
// a random direction with a distance randomly chosen from a normal
|
||||
// distribution with a stddev of offset.
|
||||
|
||||
Point Nudge(Point p, float offset);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// We use quaternions to do rotations in 3d space
|
||||
|
||||
Quaternion Normalize(Quaternion q);
|
||||
|
||||
Quaternion ConstructFromAngleAxis(float angle, Point axis);
|
||||
std::tuple<double, Point> QuaternionToAngleAxis(Quaternion q);
|
||||
|
||||
Point Centroid(const std::vector<Point> &Points);
|
||||
Point CenterPoints(std::vector<Point> &Points);
|
||||
|
||||
/// \brief Returns how the two sets of points \a a and \b b can be aligned
|
||||
///
|
||||
/// \param a The first set of points
|
||||
/// \param b The second set of points
|
||||
/// \result The quaternion which should be applied to the points in \a a to
|
||||
/// obtain the best superposition.
|
||||
Quaternion AlignPoints(const std::vector<Point> &a, const std::vector<Point> &b);
|
||||
|
||||
/// \brief The RMSd for the points in \a a and \a b
|
||||
double RMSd(const std::vector<Point> &a, const std::vector<Point> &b);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Helper class to generate evenly divided Points on a sphere
|
||||
// we use a fibonacci sphere to calculate even distribution of the dots
|
||||
|
||||
template <int N>
|
||||
class SphericalDots
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
P = 2 * N + 1
|
||||
};
|
||||
typedef typename std::array<Point, P> array_type;
|
||||
typedef typename array_type::const_iterator iterator;
|
||||
|
||||
static SphericalDots &instance()
|
||||
{
|
||||
static SphericalDots sInstance;
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
size_t size() const { return mPoints.size(); }
|
||||
const Point operator[](uint32_t inIx) const { return mPoints[inIx]; }
|
||||
iterator begin() const { return mPoints.begin(); }
|
||||
iterator end() const { return mPoints.end(); }
|
||||
|
||||
double weight() const { return mWeight; }
|
||||
|
||||
SphericalDots()
|
||||
{
|
||||
|
||||
const double
|
||||
kGoldenRatio = (1 + std::sqrt(5.0)) / 2;
|
||||
|
||||
mWeight = (4 * kPI) / P;
|
||||
|
||||
auto p = mPoints.begin();
|
||||
|
||||
for (int32_t i = -N; i <= N; ++i)
|
||||
{
|
||||
double lat = std::asin((2.0 * i) / P);
|
||||
double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio;
|
||||
|
||||
p->mX = std::sin(lon) * std::cos(lat);
|
||||
p->mY = std::cos(lon) * std::cos(lat);
|
||||
p->mZ = std::sin(lat);
|
||||
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
array_type mPoints;
|
||||
double mWeight;
|
||||
};
|
||||
|
||||
typedef SphericalDots<50> SphericalDots_50;
|
||||
|
||||
} // namespace mmcif
|
||||
251
include/cif++/Secondary.hpp
Normal file
251
include/cif++/Secondary.hpp
Normal file
@@ -0,0 +1,251 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Calculate DSSP-like secondary structure information
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
class Structure;
|
||||
class Monomer;
|
||||
|
||||
struct Res;
|
||||
|
||||
extern const float
|
||||
kCouplingConstant, kMinHBondEnergy, kMaxHBondEnergy;
|
||||
|
||||
enum SecondaryStructureType : char
|
||||
{
|
||||
ssLoop = ' ',
|
||||
ssAlphahelix = 'H',
|
||||
ssBetabridge = 'B',
|
||||
ssStrand = 'E',
|
||||
ssHelix_3 = 'G',
|
||||
ssHelix_5 = 'I',
|
||||
ssHelix_PPII = 'P',
|
||||
ssTurn = 'T',
|
||||
ssBend = 'S'
|
||||
};
|
||||
|
||||
enum class HelixType
|
||||
{
|
||||
rh_3_10, rh_alpha, rh_pi, rh_pp
|
||||
};
|
||||
|
||||
enum class Helix
|
||||
{
|
||||
None, Start, End, StartAndEnd, Middle
|
||||
};
|
||||
|
||||
//struct HBond
|
||||
//{
|
||||
// std::string labelAsymID;
|
||||
// int labelSeqID;
|
||||
// double energy;
|
||||
//};
|
||||
//
|
||||
//struct BridgePartner
|
||||
//{
|
||||
// std::string labelAsymID;
|
||||
// int labelSeqID;
|
||||
// int ladder;
|
||||
// bool parallel;
|
||||
//};
|
||||
|
||||
struct SecondaryStructure
|
||||
{
|
||||
SecondaryStructureType type;
|
||||
// HBond donor[2], acceptor[2];
|
||||
// BridgePartner beta[2];
|
||||
// int sheet;
|
||||
// bool bend;
|
||||
};
|
||||
|
||||
//void CalculateSecondaryStructure(Structure& s);
|
||||
|
||||
const size_t
|
||||
kHistogramSize = 30;
|
||||
|
||||
struct DSSP_Statistics
|
||||
{
|
||||
uint32_t nrOfResidues, nrOfChains, nrOfSSBridges, nrOfIntraChainSSBridges, nrOfHBonds;
|
||||
uint32_t nrOfHBondsInAntiparallelBridges, nrOfHBondsInParallelBridges;
|
||||
uint32_t nrOfHBondsPerDistance[11] = {};
|
||||
double accessibleSurface = 0;
|
||||
|
||||
uint32_t residuesPerAlphaHelixHistogram[kHistogramSize] = {};
|
||||
uint32_t parallelBridgesPerLadderHistogram[kHistogramSize] = {};
|
||||
uint32_t antiparallelBridgesPerLadderHistogram[kHistogramSize] = {};
|
||||
uint32_t laddersPerSheetHistogram[kHistogramSize] = {};
|
||||
};
|
||||
|
||||
enum class ChainBreak
|
||||
{
|
||||
None, NewChain, Gap
|
||||
};
|
||||
|
||||
class DSSP
|
||||
{
|
||||
public:
|
||||
DSSP(const Structure& s, int min_poly_proline_stretch_length, bool calculateSurfaceAccessibility);
|
||||
~DSSP();
|
||||
|
||||
DSSP(const DSSP&) = delete;
|
||||
DSSP& operator=(const DSSP&) = delete;
|
||||
|
||||
SecondaryStructureType operator()(const std::string& inAsymID, int inSeqID) const;
|
||||
SecondaryStructureType operator()(const Monomer& m) const;
|
||||
|
||||
double accessibility(const std::string& inAsymID, int inSeqID) const;
|
||||
double accessibility(const Monomer& m) const;
|
||||
|
||||
bool isAlphaHelixEndBeforeStart(const Monomer& m) const;
|
||||
bool isAlphaHelixEndBeforeStart(const std::string& inAsymID, int inSeqID) const;
|
||||
|
||||
DSSP_Statistics GetStatistics() const;
|
||||
|
||||
class iterator;
|
||||
using res_iterator = typename std::vector<Res>::iterator;
|
||||
|
||||
class ResidueInfo
|
||||
{
|
||||
public:
|
||||
friend class iterator;
|
||||
|
||||
ResidueInfo()
|
||||
: mImpl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ResidueInfo(const ResidueInfo &rhs)
|
||||
: mImpl(rhs.mImpl)
|
||||
{
|
||||
}
|
||||
|
||||
ResidueInfo& operator=(const ResidueInfo &rhs)
|
||||
{
|
||||
mImpl = rhs.mImpl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return not empty(); }
|
||||
bool empty() const { return mImpl == nullptr; }
|
||||
|
||||
const Monomer& residue() const;
|
||||
std::string alt_id() const;
|
||||
|
||||
/// \brief return 0 if not a break, ' ' in case of a new chain and '*' in case of a broken chain
|
||||
ChainBreak chainBreak() const;
|
||||
|
||||
/// \brief the internal number in DSSP
|
||||
int nr() const;
|
||||
|
||||
SecondaryStructureType ss() const;
|
||||
|
||||
int ssBridgeNr() const;
|
||||
|
||||
Helix helix(HelixType helixType) const;
|
||||
|
||||
bool bend() const;
|
||||
|
||||
double accessibility() const;
|
||||
|
||||
/// \brief returns resinfo, ladder and parallel
|
||||
std::tuple<ResidueInfo,int,bool> bridgePartner(int i) const;
|
||||
|
||||
int sheet() const;
|
||||
|
||||
/// \brief return resinfo and the energy of the bond
|
||||
std::tuple<ResidueInfo,double> acceptor(int i) const;
|
||||
std::tuple<ResidueInfo,double> donor(int i) const;
|
||||
|
||||
/// \brief Simple compare equals
|
||||
bool operator==(const ResidueInfo &rhs) const
|
||||
{
|
||||
return mImpl == rhs.mImpl;
|
||||
}
|
||||
|
||||
/// \brief Returns \result true if there is a bond between two residues
|
||||
friend bool TestBond(ResidueInfo const &a, ResidueInfo const &b);
|
||||
|
||||
private:
|
||||
ResidueInfo(Res* res) : mImpl(res) {}
|
||||
|
||||
Res* mImpl;
|
||||
};
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = ResidueInfo;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
|
||||
iterator(const iterator& i);
|
||||
iterator(Res* res);
|
||||
iterator& operator=(const iterator& i);
|
||||
|
||||
reference operator*() { return mCurrent; }
|
||||
pointer operator->() { return &mCurrent; }
|
||||
|
||||
iterator& operator++();
|
||||
iterator operator++(int)
|
||||
{
|
||||
auto tmp(*this);
|
||||
this->operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator& operator--();
|
||||
iterator operator--(int)
|
||||
{
|
||||
auto tmp(*this);
|
||||
this->operator--();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& rhs) const { return mCurrent.mImpl == rhs.mCurrent.mImpl; }
|
||||
bool operator!=(const iterator& rhs) const { return mCurrent.mImpl != rhs.mCurrent.mImpl; }
|
||||
|
||||
private:
|
||||
ResidueInfo mCurrent;
|
||||
};
|
||||
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
|
||||
bool empty() const { return begin() == end(); }
|
||||
|
||||
private:
|
||||
struct DSSPImpl* mImpl;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
827
include/cif++/Structure.hpp
Normal file
827
include/cif++/Structure.hpp
Normal file
@@ -0,0 +1,827 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include "cif++/AtomType.hpp"
|
||||
#include "cif++/Cif++.hpp"
|
||||
#include "cif++/Compound.hpp"
|
||||
#include "cif++/Point.hpp"
|
||||
|
||||
/*
|
||||
To modify a structure, you will have to use actions.
|
||||
|
||||
The currently supported actions are:
|
||||
|
||||
// - Move atom to new location
|
||||
- Remove atom
|
||||
// - Add new atom that was formerly missing
|
||||
// - Add alternate Residue
|
||||
-
|
||||
|
||||
*/
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
class Atom;
|
||||
class Residue;
|
||||
class Monomer;
|
||||
class Polymer;
|
||||
class Structure;
|
||||
class File;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Atom
|
||||
{
|
||||
private:
|
||||
struct AtomImpl : public std::enable_shared_from_this<AtomImpl>
|
||||
{
|
||||
AtomImpl(cif::Datablock &db, const std::string &id, cif::Row row);
|
||||
|
||||
// constructor for a symmetry copy of an atom
|
||||
AtomImpl(const AtomImpl &impl, const Point &loc, const std::string &sym_op);
|
||||
|
||||
AtomImpl(const AtomImpl &i) = default;
|
||||
|
||||
void prefetch();
|
||||
|
||||
int compare(const AtomImpl &b) const;
|
||||
|
||||
bool getAnisoU(float anisou[6]) const;
|
||||
|
||||
int charge() const;
|
||||
|
||||
void moveTo(const Point &p);
|
||||
|
||||
const Compound &comp() const;
|
||||
|
||||
const std::string get_property(const std::string_view name) const;
|
||||
void set_property(const std::string_view name, const std::string &value);
|
||||
|
||||
const cif::Datablock &mDb;
|
||||
std::string mID;
|
||||
AtomType mType;
|
||||
|
||||
std::string mAtomID;
|
||||
std::string mCompID;
|
||||
std::string mAsymID;
|
||||
int mSeqID;
|
||||
std::string mAltID;
|
||||
std::string mAuthSeqID;
|
||||
|
||||
Point mLocation;
|
||||
int mRefcount;
|
||||
cif::Row mRow;
|
||||
|
||||
mutable std::vector<std::tuple<std::string, cif::detail::ItemReference>> mCachedRefs;
|
||||
|
||||
mutable const Compound *mCompound = nullptr;
|
||||
|
||||
bool mSymmetryCopy = false;
|
||||
bool mClone = false;
|
||||
|
||||
std::string mSymmetryOperator = "1_555";
|
||||
};
|
||||
|
||||
public:
|
||||
Atom() {}
|
||||
|
||||
Atom(std::shared_ptr<AtomImpl> impl)
|
||||
: mImpl(impl)
|
||||
{
|
||||
}
|
||||
|
||||
Atom(const Atom &rhs)
|
||||
: mImpl(rhs.mImpl)
|
||||
{
|
||||
}
|
||||
|
||||
Atom(cif::Datablock &db, cif::Row &row);
|
||||
|
||||
// a special constructor to create symmetry copies
|
||||
Atom(const Atom &rhs, const Point &symmmetry_location, const std::string &symmetry_operation);
|
||||
|
||||
explicit operator bool() const { return (bool)mImpl; }
|
||||
|
||||
// return a copy of this atom, with data copied instead of referenced
|
||||
Atom clone() const
|
||||
{
|
||||
auto copy = std::make_shared<AtomImpl>(*mImpl);
|
||||
copy->mClone = true;
|
||||
return Atom(copy);
|
||||
}
|
||||
|
||||
Atom &operator=(const Atom &rhs) = default;
|
||||
|
||||
template <typename T>
|
||||
T get_property(const std::string_view name) const;
|
||||
|
||||
void set_property(const std::string_view name, const std::string &value)
|
||||
{
|
||||
if (not mImpl)
|
||||
throw std::logic_error("Error trying to modify an uninitialized atom");
|
||||
mImpl->set_property(name, value);
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
|
||||
void property(const std::string_view name, const T &value)
|
||||
{
|
||||
set_property(name, std::to_string(value));
|
||||
}
|
||||
|
||||
const std::string &id() const { return impl().mID; }
|
||||
AtomType type() const { return impl().mType; }
|
||||
|
||||
Point location() const { return impl().mLocation; }
|
||||
void location(Point p)
|
||||
{
|
||||
if (not mImpl)
|
||||
throw std::logic_error("Error trying to modify an uninitialized atom");
|
||||
mImpl->moveTo(p);
|
||||
}
|
||||
|
||||
/// \brief Translate the position of this atom by \a t
|
||||
void translate(Point t);
|
||||
|
||||
/// \brief Rotate the position of this atom by \a q
|
||||
void rotate(Quaternion q);
|
||||
|
||||
/// \brief Translate and rotate the position of this atom by \a t and \a q
|
||||
void translateAndRotate(Point t, Quaternion q);
|
||||
|
||||
/// \brief Translate, rotate and translate again the coordinates this atom by \a t1 , \a q and \a t2
|
||||
void translateRotateAndTranslate(Point t1, Quaternion q, Point t2);
|
||||
|
||||
// for direct access to underlying data, be careful!
|
||||
const cif::Row getRow() const { return impl().mRow; }
|
||||
const cif::Row getRowAniso() const;
|
||||
|
||||
bool isSymmetryCopy() const { return impl().mSymmetryCopy; }
|
||||
std::string symmetry() const { return impl().mSymmetryOperator; }
|
||||
|
||||
const Compound &comp() const { return impl().comp(); }
|
||||
bool isWater() const { return impl().mCompID == "HOH" or impl().mCompID == "H2O" or impl().mCompID == "WAT"; }
|
||||
int charge() const;
|
||||
|
||||
float uIso() const;
|
||||
bool getAnisoU(float anisou[6]) const { return impl().getAnisoU(anisou); }
|
||||
float occupancy() const;
|
||||
|
||||
// specifications
|
||||
const std::string &labelAtomID() const { return impl().mAtomID; }
|
||||
const std::string &labelCompID() const { return impl().mCompID; }
|
||||
const std::string &labelAsymID() const { return impl().mAsymID; }
|
||||
std::string labelEntityID() const;
|
||||
int labelSeqID() const { return impl().mSeqID; }
|
||||
const std::string &labelAltID() const { return impl().mAltID; }
|
||||
bool isAlternate() const { return not impl().mAltID.empty(); }
|
||||
|
||||
std::string authAtomID() const;
|
||||
std::string authCompID() const;
|
||||
std::string authAsymID() const;
|
||||
const std::string &authSeqID() const { return impl().mAuthSeqID; }
|
||||
std::string pdbxAuthInsCode() const;
|
||||
std::string pdbxAuthAltID() const;
|
||||
|
||||
std::string labelID() const; // label_comp_id + '_' + label_asym_id + '_' + label_seq_id
|
||||
std::string pdbID() const; // auth_comp_id + '_' + auth_asym_id + '_' + auth_seq_id + pdbx_PDB_ins_code
|
||||
|
||||
bool operator==(const Atom &rhs) const;
|
||||
bool operator!=(const Atom &rhs) const
|
||||
{
|
||||
return not operator==(rhs);
|
||||
}
|
||||
|
||||
// access data in compound for this atom
|
||||
|
||||
// convenience routine
|
||||
bool isBackBone() const
|
||||
{
|
||||
auto atomID = labelAtomID();
|
||||
return atomID == "N" or atomID == "O" or atomID == "C" or atomID == "CA";
|
||||
}
|
||||
|
||||
void swap(Atom &b)
|
||||
{
|
||||
std::swap(mImpl, b.mImpl);
|
||||
}
|
||||
|
||||
int compare(const Atom &b) const { return impl().compare(*b.mImpl); }
|
||||
|
||||
bool operator<(const Atom &rhs) const
|
||||
{
|
||||
return compare(rhs) < 0;
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Atom &atom);
|
||||
|
||||
/// \brief Synchronize data with underlying cif data
|
||||
void sync()
|
||||
{
|
||||
if (mImpl)
|
||||
mImpl->prefetch();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Structure;
|
||||
|
||||
const AtomImpl &impl() const
|
||||
{
|
||||
if (not mImpl)
|
||||
throw std::runtime_error("Uninitialized atom, not found?");
|
||||
return *mImpl;
|
||||
}
|
||||
|
||||
std::shared_ptr<AtomImpl> mImpl;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline std::string Atom::get_property<std::string>(const std::string_view name) const
|
||||
{
|
||||
return impl().get_property(name);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int Atom::get_property<int>(const std::string_view name) const
|
||||
{
|
||||
auto v = impl().get_property(name);
|
||||
return v.empty() ? 0 : stoi(v);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float Atom::get_property<float>(const std::string_view name) const
|
||||
{
|
||||
return stof(impl().get_property(name));
|
||||
}
|
||||
|
||||
inline void swap(mmcif::Atom &a, mmcif::Atom &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
inline double Distance(const Atom &a, const Atom &b)
|
||||
{
|
||||
return Distance(a.location(), b.location());
|
||||
}
|
||||
|
||||
inline double DistanceSquared(const Atom &a, const Atom &b)
|
||||
{
|
||||
return DistanceSquared(a.location(), b.location());
|
||||
}
|
||||
|
||||
typedef std::vector<Atom> AtomView;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
enum class EntityType
|
||||
{
|
||||
Polymer, NonPolymer, Macrolide, Water, Branched
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Residue
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
Residue(const Structure &structure, const std::string &compoundID,
|
||||
const std::string &asymID, int seqID, const std::string &authSeqID)
|
||||
: mStructure(&structure)
|
||||
, mCompoundID(compoundID)
|
||||
, mAsymID(asymID)
|
||||
, mSeqID(seqID)
|
||||
, mAuthSeqID(authSeqID)
|
||||
{
|
||||
}
|
||||
|
||||
Residue(const Residue &rhs) = delete;
|
||||
Residue &operator=(const Residue &rhs) = delete;
|
||||
|
||||
Residue(Residue &&rhs);
|
||||
Residue &operator=(Residue &&rhs);
|
||||
|
||||
virtual ~Residue();
|
||||
|
||||
const Compound &compound() const;
|
||||
|
||||
AtomView &atoms();
|
||||
const AtomView &atoms() const;
|
||||
|
||||
void addAtom(Atom &atom);
|
||||
|
||||
/// \brief Unique atoms returns only the atoms without alternates and the first of each alternate atom id.
|
||||
AtomView unique_atoms() const;
|
||||
|
||||
/// \brief The alt ID used for the unique atoms
|
||||
std::string unique_alt_id() const;
|
||||
|
||||
Atom atomByID(const std::string &atomID) const;
|
||||
|
||||
const std::string &compoundID() const { return mCompoundID; }
|
||||
void setCompoundID(const std::string &id) { mCompoundID = id; }
|
||||
|
||||
const std::string &asymID() const { return mAsymID; }
|
||||
int seqID() const { return mSeqID; }
|
||||
std::string entityID() const;
|
||||
|
||||
EntityType entityType() const;
|
||||
|
||||
std::string authAsymID() const;
|
||||
std::string authSeqID() const;
|
||||
std::string authInsCode() const;
|
||||
|
||||
// return a human readable PDB-like auth id (chain+seqnr+iCode)
|
||||
std::string authID() const;
|
||||
|
||||
// similar for mmCIF space
|
||||
std::string labelID() const;
|
||||
|
||||
// Is this residue a single entity?
|
||||
bool isEntity() const;
|
||||
|
||||
bool isWater() const { return mCompoundID == "HOH"; }
|
||||
|
||||
const Structure &structure() const { return *mStructure; }
|
||||
|
||||
bool empty() const { return mStructure == nullptr; }
|
||||
|
||||
bool hasAlternateAtoms() const;
|
||||
|
||||
/// \brief Return the list of unique alt ID's present in this residue
|
||||
std::set<std::string> getAlternateIDs() const;
|
||||
|
||||
/// \brief Return the list of unique atom ID's
|
||||
std::set<std::string> getAtomIDs() const;
|
||||
|
||||
/// \brief Return the list of atoms having ID \a atomID
|
||||
AtomView getAtomsByID(const std::string &atomID) const;
|
||||
|
||||
// some routines for 3d work
|
||||
std::tuple<Point, float> centerAndRadius() const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Residue &res);
|
||||
|
||||
friend Structure;
|
||||
|
||||
bool operator==(const mmcif::Residue &rhs) const
|
||||
{
|
||||
return this == &rhs or (
|
||||
mStructure == rhs.mStructure and
|
||||
mSeqID == rhs.mSeqID and
|
||||
mAsymID == rhs.mAsymID and
|
||||
mCompoundID == rhs.mCompoundID and
|
||||
mAuthSeqID == rhs.mAuthSeqID);
|
||||
}
|
||||
|
||||
protected:
|
||||
Residue() {}
|
||||
|
||||
friend class Polymer;
|
||||
|
||||
const Structure *mStructure = nullptr;
|
||||
std::string mCompoundID, mAsymID;
|
||||
int mSeqID = 0;
|
||||
std::string mAuthSeqID;
|
||||
AtomView mAtoms;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// a monomer models a single Residue in a protein chain
|
||||
|
||||
class Monomer : public Residue
|
||||
{
|
||||
public:
|
||||
// Monomer();
|
||||
Monomer(const Monomer &rhs) = delete;
|
||||
Monomer &operator=(const Monomer &rhs) = delete;
|
||||
|
||||
Monomer(Monomer &&rhs);
|
||||
Monomer &operator=(Monomer &&rhs);
|
||||
|
||||
Monomer(const Polymer &polymer, size_t index, int seqID, const std::string &authSeqID,
|
||||
const std::string &compoundID);
|
||||
|
||||
bool is_first_in_chain() const;
|
||||
bool is_last_in_chain() const;
|
||||
|
||||
// convenience
|
||||
bool has_alpha() const;
|
||||
bool has_kappa() const;
|
||||
|
||||
// Assuming this is really an amino acid...
|
||||
|
||||
float phi() const;
|
||||
float psi() const;
|
||||
float alpha() const;
|
||||
float kappa() const;
|
||||
float tco() const;
|
||||
float omega() const;
|
||||
|
||||
// torsion angles
|
||||
size_t nrOfChis() const;
|
||||
float chi(size_t i) const;
|
||||
|
||||
bool isCis() const;
|
||||
|
||||
/// \brief Returns true if the four atoms C, CA, N and O are present
|
||||
bool isComplete() const;
|
||||
|
||||
/// \brief Returns true if any of the backbone atoms has an alternate
|
||||
bool hasAlternateBackboneAtoms() const;
|
||||
|
||||
Atom CAlpha() const { return atomByID("CA"); }
|
||||
Atom C() const { return atomByID("C"); }
|
||||
Atom N() const { return atomByID("N"); }
|
||||
Atom O() const { return atomByID("O"); }
|
||||
Atom H() const { return atomByID("H"); }
|
||||
|
||||
bool isBondedTo(const Monomer &rhs) const
|
||||
{
|
||||
return this != &rhs and areBonded(*this, rhs);
|
||||
}
|
||||
|
||||
static bool areBonded(const Monomer &a, const Monomer &b, float errorMargin = 0.5f);
|
||||
static bool isCis(const Monomer &a, const Monomer &b);
|
||||
static float omega(const Monomer &a, const Monomer &b);
|
||||
|
||||
// for LEU and VAL
|
||||
float chiralVolume() const;
|
||||
|
||||
bool operator==(const Monomer &rhs) const
|
||||
{
|
||||
return mPolymer == rhs.mPolymer and mIndex == rhs.mIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
const Polymer *mPolymer;
|
||||
size_t mIndex;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Polymer : public std::vector<Monomer>
|
||||
{
|
||||
public:
|
||||
Polymer(const Structure &s, const std::string &entityID, const std::string &asymID);
|
||||
|
||||
Polymer(const Polymer &) = delete;
|
||||
Polymer &operator=(const Polymer &) = delete;
|
||||
|
||||
// Polymer(Polymer&& rhs) = delete;
|
||||
// Polymer& operator=(Polymer&& rhs) = de;
|
||||
|
||||
Monomer &getBySeqID(int seqID);
|
||||
const Monomer &getBySeqID(int seqID) const;
|
||||
|
||||
Structure *structure() const { return mStructure; }
|
||||
|
||||
std::string asymID() const { return mAsymID; }
|
||||
std::string entityID() const { return mEntityID; }
|
||||
|
||||
std::string chainID() const;
|
||||
|
||||
int Distance(const Monomer &a, const Monomer &b) const;
|
||||
|
||||
private:
|
||||
Structure *mStructure;
|
||||
std::string mEntityID;
|
||||
std::string mAsymID;
|
||||
cif::RowSet mPolySeq;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Sugar and Branch, to describe glycosylation sites
|
||||
|
||||
class Branch;
|
||||
|
||||
class Sugar : public Residue
|
||||
{
|
||||
public:
|
||||
Sugar(const Branch &branch, const std::string &compoundID,
|
||||
const std::string &asymID, int authSeqID);
|
||||
|
||||
int num() const { return std::stoi(mAuthSeqID); }
|
||||
std::string name() const;
|
||||
|
||||
/// \brief Return the atom the C1 is linked to
|
||||
Atom getLink() const { return mLink; }
|
||||
void setLink(Atom link) { mLink = link; }
|
||||
|
||||
private:
|
||||
|
||||
const Branch &mBranch;
|
||||
Atom mLink;
|
||||
};
|
||||
|
||||
class Branch : public std::vector<Sugar>
|
||||
{
|
||||
public:
|
||||
Branch(Structure &structure, const std::string &asymID);
|
||||
|
||||
void linkAtoms();
|
||||
|
||||
std::string name() const;
|
||||
float weight() const;
|
||||
std::string asymID() const { return mAsymID; }
|
||||
|
||||
Structure &structure() { return *mStructure; }
|
||||
const Structure &structure() const { return *mStructure; }
|
||||
|
||||
Sugar &getSugarByNum(int nr);
|
||||
const Sugar &getSugarByNum(int nr) const;
|
||||
|
||||
private:
|
||||
friend Sugar;
|
||||
|
||||
std::string name(const Sugar &s) const;
|
||||
|
||||
Structure *mStructure;
|
||||
std::string mAsymID;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// file is a reference to the data stored in e.g. the cif file.
|
||||
// This object is not copyable.
|
||||
|
||||
class File : public cif::File
|
||||
{
|
||||
public:
|
||||
File() {}
|
||||
|
||||
File(const std::filesystem::path &path)
|
||||
{
|
||||
load(path);
|
||||
}
|
||||
|
||||
File(const char *data, size_t length)
|
||||
{
|
||||
load(data, length);
|
||||
}
|
||||
|
||||
File(const File &) = delete;
|
||||
File &operator=(const File &) = delete;
|
||||
|
||||
void load(const std::filesystem::path &p) override;
|
||||
void save(const std::filesystem::path &p) override;
|
||||
|
||||
void load(std::istream &is) override;
|
||||
|
||||
using cif::File::load;
|
||||
using cif::File::save;
|
||||
|
||||
cif::Datablock &data() { return front(); }
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
enum class StructureOpenOptions
|
||||
{
|
||||
SkipHydrogen = 1 << 0
|
||||
};
|
||||
|
||||
inline bool operator&(StructureOpenOptions a, StructureOpenOptions b)
|
||||
{
|
||||
return static_cast<int>(a) bitand static_cast<int>(b);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class Structure
|
||||
{
|
||||
public:
|
||||
Structure(cif::File &p, size_t modelNr = 1, StructureOpenOptions options = {})
|
||||
: Structure(p.front(), modelNr, options)
|
||||
{
|
||||
}
|
||||
|
||||
Structure(cif::Datablock &db, size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
|
||||
// Create a read-only clone of the current structure (for multithreaded calculations that move atoms)
|
||||
Structure(const Structure &);
|
||||
|
||||
Structure &operator=(const Structure &) = delete;
|
||||
~Structure();
|
||||
|
||||
const AtomView &atoms() const { return mAtoms; }
|
||||
// AtomView &atoms() { return mAtoms; }
|
||||
|
||||
EntityType getEntityTypeForEntityID(const std::string entityID) const;
|
||||
EntityType getEntityTypeForAsymID(const std::string asymID) const;
|
||||
|
||||
AtomView waters() const;
|
||||
|
||||
const std::list<Polymer> &polymers() const { return mPolymers; }
|
||||
std::list<Polymer> &polymers() { return mPolymers; }
|
||||
|
||||
Polymer &getPolymerByAsymID(const std::string &asymID);
|
||||
|
||||
const Polymer &getPolymerByAsymID(const std::string &asymID) const
|
||||
{
|
||||
return const_cast<Structure *>(this)->getPolymerByAsymID(asymID);
|
||||
}
|
||||
|
||||
const std::list<Branch> &branches() const { return mBranches; }
|
||||
std::list<Branch> &branches() { return mBranches; }
|
||||
|
||||
Branch &getBranchByAsymID(const std::string &asymID);
|
||||
const Branch &getBranchByAsymID(const std::string &asymID) const;
|
||||
|
||||
const std::vector<Residue> &nonPolymers() const { return mNonPolymers; }
|
||||
|
||||
Atom getAtomByID(const std::string &id) const;
|
||||
// Atom getAtomByLocation(Point pt, float maxDistance) const;
|
||||
|
||||
Atom getAtomByLabel(const std::string &atomID, const std::string &asymID,
|
||||
const std::string &compID, int seqID, const std::string &altID = "");
|
||||
|
||||
/// \brief Return the atom closest to point \a p
|
||||
Atom getAtomByPosition(Point p) const;
|
||||
|
||||
/// \brief Return the atom closest to point \a p with atom type \a type in a residue of type \a res_type
|
||||
Atom getAtomByPositionAndType(Point p, std::string_view type, std::string_view res_type) const;
|
||||
|
||||
/// \brief Get a non-poly residue for an asym with id \a asymID
|
||||
Residue &getResidue(const std::string &asymID)
|
||||
{
|
||||
return getResidue(asymID, 0, "");
|
||||
}
|
||||
|
||||
/// \brief Get a non-poly residue for an asym with id \a asymID
|
||||
const Residue &getResidue(const std::string &asymID) const
|
||||
{
|
||||
return getResidue(asymID, 0, "");
|
||||
}
|
||||
|
||||
/// \brief Get a residue for an asym with id \a asymID seq id \a seqID and authSeqID \a authSeqID
|
||||
Residue &getResidue(const std::string &asymID, int seqID, const std::string &authSeqID);
|
||||
|
||||
/// \brief Get a the single residue for an asym with id \a asymID seq id \a seqID and authSeqID \a authSeqID
|
||||
const Residue &getResidue(const std::string &asymID, int seqID, const std::string &authSeqID) const
|
||||
{
|
||||
return const_cast<Structure *>(this)->getResidue(asymID, seqID, authSeqID);
|
||||
}
|
||||
|
||||
/// \brief Get a residue for an asym with id \a asymID, compound id \a compID, seq id \a seqID and authSeqID \a authSeqID
|
||||
Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID, const std::string &authSeqID);
|
||||
|
||||
/// \brief Get a residue for an asym with id \a asymID, compound id \a compID, seq id \a seqID and authSeqID \a authSeqID
|
||||
const Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID, const std::string &authSeqID) const
|
||||
{
|
||||
return const_cast<Structure *>(this)->getResidue(asymID, compID, seqID, authSeqID);
|
||||
}
|
||||
|
||||
/// \brief Get a the residue for atom \a atom
|
||||
Residue &getResidue(const mmcif::Atom &atom)
|
||||
{
|
||||
return getResidue(atom.labelAsymID(), atom.labelCompID(), atom.labelSeqID(), atom.authSeqID());
|
||||
}
|
||||
|
||||
/// \brief Get a the residue for atom \a atom
|
||||
const Residue &getResidue(const mmcif::Atom &atom) const
|
||||
{
|
||||
return getResidue(atom.labelAsymID(), atom.labelCompID(), atom.labelSeqID(), atom.authSeqID());
|
||||
}
|
||||
|
||||
// Actions
|
||||
void removeAtom(Atom &a);
|
||||
void swapAtoms(Atom a1, Atom a2); // swap the labels for these atoms
|
||||
void moveAtom(Atom a, Point p); // move atom to a new location
|
||||
void changeResidue(Residue &res, const std::string &newCompound,
|
||||
const std::vector<std::tuple<std::string, std::string>> &remappedAtoms);
|
||||
|
||||
/// \brief Remove a residue, can be monomer or nonpoly
|
||||
///
|
||||
/// \param asym_id The asym ID
|
||||
/// \param seq_id The sequence ID
|
||||
void removeResidue(const std::string &asym_id, int seq_id, const std::string &auth_seq_id)
|
||||
{
|
||||
removeResidue(getResidue(asym_id, seq_id, auth_seq_id));
|
||||
}
|
||||
|
||||
/// \brief Create a new non-polymer entity, returns new ID
|
||||
/// \param mon_id The mon_id for the new nonpoly, must be an existing and known compound from CCD
|
||||
/// \return The ID of the created entity
|
||||
std::string createNonPolyEntity(const std::string &mon_id);
|
||||
|
||||
/// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atoms, returns asym_id.
|
||||
/// This method assumes you are copying data from one cif file to another.
|
||||
///
|
||||
/// \param entity_id The entity ID of the new nonpoly
|
||||
/// \param atoms The array of atom_site rows containing the data.
|
||||
/// \return The newly create asym ID
|
||||
std::string createNonpoly(const std::string &entity_id, const std::vector<mmcif::Atom> &atoms);
|
||||
|
||||
/// \brief Create a new NonPolymer struct_asym with atoms constructed from info in \a atom_info, returns asym_id.
|
||||
/// This method creates new atom records filled with info from the info.
|
||||
///
|
||||
/// \param entity_id The entity ID of the new nonpoly
|
||||
/// \param atoms The array of sets of cif::item data containing the data for the atoms.
|
||||
/// \return The newly create asym ID
|
||||
std::string createNonpoly(const std::string &entity_id, std::vector<std::vector<cif::Item>> &atom_info);
|
||||
|
||||
/// \brief Create a new (sugar) branch with one first NAG containing atoms constructed from \a nag_atom_info
|
||||
Branch &createBranch(std::vector<std::vector<cif::Item>> &nag_atom_info);
|
||||
|
||||
/// \brief Extend an existing (sugar) branch identified by \a asymID with one sugar containing atoms constructed from \a atom_info
|
||||
///
|
||||
/// \param asym_id The asym id of the branch to extend
|
||||
/// \param atom_info Array containing the info for the atoms to construct for the new sugar
|
||||
/// \param link_sugar The sugar to link to, note: this is the sugar number (1 based)
|
||||
/// \param link_atom The atom id of the atom linked in the sugar
|
||||
Branch &extendBranch(const std::string &asym_id, std::vector<std::vector<cif::Item>> &atom_info,
|
||||
int link_sugar, const std::string &link_atom);
|
||||
|
||||
/// \brief Remove \a branch
|
||||
void removeBranch(Branch &branch);
|
||||
|
||||
/// \brief Remove residue \a res
|
||||
///
|
||||
/// \param res The residue to remove
|
||||
void removeResidue(mmcif::Residue &res);
|
||||
|
||||
/// \brief Translate the coordinates of all atoms in the structure by \a t
|
||||
void translate(Point t);
|
||||
|
||||
/// \brief Rotate the coordinates of all atoms in the structure by \a q
|
||||
void rotate(Quaternion t);
|
||||
|
||||
/// \brief Translate and rotate the coordinates of all atoms in the structure by \a t and \a q
|
||||
void translateAndRotate(Point t, Quaternion q);
|
||||
|
||||
/// \brief Translate, rotate and translate again the coordinates of all atoms in the structure by \a t1 , \a q and \a t2
|
||||
void translateRotateAndTranslate(Point t1, Quaternion q, Point t2);
|
||||
|
||||
const std::vector<Residue> &getNonPolymers() const { return mNonPolymers; }
|
||||
|
||||
void cleanupEmptyCategories();
|
||||
|
||||
/// \brief Direct access to underlying data
|
||||
cif::Category &category(std::string_view name) const
|
||||
{
|
||||
return mDb[name];
|
||||
}
|
||||
|
||||
cif::Datablock &datablock() const
|
||||
{
|
||||
return mDb;
|
||||
}
|
||||
|
||||
void validateAtoms() const;
|
||||
|
||||
private:
|
||||
friend Polymer;
|
||||
friend Residue;
|
||||
|
||||
std::string insertCompound(const std::string &compoundID, bool isEntity);
|
||||
|
||||
std::string createEntityForBranch(Branch &branch);
|
||||
|
||||
void loadData();
|
||||
|
||||
void loadAtomsForModel(StructureOpenOptions options);
|
||||
|
||||
template<typename... Args>
|
||||
Atom& emplace_atom(Args ...args)
|
||||
{
|
||||
return emplace_atom(Atom{std::forward<Args>(args)...});
|
||||
}
|
||||
|
||||
Atom &emplace_atom(Atom &&atom);
|
||||
|
||||
cif::Datablock &mDb;
|
||||
size_t mModelNr;
|
||||
AtomView mAtoms;
|
||||
std::vector<size_t> mAtomIndex;
|
||||
std::list<Polymer> mPolymers;
|
||||
std::list<Branch> mBranches;
|
||||
std::vector<Residue> mNonPolymers;
|
||||
};
|
||||
|
||||
} // namespace mmcif
|
||||
144
include/cif++/Symmetry.hpp
Normal file
144
include/cif++/Symmetry.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
#include "CifUtils.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
enum class SpacegroupName
|
||||
{
|
||||
full, xHM, Hall
|
||||
};
|
||||
|
||||
struct Spacegroup
|
||||
{
|
||||
const char* name;
|
||||
const char* xHM;
|
||||
const char* Hall;
|
||||
int nr;
|
||||
};
|
||||
|
||||
CIFPP_EXPORT extern const Spacegroup kSpaceGroups[];
|
||||
CIFPP_EXPORT extern const std::size_t kNrOfSpaceGroups;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct SymopData
|
||||
{
|
||||
constexpr SymopData(const std::array<int,15>& data)
|
||||
: m_packed((data[ 0] & 0x03ULL) << 34 bitor
|
||||
(data[ 1] & 0x03ULL) << 32 bitor
|
||||
(data[ 2] & 0x03ULL) << 30 bitor
|
||||
(data[ 3] & 0x03ULL) << 28 bitor
|
||||
(data[ 4] & 0x03ULL) << 26 bitor
|
||||
(data[ 5] & 0x03ULL) << 24 bitor
|
||||
(data[ 6] & 0x03ULL) << 22 bitor
|
||||
(data[ 7] & 0x03ULL) << 20 bitor
|
||||
(data[ 8] & 0x03ULL) << 18 bitor
|
||||
(data[ 9] & 0x07ULL) << 15 bitor
|
||||
(data[10] & 0x07ULL) << 12 bitor
|
||||
(data[11] & 0x07ULL) << 9 bitor
|
||||
(data[12] & 0x07ULL) << 6 bitor
|
||||
(data[13] & 0x07ULL) << 3 bitor
|
||||
(data[14] & 0x07ULL) << 0)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const SymopData& rhs) const
|
||||
{
|
||||
return m_packed == rhs.m_packed;
|
||||
}
|
||||
|
||||
std::array<int,15> data() const
|
||||
{
|
||||
return {
|
||||
static_cast<int>(m_packed >> 34) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 32) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 30) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 28) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 26) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 24) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 22) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 20) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 18) bitand 0x03,
|
||||
static_cast<int>(m_packed >> 15) bitand 0x07,
|
||||
static_cast<int>(m_packed >> 12) bitand 0x07,
|
||||
static_cast<int>(m_packed >> 9) bitand 0x07,
|
||||
static_cast<int>(m_packed >> 6) bitand 0x07,
|
||||
static_cast<int>(m_packed >> 3) bitand 0x07,
|
||||
static_cast<int>(m_packed >> 0) bitand 0x07,
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend struct SymopDataBlock;
|
||||
|
||||
const uint64_t kPackMask = (~0ULL >> (64-36));
|
||||
|
||||
SymopData(uint64_t v)
|
||||
: m_packed(v bitand kPackMask) {}
|
||||
|
||||
uint64_t m_packed;
|
||||
};
|
||||
|
||||
struct SymopDataBlock
|
||||
{
|
||||
constexpr SymopDataBlock(int spacegroup, int rotational_number, const std::array<int,15>& rt_data)
|
||||
: m_v((spacegroup & 0xffffULL) << 48 bitor
|
||||
(rotational_number & 0xffULL) << 40 bitor
|
||||
SymopData(rt_data).m_packed)
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t spacegroup() const { return m_v >> 48; }
|
||||
SymopData symop() const { return SymopData(m_v); }
|
||||
uint8_t rotational_number() const { return (m_v >> 40) bitand 0xff; }
|
||||
|
||||
private:
|
||||
uint64_t m_v;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SymopDataBlock) == sizeof(uint64_t), "Size of SymopData is wrong");
|
||||
|
||||
CIFPP_EXPORT extern const SymopDataBlock kSymopNrTable[];
|
||||
CIFPP_EXPORT extern const std::size_t kSymopNrTableSize;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code, using SpacegroupName::full
|
||||
int GetSpacegroupNumber(std::string spacegroup, SpacegroupName type); // alternative for clipper's parsing code
|
||||
|
||||
}
|
||||
57
include/cif++/TlsParser.hpp
Normal file
57
include/cif++/TlsParser.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
extern const int
|
||||
kResidueNrWildcard,
|
||||
kNoSeqNum;
|
||||
|
||||
struct TLSSelection;
|
||||
typedef std::unique_ptr<TLSSelection> TLSSelectionPtr;
|
||||
|
||||
struct TLSResidue;
|
||||
|
||||
struct TLSSelection
|
||||
{
|
||||
virtual ~TLSSelection() {}
|
||||
virtual void CollectResidues(cif::Datablock& db, std::vector<TLSResidue>& residues, std::size_t indentLevel = 0) const = 0;
|
||||
std::vector<std::tuple<std::string,int,int>> GetRanges(cif::Datablock& db, bool pdbNamespace) const;
|
||||
};
|
||||
|
||||
// Low level: get the selections
|
||||
TLSSelectionPtr ParseSelectionDetails(const std::string& program, const std::string& selection);
|
||||
|
||||
}
|
||||
12
libcifpp.pc.in
Normal file
12
libcifpp.pc.in
Normal file
@@ -0,0 +1,12 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
datalibdir=@datarootdir@/libcifpp
|
||||
|
||||
Name: libcifpp
|
||||
Description: C++ library for the manipulation of mmCIF files.
|
||||
Version: @PACKAGE_VERSION@
|
||||
|
||||
Libs: -L${libdir} -lcifpp -lboost_regex -lboost_iostreams
|
||||
Cflags: -I${includedir} -pthread
|
||||
36
rsrc/isomers.txt
Normal file
36
rsrc/isomers.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
13R:13S
|
||||
1AB:IMR
|
||||
558:559
|
||||
6PG:LG6
|
||||
A:AMP
|
||||
ABA:DBB
|
||||
ALO:DTH
|
||||
BDR:BXX
|
||||
C:C5P
|
||||
CBI:MAL:MAB
|
||||
COA:COZ
|
||||
COM:COM
|
||||
CTL:TTL
|
||||
CTR:MLR
|
||||
DIL:IIL
|
||||
DNE:NLE
|
||||
DTL:MRY
|
||||
DX5:LXP:R5P
|
||||
G:G25
|
||||
GDC:GDD
|
||||
GDM:GMY
|
||||
GDU:GUD:UFM:UPG
|
||||
HY0:HYG
|
||||
I:IMP
|
||||
LLT:THM
|
||||
LPK:LTG
|
||||
M13:MDM
|
||||
PDE:PNE
|
||||
QDN:QI9
|
||||
R5A:R5B
|
||||
RUB:XBP
|
||||
RWF:SWF
|
||||
TBE:TBI
|
||||
U:U5P
|
||||
U2F:UP1:UPF
|
||||
UD1:UD2
|
||||
3098
rsrc/mmcif_ddl.dic
Normal file
3098
rsrc/mmcif_ddl.dic
Normal file
File diff suppressed because it is too large
Load Diff
147200
rsrc/mmcif_pdbx_v50.dic
Normal file
147200
rsrc/mmcif_pdbx_v50.dic
Normal file
File diff suppressed because it is too large
Load Diff
1140
src/AtomType.cpp
Normal file
1140
src/AtomType.cpp
Normal file
File diff suppressed because it is too large
Load Diff
500
src/BondMap.cpp
Normal file
500
src/BondMap.cpp
Normal file
@@ -0,0 +1,500 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
|
||||
#include "cif++/BondMap.hpp"
|
||||
#include "cif++/Cif++.hpp"
|
||||
#include "cif++/CifUtils.hpp"
|
||||
#include "cif++/Compound.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
union IDType
|
||||
{
|
||||
IDType()
|
||||
: id_n(0)
|
||||
{
|
||||
}
|
||||
IDType(const IDType &rhs)
|
||||
: id_n(rhs.id_n)
|
||||
{
|
||||
}
|
||||
IDType(const std::string &s)
|
||||
: IDType()
|
||||
{
|
||||
assert(s.length() <= 4);
|
||||
if (s.length() > 4)
|
||||
throw BondMapException("Atom ID '" + s + "' is too long");
|
||||
std::copy(s.begin(), s.end(), id_s);
|
||||
}
|
||||
|
||||
IDType &operator=(const IDType &rhs)
|
||||
{
|
||||
id_n = rhs.id_n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
IDType &operator=(const std::string &s)
|
||||
{
|
||||
id_n = 0;
|
||||
assert(s.length() <= 4);
|
||||
if (s.length() > 4)
|
||||
throw BondMapException("Atom ID '" + s + "' is too long");
|
||||
std::copy(s.begin(), s.end(), id_s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator<(const IDType &rhs) const
|
||||
{
|
||||
return id_n < rhs.id_n;
|
||||
}
|
||||
|
||||
bool operator<=(const IDType &rhs) const
|
||||
{
|
||||
return id_n <= rhs.id_n;
|
||||
}
|
||||
|
||||
bool operator==(const IDType &rhs) const
|
||||
{
|
||||
return id_n == rhs.id_n;
|
||||
}
|
||||
|
||||
bool operator!=(const IDType &rhs) const
|
||||
{
|
||||
return id_n != rhs.id_n;
|
||||
}
|
||||
|
||||
char id_s[4];
|
||||
uint32_t id_n;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IDType) == 4, "atom_id_type should be 4 bytes");
|
||||
} // namespace
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct CompoundBondInfo
|
||||
{
|
||||
IDType mID;
|
||||
std::set<std::tuple<uint32_t, uint32_t>> mBonded;
|
||||
|
||||
bool bonded(uint32_t a1, uint32_t a2) const
|
||||
{
|
||||
return mBonded.count({a1, a2}) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class CompoundBondMap
|
||||
{
|
||||
public:
|
||||
static CompoundBondMap &instance()
|
||||
{
|
||||
static std::unique_ptr<CompoundBondMap> s_instance(new CompoundBondMap);
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
bool bonded(const std::string &compoundID, const std::string &atomID1, const std::string &atomID2);
|
||||
|
||||
private:
|
||||
CompoundBondMap() {}
|
||||
|
||||
uint32_t getAtomID(const std::string &atomID)
|
||||
{
|
||||
IDType id(atomID);
|
||||
|
||||
uint32_t result;
|
||||
|
||||
auto i = mAtomIDIndex.find(id);
|
||||
if (i == mAtomIDIndex.end())
|
||||
{
|
||||
result = uint32_t(mAtomIDIndex.size());
|
||||
mAtomIDIndex[id] = result;
|
||||
}
|
||||
else
|
||||
result = i->second;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::map<IDType, uint32_t> mAtomIDIndex;
|
||||
std::vector<CompoundBondInfo> mCompounds;
|
||||
std::mutex mMutex;
|
||||
};
|
||||
|
||||
bool CompoundBondMap::bonded(const std::string &compoundID, const std::string &atomID1, const std::string &atomID2)
|
||||
{
|
||||
std::lock_guard lock(mMutex);
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
IDType id(compoundID);
|
||||
uint32_t a1 = getAtomID(atomID1);
|
||||
uint32_t a2 = getAtomID(atomID2);
|
||||
if (a1 > a2)
|
||||
std::swap(a1, a2);
|
||||
|
||||
for (auto &bi : mCompounds)
|
||||
{
|
||||
if (bi.mID != id)
|
||||
continue;
|
||||
|
||||
return bi.bonded(a1, a2);
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
|
||||
// not found in our cache, calculate
|
||||
CompoundBondInfo bondInfo{id};
|
||||
|
||||
auto compound = mmcif::CompoundFactory::instance().create(compoundID);
|
||||
if (not compound)
|
||||
{
|
||||
if (cif::VERBOSE >= 0)
|
||||
std::cerr << "Missing compound bond info for " << compoundID << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &atom : compound->bonds())
|
||||
{
|
||||
uint32_t ca1 = getAtomID(atom.atomID[0]);
|
||||
uint32_t ca2 = getAtomID(atom.atomID[1]);
|
||||
if (ca1 > ca2)
|
||||
std::swap(ca1, ca2);
|
||||
|
||||
bondInfo.mBonded.insert({ca1, ca2});
|
||||
result = result or (a1 == ca1 and a2 == ca2);
|
||||
}
|
||||
}
|
||||
|
||||
mCompounds.push_back(bondInfo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BondMap::BondMap(const Structure &p)
|
||||
{
|
||||
auto &compoundBondInfo = CompoundBondMap::instance();
|
||||
|
||||
auto atoms = p.atoms();
|
||||
dim = uint32_t(atoms.size());
|
||||
|
||||
// bond = std::vector<bool>(dim * (dim - 1), false);
|
||||
|
||||
for (auto &atom : atoms)
|
||||
index[atom.id()] = uint32_t(index.size());
|
||||
|
||||
auto bindAtoms = [this](const std::string &a, const std::string &b)
|
||||
{
|
||||
uint32_t ixa = index[a];
|
||||
uint32_t ixb = index[b];
|
||||
|
||||
bond.insert(key(ixa, ixb));
|
||||
};
|
||||
|
||||
auto linkAtoms = [this, &bindAtoms](const std::string &a, const std::string &b)
|
||||
{
|
||||
bindAtoms(a, b);
|
||||
|
||||
link[a].insert(b);
|
||||
link[b].insert(a);
|
||||
};
|
||||
|
||||
cif::Datablock &db = p.datablock();
|
||||
|
||||
// collect all compounds first
|
||||
std::set<std::string> compounds;
|
||||
for (auto c : db["chem_comp"])
|
||||
compounds.insert(c["id"].as<std::string>());
|
||||
|
||||
// make sure we also have all residues in the polyseq
|
||||
for (auto m : db["entity_poly_seq"])
|
||||
{
|
||||
std::string c = m["mon_id"].as<std::string>();
|
||||
if (compounds.count(c))
|
||||
continue;
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << std::endl;
|
||||
compounds.insert(c);
|
||||
}
|
||||
|
||||
cif::Progress progress(compounds.size(), "Creating bond map");
|
||||
|
||||
// some helper indices to speed things up a bit
|
||||
std::map<std::tuple<std::string, int, std::string, std::string>, std::string> atomMapByAsymSeqAndAtom;
|
||||
for (auto &a : p.atoms())
|
||||
{
|
||||
auto key = make_tuple(a.labelAsymID(), a.labelSeqID(), a.labelAtomID(), a.authSeqID());
|
||||
atomMapByAsymSeqAndAtom[key] = a.id();
|
||||
}
|
||||
|
||||
// first link all residues in a polyseq
|
||||
|
||||
std::string lastAsymID, lastAuthSeqID;
|
||||
int lastSeqID = 0;
|
||||
for (const auto &[asymID, seqID, authSeqID] : db["pdbx_poly_seq_scheme"].rows<std::string,int,std::string>("asym_id", "seq_id", "pdb_seq_num"))
|
||||
{
|
||||
if (asymID != lastAsymID) // first in a new sequece
|
||||
{
|
||||
lastAsymID = asymID;
|
||||
lastSeqID = seqID;
|
||||
lastAuthSeqID = authSeqID;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto kc = make_tuple(asymID, lastSeqID, "C", lastAuthSeqID);
|
||||
auto kn = make_tuple(asymID, seqID, "N", authSeqID);
|
||||
|
||||
if (atomMapByAsymSeqAndAtom.count(kc) and atomMapByAsymSeqAndAtom.count(kn))
|
||||
{
|
||||
auto c = atomMapByAsymSeqAndAtom.at(kc);
|
||||
auto n = atomMapByAsymSeqAndAtom.at(kn);
|
||||
|
||||
bindAtoms(c, n);
|
||||
}
|
||||
// if (not(c.empty() or n.empty()))
|
||||
|
||||
lastSeqID = seqID;
|
||||
lastAuthSeqID = authSeqID;
|
||||
}
|
||||
|
||||
for (auto l : db["struct_conn"])
|
||||
{
|
||||
std::string asym1, asym2, atomId1, atomId2;
|
||||
int seqId1 = 0, seqId2 = 0;
|
||||
std::string authSeqId1, authSeqId2;
|
||||
|
||||
cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2, authSeqId1, authSeqId2) =
|
||||
l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id",
|
||||
"ptnr1_label_atom_id", "ptnr2_label_atom_id",
|
||||
"ptnr1_label_seq_id", "ptnr2_label_seq_id",
|
||||
"ptnr1_auth_seq_id", "ptnr2_auth_seq_id");
|
||||
|
||||
auto ka = make_tuple(asym1, seqId1, atomId1, authSeqId1);
|
||||
auto kb = make_tuple(asym2, seqId2, atomId2, authSeqId2);
|
||||
|
||||
if (atomMapByAsymSeqAndAtom.count(ka) and atomMapByAsymSeqAndAtom.count(kb))
|
||||
{
|
||||
auto a = atomMapByAsymSeqAndAtom.at(ka);
|
||||
auto b = atomMapByAsymSeqAndAtom.at(kb);
|
||||
|
||||
linkAtoms(a, b);
|
||||
}
|
||||
|
||||
// std::string a = atomMapByAsymSeqAndAtom.at(make_tuple(asym1, seqId1, atomId1, authSeqId1));
|
||||
// std::string b = atomMapByAsymSeqAndAtom.at(make_tuple(asym2, seqId2, atomId2, authSeqId2));
|
||||
// if (not(a.empty() or b.empty()))
|
||||
// linkAtoms(a, b);
|
||||
}
|
||||
|
||||
// then link all atoms in the compounds
|
||||
|
||||
for (auto c : compounds)
|
||||
{
|
||||
if (c == "HOH" or c == "H2O" or c == "WAT")
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::cerr << "skipping water in bond map calculation" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto bonded = [c, &compoundBondInfo](const Atom &a, const Atom &b)
|
||||
{
|
||||
auto label_a = a.labelAtomID();
|
||||
auto label_b = b.labelAtomID();
|
||||
|
||||
return compoundBondInfo.bonded(c, label_a, label_b);
|
||||
};
|
||||
|
||||
// loop over poly_seq_scheme
|
||||
for (auto r : db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c))
|
||||
{
|
||||
std::string asymID;
|
||||
int seqID;
|
||||
cif::tie(asymID, seqID) = r.get("asym_id", "seq_id");
|
||||
|
||||
std::vector<Atom> rAtoms;
|
||||
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
|
||||
[&](auto &a)
|
||||
{ return a.labelAsymID() == asymID and a.labelSeqID() == seqID; });
|
||||
|
||||
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
|
||||
{
|
||||
for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
|
||||
{
|
||||
if (bonded(rAtoms[i], rAtoms[j]))
|
||||
bindAtoms(rAtoms[i].id(), rAtoms[j].id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loop over pdbx_nonpoly_scheme
|
||||
for (auto r : db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c))
|
||||
{
|
||||
std::string asymID;
|
||||
cif::tie(asymID) = r.get("asym_id");
|
||||
|
||||
std::vector<Atom> rAtoms;
|
||||
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
|
||||
[&](auto &a)
|
||||
{ return a.labelAsymID() == asymID; });
|
||||
|
||||
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
|
||||
{
|
||||
for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
|
||||
{
|
||||
if (bonded(rAtoms[i], rAtoms[j]))
|
||||
{
|
||||
uint32_t ixa = index[rAtoms[i].id()];
|
||||
uint32_t ixb = index[rAtoms[j].id()];
|
||||
|
||||
bond.insert(key(ixa, ixb));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loop over pdbx_branch_scheme
|
||||
for (const auto &[asym_id, pdb_seq_num] : db["pdbx_branch_scheme"].find<std::string,std::string>(cif::Key("mon_id") == c, "asym_id", "pdb_seq_num"))
|
||||
{
|
||||
std::vector<Atom> rAtoms;
|
||||
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
|
||||
[&](const Atom &a)
|
||||
{ return a.labelAsymID() == asym_id and a.authSeqID() == pdb_seq_num; });
|
||||
|
||||
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
|
||||
{
|
||||
for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
|
||||
{
|
||||
if (bonded(rAtoms[i], rAtoms[j]))
|
||||
{
|
||||
uint32_t ixa = index[rAtoms[i].id()];
|
||||
uint32_t ixb = index[rAtoms[j].id()];
|
||||
|
||||
bond.insert(key(ixa, ixb));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start by creating an index for single bonds
|
||||
|
||||
std::multimap<uint32_t, uint32_t> b1_2;
|
||||
for (auto &bk : bond)
|
||||
{
|
||||
uint32_t a, b;
|
||||
std::tie(a, b) = dekey(bk);
|
||||
|
||||
b1_2.insert({a, b});
|
||||
b1_2.insert({b, a});
|
||||
}
|
||||
|
||||
std::multimap<uint32_t, uint32_t> b1_3;
|
||||
for (uint32_t i = 0; i < dim; ++i)
|
||||
{
|
||||
auto a = b1_2.equal_range(i);
|
||||
|
||||
std::vector<uint32_t> s;
|
||||
for (auto j = a.first; j != a.second; ++j)
|
||||
s.push_back(j->second);
|
||||
|
||||
for (size_t si1 = 0; si1 + 1 < s.size(); ++si1)
|
||||
{
|
||||
for (size_t si2 = si1 + 1; si2 < s.size(); ++si2)
|
||||
{
|
||||
uint32_t x = s[si1];
|
||||
uint32_t y = s[si2];
|
||||
|
||||
if (isBonded(x, y))
|
||||
continue;
|
||||
|
||||
b1_3.insert({x, y});
|
||||
b1_3.insert({y, x});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < dim; ++i)
|
||||
{
|
||||
auto a1 = b1_2.equal_range(i);
|
||||
auto a2 = b1_3.equal_range(i);
|
||||
|
||||
for (auto ai1 = a1.first; ai1 != a1.second; ++ai1)
|
||||
{
|
||||
for (auto ai2 = a2.first; ai2 != a2.second; ++ai2)
|
||||
{
|
||||
uint32_t b1 = ai1->second;
|
||||
uint32_t b2 = ai2->second;
|
||||
|
||||
if (isBonded(b1, b2))
|
||||
continue;
|
||||
|
||||
bond_1_4.insert(key(b1, b2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> BondMap::linked(const Atom &a) const
|
||||
{
|
||||
auto i = link.find(a.id());
|
||||
|
||||
std::vector<std::string> result;
|
||||
|
||||
if (i != link.end())
|
||||
result = std::vector<std::string>(i->second.begin(), i->second.end());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> BondMap::atomIDsForCompound(const std::string &compoundID)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
auto *compound = mmcif::CompoundFactory::instance().create(compoundID);
|
||||
|
||||
if (compound == nullptr)
|
||||
throw BondMapException("Missing bond information for compound " + compoundID);
|
||||
|
||||
for (auto &compAtom : compound->atoms())
|
||||
result.push_back(compAtom.id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace mmcif
|
||||
3649
src/Cif++.cpp
Normal file
3649
src/Cif++.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3984
src/Cif2PDB.cpp
Normal file
3984
src/Cif2PDB.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1331
src/CifParser.cpp
Normal file
1331
src/CifParser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1284
src/CifUtils.cpp
Normal file
1284
src/CifUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
435
src/CifValidator.cpp
Normal file
435
src/CifValidator.cpp
Normal file
@@ -0,0 +1,435 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/iostreams/filter/gzip.hpp>
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
#include "cif++/CifParser.hpp"
|
||||
#include "cif++/CifValidator.hpp"
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
namespace fs = std::filesystem;
|
||||
namespace io = boost::iostreams;
|
||||
|
||||
extern int VERBOSE;
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
ValidationError::ValidationError(const std::string &msg)
|
||||
: mMsg(msg)
|
||||
{
|
||||
}
|
||||
|
||||
ValidationError::ValidationError(const std::string &cat, const std::string &item, const std::string &msg)
|
||||
: mMsg("When validating _" + cat + '.' + item + ": " + msg)
|
||||
{
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
DDL_PrimitiveType mapToPrimitiveType(std::string_view s)
|
||||
{
|
||||
DDL_PrimitiveType result;
|
||||
if (iequals(s, "char"))
|
||||
result = DDL_PrimitiveType::Char;
|
||||
else if (iequals(s, "uchar"))
|
||||
result = DDL_PrimitiveType::UChar;
|
||||
else if (iequals(s, "numb"))
|
||||
result = DDL_PrimitiveType::Numb;
|
||||
else
|
||||
throw ValidationError("Not a known primitive type");
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
int ValidateType::compare(const char *a, const char *b) const
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (*a == 0)
|
||||
result = *b == 0 ? 0 : -1;
|
||||
else if (*b == 0)
|
||||
result = *a == 0 ? 0 : +1;
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (mPrimitiveType)
|
||||
{
|
||||
case DDL_PrimitiveType::Numb:
|
||||
{
|
||||
double da = strtod(a, nullptr);
|
||||
double db = strtod(b, nullptr);
|
||||
|
||||
auto d = da - db;
|
||||
if (std::abs(d) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
if (d > 0)
|
||||
result = 1;
|
||||
else if (d < 0)
|
||||
result = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DDL_PrimitiveType::UChar:
|
||||
case DDL_PrimitiveType::Char:
|
||||
{
|
||||
// CIF is guaranteed to have ascii only, therefore this primitive code will do
|
||||
// also, we're collapsing spaces
|
||||
|
||||
auto ai = a, bi = b;
|
||||
for (;;)
|
||||
{
|
||||
if (*ai == 0)
|
||||
{
|
||||
if (*bi != 0)
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
else if (*bi == 0)
|
||||
{
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
char ca = *ai;
|
||||
char cb = *bi;
|
||||
|
||||
if (mPrimitiveType == DDL_PrimitiveType::UChar)
|
||||
{
|
||||
ca = tolower(ca);
|
||||
cb = tolower(cb);
|
||||
}
|
||||
|
||||
result = ca - cb;
|
||||
|
||||
if (result != 0)
|
||||
break;
|
||||
|
||||
if (ca == ' ')
|
||||
{
|
||||
while (ai[1] == ' ')
|
||||
++ai;
|
||||
while (bi[1] == ' ')
|
||||
++bi;
|
||||
}
|
||||
|
||||
++ai;
|
||||
++bi;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::invalid_argument &ex)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
//void ValidateItem::addLinked(ValidateItem* parent, const std::string& parentItem, const std::string& childItem)
|
||||
//{
|
||||
//// if (mParent != nullptr and VERBOSE)
|
||||
//// cerr << "replacing parent in " << mCategory->mName << " from " << mParent->mCategory->mName << " to " << parent->mCategory->mName << endl;
|
||||
//// mParent = parent;
|
||||
//
|
||||
// if (mType == nullptr and parent != nullptr)
|
||||
// mType = parent->mType;
|
||||
//
|
||||
// if (parent != nullptr)
|
||||
// {
|
||||
// mLinked.push_back({parent, parentItem, childItem});
|
||||
//
|
||||
// parent->mChildren.insert(this);
|
||||
////
|
||||
//// if (mCategory->mKeys == std::vector<std::string>{mTag})
|
||||
//// parent->mForeignKeys.insert(this);
|
||||
// }
|
||||
//}
|
||||
|
||||
void ValidateItem::operator()(std::string value) const
|
||||
{
|
||||
if (not value.empty() and value != "?" and value != ".")
|
||||
{
|
||||
if (mType != nullptr and not regex_match(value, mType->mRx))
|
||||
throw ValidationError(mCategory->mName, mTag, "Value '" + value + "' does not match type expression for type " + mType->mName);
|
||||
|
||||
if (not mEnums.empty())
|
||||
{
|
||||
if (mEnums.count(value) == 0)
|
||||
throw ValidationError(mCategory->mName, mTag, "Value '" + value + "' is not in the list of allowed values");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void ValidateCategory::addItemValidator(ValidateItem &&v)
|
||||
{
|
||||
if (v.mMandatory)
|
||||
mMandatoryFields.insert(v.mTag);
|
||||
|
||||
v.mCategory = this;
|
||||
|
||||
auto r = mItemValidators.insert(std::move(v));
|
||||
if (not r.second and VERBOSE >= 4)
|
||||
std::cout << "Could not add validator for item " << v.mTag << " to category " << mName << std::endl;
|
||||
}
|
||||
|
||||
const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) const
|
||||
{
|
||||
const ValidateItem *result = nullptr;
|
||||
auto i = mItemValidators.find(ValidateItem{std::string(tag)});
|
||||
if (i != mItemValidators.end())
|
||||
result = &*i;
|
||||
else if (VERBOSE > 4)
|
||||
std::cout << "No validator for tag " << tag << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
Validator::Validator(std::string_view name, std::istream &is)
|
||||
: mName(name)
|
||||
{
|
||||
DictParser p(*this, is);
|
||||
p.loadDictionary();
|
||||
}
|
||||
|
||||
Validator::~Validator()
|
||||
{
|
||||
}
|
||||
|
||||
void Validator::addTypeValidator(ValidateType &&v)
|
||||
{
|
||||
auto r = mTypeValidators.insert(std::move(v));
|
||||
if (not r.second and VERBOSE > 4)
|
||||
std::cout << "Could not add validator for type " << v.mName << std::endl;
|
||||
}
|
||||
|
||||
const ValidateType *Validator::getValidatorForType(std::string_view typeCode) const
|
||||
{
|
||||
const ValidateType *result = nullptr;
|
||||
|
||||
auto i = mTypeValidators.find(ValidateType{std::string(typeCode), DDL_PrimitiveType::Char, boost::regex()});
|
||||
if (i != mTypeValidators.end())
|
||||
result = &*i;
|
||||
else if (VERBOSE > 4)
|
||||
std::cout << "No validator for type " << typeCode << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Validator::addCategoryValidator(ValidateCategory &&v)
|
||||
{
|
||||
auto r = mCategoryValidators.insert(std::move(v));
|
||||
if (not r.second and VERBOSE > 4)
|
||||
std::cout << "Could not add validator for category " << v.mName << std::endl;
|
||||
}
|
||||
|
||||
const ValidateCategory *Validator::getValidatorForCategory(std::string_view category) const
|
||||
{
|
||||
const ValidateCategory *result = nullptr;
|
||||
auto i = mCategoryValidators.find(ValidateCategory{std::string(category)});
|
||||
if (i != mCategoryValidators.end())
|
||||
result = &*i;
|
||||
else if (VERBOSE > 4)
|
||||
std::cout << "No validator for category " << category << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
ValidateItem *Validator::getValidatorForItem(std::string_view tag) const
|
||||
{
|
||||
ValidateItem *result = nullptr;
|
||||
|
||||
std::string cat, item;
|
||||
std::tie(cat, item) = splitTagName(tag);
|
||||
|
||||
auto *cv = getValidatorForCategory(cat);
|
||||
if (cv != nullptr)
|
||||
result = const_cast<ValidateItem *>(cv->getValidatorForItem(item));
|
||||
|
||||
if (result == nullptr and VERBOSE > 4)
|
||||
std::cout << "No validator for item " << tag << std::endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Validator::addLinkValidator(ValidateLink &&v)
|
||||
{
|
||||
assert(v.mParentKeys.size() == v.mChildKeys.size());
|
||||
if (v.mParentKeys.size() != v.mChildKeys.size())
|
||||
throw std::runtime_error("unequal number of keys for parent and child in link");
|
||||
|
||||
auto pcv = getValidatorForCategory(v.mParentCategory);
|
||||
auto ccv = getValidatorForCategory(v.mChildCategory);
|
||||
|
||||
if (pcv == nullptr)
|
||||
throw std::runtime_error("unknown parent category " + v.mParentCategory);
|
||||
|
||||
if (ccv == nullptr)
|
||||
throw std::runtime_error("unknown child category " + v.mChildCategory);
|
||||
|
||||
for (size_t i = 0; i < v.mParentKeys.size(); ++i)
|
||||
{
|
||||
auto piv = pcv->getValidatorForItem(v.mParentKeys[i]);
|
||||
|
||||
if (piv == nullptr)
|
||||
throw std::runtime_error("unknown parent tag _" + v.mParentCategory + '.' + v.mParentKeys[i]);
|
||||
|
||||
auto civ = ccv->getValidatorForItem(v.mChildKeys[i]);
|
||||
if (civ == nullptr)
|
||||
throw std::runtime_error("unknown child tag _" + v.mChildCategory + '.' + v.mChildKeys[i]);
|
||||
|
||||
if (civ->mType == nullptr and piv->mType != nullptr)
|
||||
const_cast<ValidateItem *>(civ)->mType = piv->mType;
|
||||
}
|
||||
|
||||
mLinkValidators.emplace_back(std::move(v));
|
||||
}
|
||||
|
||||
std::vector<const ValidateLink *> Validator::getLinksForParent(std::string_view category) const
|
||||
{
|
||||
std::vector<const ValidateLink *> result;
|
||||
|
||||
for (auto &l : mLinkValidators)
|
||||
{
|
||||
if (l.mParentCategory == category)
|
||||
result.push_back(&l);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view category) const
|
||||
{
|
||||
std::vector<const ValidateLink *> result;
|
||||
|
||||
for (auto &l : mLinkValidators)
|
||||
{
|
||||
if (l.mChildCategory == category)
|
||||
result.push_back(&l);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Validator::reportError(const std::string &msg, bool fatal) const
|
||||
{
|
||||
if (mStrict or fatal)
|
||||
throw ValidationError(msg);
|
||||
else if (VERBOSE > 0)
|
||||
std::cerr << msg << std::endl;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
ValidatorFactory ValidatorFactory::sInstance;
|
||||
|
||||
ValidatorFactory::ValidatorFactory()
|
||||
{
|
||||
}
|
||||
|
||||
const Validator &ValidatorFactory::operator[](std::string_view dictionary)
|
||||
{
|
||||
std::lock_guard lock(mMutex);
|
||||
|
||||
for (auto &validator : mValidators)
|
||||
{
|
||||
if (iequals(validator.mName, dictionary))
|
||||
return validator;
|
||||
}
|
||||
|
||||
// not found, add it
|
||||
|
||||
fs::path dict_name(dictionary);
|
||||
|
||||
auto data = loadResource(dictionary);
|
||||
|
||||
if (not data and dict_name.extension().string() != ".dic")
|
||||
data = loadResource(dict_name.parent_path() / (dict_name.filename().string() + ".dic"));
|
||||
|
||||
if (data)
|
||||
mValidators.emplace_back(dictionary, *data);
|
||||
else
|
||||
{
|
||||
// might be a compressed dictionary on disk
|
||||
fs::path p = dictionary;
|
||||
if (p.extension() == ".dic")
|
||||
p = p.parent_path() / (p.filename().string() + ".gz");
|
||||
else
|
||||
p = p.parent_path() / (p.filename().string() + ".dic.gz");
|
||||
|
||||
#if defined(CACHE_DIR) and defined(DATA_DIR)
|
||||
if (not fs::exists(p))
|
||||
{
|
||||
for (const char *dir : {CACHE_DIR, DATA_DIR})
|
||||
{
|
||||
auto p2 = fs::path(dir) / p;
|
||||
if (fs::exists(p2))
|
||||
{
|
||||
swap(p, p2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fs::exists(p))
|
||||
{
|
||||
std::ifstream file(p, std::ios::binary);
|
||||
if (not file.is_open())
|
||||
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
|
||||
|
||||
io::filtering_stream<io::input> in;
|
||||
in.push(io::gzip_decompressor());
|
||||
in.push(file);
|
||||
|
||||
mValidators.emplace_back(dictionary, in);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Dictionary not found or defined (" + dict_name.string() + ")");
|
||||
}
|
||||
|
||||
assert(iequals(mValidators.back().mName, dictionary));
|
||||
|
||||
return mValidators.back();
|
||||
}
|
||||
|
||||
} // namespace cif
|
||||
754
src/Compound.cpp
Normal file
754
src/Compound.cpp
Normal file
@@ -0,0 +1,754 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
#include "cif++/CifParser.hpp"
|
||||
#include "cif++/CifUtils.hpp"
|
||||
#include "cif++/Compound.hpp"
|
||||
#include "cif++/Point.hpp"
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::string to_string(BondType bondType)
|
||||
{
|
||||
switch (bondType)
|
||||
{
|
||||
case BondType::sing: return "sing";
|
||||
case BondType::doub: return "doub";
|
||||
case BondType::trip: return "trip";
|
||||
case BondType::quad: return "quad";
|
||||
case BondType::arom: return "arom";
|
||||
case BondType::poly: return "poly";
|
||||
case BondType::delo: return "delo";
|
||||
case BondType::pi: return "pi";
|
||||
}
|
||||
throw std::invalid_argument("Invalid bondType");
|
||||
}
|
||||
|
||||
BondType from_string(const std::string &bondType)
|
||||
{
|
||||
if (cif::iequals(bondType, "sing"))
|
||||
return BondType::sing;
|
||||
if (cif::iequals(bondType, "doub"))
|
||||
return BondType::doub;
|
||||
if (cif::iequals(bondType, "trip"))
|
||||
return BondType::trip;
|
||||
if (cif::iequals(bondType, "quad"))
|
||||
return BondType::quad;
|
||||
if (cif::iequals(bondType, "arom"))
|
||||
return BondType::arom;
|
||||
if (cif::iequals(bondType, "poly"))
|
||||
return BondType::poly;
|
||||
if (cif::iequals(bondType, "delo"))
|
||||
return BondType::delo;
|
||||
if (cif::iequals(bondType, "pi"))
|
||||
return BondType::pi;
|
||||
throw std::invalid_argument("Invalid bondType: " + bondType);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Compound helper classes
|
||||
|
||||
struct CompoundAtomLess
|
||||
{
|
||||
bool operator()(const CompoundAtom &a, const CompoundAtom &b) const
|
||||
{
|
||||
int d = a.id.compare(b.id);
|
||||
if (d == 0)
|
||||
d = a.typeSymbol - b.typeSymbol;
|
||||
return d < 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct CompoundBondLess
|
||||
{
|
||||
bool operator()(const CompoundBond &a, const CompoundBond &b) const
|
||||
{
|
||||
int d = a.atomID[0].compare(b.atomID[0]);
|
||||
if (d == 0)
|
||||
d = a.atomID[1].compare(b.atomID[1]);
|
||||
if (d == 0)
|
||||
d = static_cast<int>(a.type) - static_cast<int>(b.type);
|
||||
return d < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Compound
|
||||
|
||||
Compound::Compound(cif::Datablock &db)
|
||||
{
|
||||
auto &chemComp = db["chem_comp"];
|
||||
|
||||
if (chemComp.size() != 1)
|
||||
throw std::runtime_error("Invalid compound file, chem_comp should contain a single row");
|
||||
|
||||
cif::tie(mID, mName, mType, mFormula, mFormulaWeight, mFormalCharge) =
|
||||
chemComp.front().get("id", "name", "type", "formula", "formula_weight", "pdbx_formal_charge");
|
||||
|
||||
// The name should not contain newline characters since that triggers validation errors later on
|
||||
ba::replace_all(mName, "\n", "");
|
||||
|
||||
mGroup = "non-polymer";
|
||||
|
||||
auto &chemCompAtom = db["chem_comp_atom"];
|
||||
for (auto row : chemCompAtom)
|
||||
{
|
||||
CompoundAtom atom;
|
||||
std::string typeSymbol;
|
||||
cif::tie(atom.id, typeSymbol, atom.charge, atom.aromatic, atom.leavingAtom, atom.stereoConfig, atom.x, atom.y, atom.z) =
|
||||
row.get("atom_id", "type_symbol", "charge", "pdbx_aromatic_flag", "pdbx_leaving_atom_flag", "pdbx_stereo_config",
|
||||
"model_Cartn_x", "model_Cartn_y", "model_Cartn_z");
|
||||
atom.typeSymbol = AtomTypeTraits(typeSymbol).type();
|
||||
mAtoms.push_back(std::move(atom));
|
||||
}
|
||||
|
||||
auto &chemCompBond = db["chem_comp_bond"];
|
||||
for (auto row : chemCompBond)
|
||||
{
|
||||
CompoundBond bond;
|
||||
std::string valueOrder;
|
||||
cif::tie(bond.atomID[0], bond.atomID[1], valueOrder, bond.aromatic, bond.stereoConfig) = row.get("atom_id_1", "atom_id_2", "value_order", "pdbx_aromatic_flag", "pdbx_stereo_config");
|
||||
bond.type = from_string(valueOrder);
|
||||
mBonds.push_back(std::move(bond));
|
||||
}
|
||||
}
|
||||
|
||||
Compound::Compound(cif::Datablock &db, const std::string &id, const std::string &name, const std::string &type, const std::string &group)
|
||||
: mID(id)
|
||||
, mName(name)
|
||||
, mType(type)
|
||||
, mGroup(group)
|
||||
{
|
||||
auto &chemCompAtom = db["chem_comp_atom"];
|
||||
for (auto row : chemCompAtom)
|
||||
{
|
||||
CompoundAtom atom;
|
||||
std::string typeSymbol;
|
||||
cif::tie(atom.id, typeSymbol, atom.charge, atom.x, atom.y, atom.z) =
|
||||
row.get("atom_id", "type_symbol", "charge", "x", "y", "z");
|
||||
atom.typeSymbol = AtomTypeTraits(typeSymbol).type();
|
||||
|
||||
mFormalCharge += atom.charge;
|
||||
mFormulaWeight += AtomTypeTraits(atom.typeSymbol).weight();
|
||||
|
||||
mAtoms.push_back(std::move(atom));
|
||||
}
|
||||
|
||||
auto &chemCompBond = db["chem_comp_bond"];
|
||||
for (auto row : chemCompBond)
|
||||
{
|
||||
CompoundBond bond;
|
||||
std::string btype;
|
||||
cif::tie(bond.atomID[0], bond.atomID[1], btype, bond.aromatic) = row.get("atom_id_1", "atom_id_2", "type", "aromatic");
|
||||
|
||||
using cif::iequals;
|
||||
|
||||
if (iequals(btype, "single"))
|
||||
bond.type = BondType::sing;
|
||||
else if (iequals(btype, "double"))
|
||||
bond.type = BondType::doub;
|
||||
else if (iequals(btype, "triple"))
|
||||
bond.type = BondType::trip;
|
||||
else if (iequals(btype, "deloc") or iequals(btype, "aromat") or iequals(btype, "aromatic"))
|
||||
bond.type = BondType::delo;
|
||||
else
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::cerr << "Unimplemented chem_comp_bond.type " << btype << " in " << id << std::endl;
|
||||
bond.type = BondType::sing;
|
||||
}
|
||||
mBonds.push_back(std::move(bond));
|
||||
}
|
||||
}
|
||||
|
||||
CompoundAtom Compound::getAtomByID(const std::string &atomID) const
|
||||
{
|
||||
CompoundAtom result = {};
|
||||
for (auto &a : mAtoms)
|
||||
{
|
||||
if (a.id == atomID)
|
||||
{
|
||||
result = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.id != atomID)
|
||||
throw std::out_of_range("No atom " + atomID + " in Compound " + mID);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Compound::atomsBonded(const std::string &atomId_1, const std::string &atomId_2) const
|
||||
{
|
||||
auto i = find_if(mBonds.begin(), mBonds.end(),
|
||||
[&](const CompoundBond &b) {
|
||||
return (b.atomID[0] == atomId_1 and b.atomID[1] == atomId_2) or (b.atomID[0] == atomId_2 and b.atomID[1] == atomId_1);
|
||||
});
|
||||
|
||||
return i != mBonds.end();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// a factory class to generate compounds
|
||||
|
||||
CIFPP_EXPORT const std::map<std::string, char> kAAMap{
|
||||
{"ALA", 'A'},
|
||||
{"ARG", 'R'},
|
||||
{"ASN", 'N'},
|
||||
{"ASP", 'D'},
|
||||
{"CYS", 'C'},
|
||||
{"GLN", 'Q'},
|
||||
{"GLU", 'E'},
|
||||
{"GLY", 'G'},
|
||||
{"HIS", 'H'},
|
||||
{"ILE", 'I'},
|
||||
{"LEU", 'L'},
|
||||
{"LYS", 'K'},
|
||||
{"MET", 'M'},
|
||||
{"PHE", 'F'},
|
||||
{"PRO", 'P'},
|
||||
{"SER", 'S'},
|
||||
{"THR", 'T'},
|
||||
{"TRP", 'W'},
|
||||
{"TYR", 'Y'},
|
||||
{"VAL", 'V'},
|
||||
{"GLX", 'Z'},
|
||||
{"ASX", 'B'}};
|
||||
|
||||
CIFPP_EXPORT const std::map<std::string, char> kBaseMap{
|
||||
{"A", 'A'},
|
||||
{"C", 'C'},
|
||||
{"G", 'G'},
|
||||
{"T", 'T'},
|
||||
{"U", 'U'},
|
||||
{"DA", 'A'},
|
||||
{"DC", 'C'},
|
||||
{"DG", 'G'},
|
||||
{"DT", 'T'}};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class CompoundFactoryImpl : public std::enable_shared_from_this<CompoundFactoryImpl>
|
||||
{
|
||||
public:
|
||||
CompoundFactoryImpl(std::shared_ptr<CompoundFactoryImpl> next);
|
||||
|
||||
CompoundFactoryImpl(const std::filesystem::path &file, std::shared_ptr<CompoundFactoryImpl> next);
|
||||
|
||||
virtual ~CompoundFactoryImpl()
|
||||
{
|
||||
for (auto c: mCompounds)
|
||||
delete c;
|
||||
}
|
||||
|
||||
Compound *get(std::string id)
|
||||
{
|
||||
std::shared_lock lock(mMutex);
|
||||
|
||||
ba::to_upper(id);
|
||||
|
||||
Compound *result = nullptr;
|
||||
|
||||
// walk the list, see if any of us has the compound already
|
||||
for (auto impl = shared_from_this(); impl; impl = impl->mNext)
|
||||
{
|
||||
for (auto cmp : impl->mCompounds)
|
||||
{
|
||||
if (cmp->id() == id)
|
||||
{
|
||||
result = cmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == nullptr and mMissing.count(id) == 0)
|
||||
{
|
||||
for (auto impl = shared_from_this(); impl; impl = impl->mNext)
|
||||
{
|
||||
result = impl->create(id);
|
||||
if (result != nullptr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == nullptr)
|
||||
mMissing.insert(id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<CompoundFactoryImpl> next() const
|
||||
{
|
||||
return mNext;
|
||||
}
|
||||
|
||||
bool isKnownPeptide(const std::string &resName)
|
||||
{
|
||||
return mKnownPeptides.count(resName) or
|
||||
(mNext and mNext->isKnownPeptide(resName));
|
||||
}
|
||||
|
||||
bool isKnownBase(const std::string &resName)
|
||||
{
|
||||
return mKnownBases.count(resName) or
|
||||
(mNext and mNext->isKnownBase(resName));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual Compound *create(const std::string &id)
|
||||
{
|
||||
// For the base class we assume every compound is preloaded
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_timed_mutex mMutex;
|
||||
|
||||
std::vector<Compound *> mCompounds;
|
||||
std::set<std::string> mKnownPeptides;
|
||||
std::set<std::string> mKnownBases;
|
||||
std::set<std::string> mMissing;
|
||||
std::shared_ptr<CompoundFactoryImpl> mNext;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
CompoundFactoryImpl::CompoundFactoryImpl(std::shared_ptr<CompoundFactoryImpl> next)
|
||||
: mNext(next)
|
||||
{
|
||||
for (const auto &[key, value] : kAAMap)
|
||||
mKnownPeptides.insert(key);
|
||||
|
||||
for (const auto &[key, value] : kBaseMap)
|
||||
mKnownBases.insert(key);
|
||||
}
|
||||
|
||||
CompoundFactoryImpl::CompoundFactoryImpl(const std::filesystem::path &file, std::shared_ptr<CompoundFactoryImpl> next)
|
||||
: mNext(next)
|
||||
{
|
||||
cif::File cifFile(file);
|
||||
|
||||
auto compList = cifFile.get("comp_list");
|
||||
if (compList) // So this is a CCP4 restraints file, special handling
|
||||
{
|
||||
auto &chemComp = (*compList)["chem_comp"];
|
||||
|
||||
for (const auto &[id, name, group] : chemComp.rows<std::string, std::string, std::string>("id", "name", "group"))
|
||||
{
|
||||
std::string type;
|
||||
|
||||
// known groups are (counted from ccp4 monomer dictionary)
|
||||
|
||||
// D-pyranose
|
||||
// DNA
|
||||
// L-PEPTIDE LINKING
|
||||
// L-SACCHARIDE
|
||||
// L-peptide
|
||||
// L-pyranose
|
||||
// M-peptide
|
||||
// NON-POLYMER
|
||||
// P-peptide
|
||||
// RNA
|
||||
// furanose
|
||||
// non-polymer
|
||||
// non_polymer
|
||||
// peptide
|
||||
// pyranose
|
||||
// saccharide
|
||||
|
||||
if (cif::iequals(id, "gly"))
|
||||
type = "peptide linking";
|
||||
else if (cif::iequals(group, "l-peptide") or cif::iequals(group, "L-peptide linking") or cif::iequals(group, "peptide") or cif::iequals(group, "p-peptide"))
|
||||
type = "L-peptide linking";
|
||||
else if (cif::iequals(group, "DNA"))
|
||||
type = "DNA linking";
|
||||
else if (cif::iequals(group, "RNA"))
|
||||
type = "RNA linking";
|
||||
else
|
||||
type = "non-polymer";
|
||||
|
||||
auto &db = cifFile["comp_" + id];
|
||||
|
||||
mCompounds.push_back(new Compound(db, id, name, type, group));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// A CCD components file, validate it first
|
||||
cifFile.loadDictionary("mmcif_pdbx_v50");
|
||||
|
||||
if (not cifFile.isValid())
|
||||
throw std::runtime_error("Invalid compound file");
|
||||
|
||||
for (auto &db : cifFile)
|
||||
mCompounds.push_back(new Compound(db));
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Version for the default compounds, based on the cached components.cif file from CCD
|
||||
|
||||
class CCDCompoundFactoryImpl : public CompoundFactoryImpl
|
||||
{
|
||||
public:
|
||||
CCDCompoundFactoryImpl(std::shared_ptr<CompoundFactoryImpl> next, const fs::path& file)
|
||||
: CompoundFactoryImpl(next)
|
||||
, mCompoundsFile(file)
|
||||
{
|
||||
}
|
||||
|
||||
CCDCompoundFactoryImpl(std::shared_ptr<CompoundFactoryImpl> next)
|
||||
: CompoundFactoryImpl(next)
|
||||
{
|
||||
}
|
||||
|
||||
Compound *create(const std::string &id) override;
|
||||
|
||||
cif::DatablockIndex mIndex;
|
||||
fs::path mCompoundsFile;
|
||||
};
|
||||
|
||||
Compound *CCDCompoundFactoryImpl::create(const std::string &id)
|
||||
{
|
||||
Compound *result = nullptr;
|
||||
|
||||
std::unique_ptr<std::istream> ccd;
|
||||
|
||||
if (mCompoundsFile.empty())
|
||||
{
|
||||
ccd = cif::loadResource("components.cif");
|
||||
if (not ccd)
|
||||
throw std::runtime_error("Could not locate the CCD components.cif file, please make sure the software is installed properly and/or use the update-libcifpp-data to fetch the data.");
|
||||
}
|
||||
else
|
||||
ccd.reset(new std::ifstream(mCompoundsFile));
|
||||
|
||||
cif::File file;
|
||||
|
||||
if (mIndex.empty())
|
||||
{
|
||||
if (cif::VERBOSE > 1)
|
||||
{
|
||||
std::cout << "Creating component index "
|
||||
<< "...";
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
cif::Parser parser(*ccd, file, false);
|
||||
mIndex = parser.indexDatablocks();
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cout << " done" << std::endl;
|
||||
|
||||
// reload the resource, perhaps this should be improved...
|
||||
if (mCompoundsFile.empty())
|
||||
{
|
||||
ccd = cif::loadResource("components.cif");
|
||||
if (not ccd)
|
||||
throw std::runtime_error("Could not locate the CCD components.cif file, please make sure the software is installed properly and/or use the update-libcifpp-data to fetch the data.");
|
||||
}
|
||||
else
|
||||
ccd.reset(new std::ifstream(mCompoundsFile));
|
||||
}
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
{
|
||||
std::cout << "Loading component " << id << "...";
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
cif::Parser parser(*ccd, file, false);
|
||||
parser.parseSingleDatablock(id, mIndex);
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cout << " done" << std::endl;
|
||||
|
||||
if (not file.empty())
|
||||
{
|
||||
auto &db = file.firstDatablock();
|
||||
if (db.getName() == id)
|
||||
{
|
||||
result = new Compound(db);
|
||||
|
||||
std::shared_lock lock(mMutex);
|
||||
mCompounds.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == nullptr and cif::VERBOSE > 0)
|
||||
std::cerr << "Could not locate compound " << id << " in the CCD components file" << std::endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Version for the default compounds, based on the data found in CCP4's monomers lib
|
||||
|
||||
class CCP4CompoundFactoryImpl : public CompoundFactoryImpl
|
||||
{
|
||||
public:
|
||||
CCP4CompoundFactoryImpl(const fs::path &clibd_mon, std::shared_ptr<CompoundFactoryImpl> next = nullptr);
|
||||
|
||||
Compound *create(const std::string &id) override;
|
||||
|
||||
private:
|
||||
cif::File mFile;
|
||||
fs::path mCLIBD_MON;
|
||||
};
|
||||
|
||||
CCP4CompoundFactoryImpl::CCP4CompoundFactoryImpl(const fs::path &clibd_mon, std::shared_ptr<CompoundFactoryImpl> next)
|
||||
: CompoundFactoryImpl(next)
|
||||
, mFile((clibd_mon / "list" / "mon_lib_list.cif").string())
|
||||
, mCLIBD_MON(clibd_mon)
|
||||
{
|
||||
const std::regex peptideRx("(?:[lmp]-)?peptide", std::regex::icase);
|
||||
|
||||
auto &chemComps = mFile["comp_list"]["chem_comp"];
|
||||
|
||||
for (const auto &[group, threeLetterCode] : chemComps.rows<std::string, std::string>("group", "three_letter_code"))
|
||||
{
|
||||
if (std::regex_match(group, peptideRx))
|
||||
mKnownPeptides.insert(threeLetterCode);
|
||||
else if (ba::iequals(group, "DNA") or ba::iequals(group, "RNA"))
|
||||
mKnownBases.insert(threeLetterCode);
|
||||
}
|
||||
}
|
||||
|
||||
Compound *CCP4CompoundFactoryImpl::create(const std::string &id)
|
||||
{
|
||||
Compound *result = nullptr;
|
||||
|
||||
auto &cat = mFile["comp_list"]["chem_comp"];
|
||||
|
||||
auto rs = cat.find(cif::Key("three_letter_code") == id);
|
||||
|
||||
if (rs.size() == 1)
|
||||
{
|
||||
auto row = rs.front();
|
||||
|
||||
std::string name, group;
|
||||
uint32_t numberAtomsAll, numberAtomsNh;
|
||||
cif::tie(name, group, numberAtomsAll, numberAtomsNh) =
|
||||
row.get("name", "group", "number_atoms_all", "number_atoms_nh");
|
||||
|
||||
fs::path resFile = mCLIBD_MON / ba::to_lower_copy(id.substr(0, 1)) / (id + ".cif");
|
||||
|
||||
if (not fs::exists(resFile) and (id == "COM" or id == "CON" or "PRN")) // seriously...
|
||||
resFile = mCLIBD_MON / ba::to_lower_copy(id.substr(0, 1)) / (id + '_' + id + ".cif");
|
||||
|
||||
if (fs::exists(resFile))
|
||||
{
|
||||
cif::File cf(resFile.string());
|
||||
|
||||
// locate the datablock
|
||||
auto &db = cf["comp_" + id];
|
||||
|
||||
std::string type;
|
||||
|
||||
// known groups are (counted from ccp4 monomer dictionary)
|
||||
|
||||
// D-pyranose
|
||||
// DNA
|
||||
// L-PEPTIDE LINKING
|
||||
// L-SACCHARIDE
|
||||
// L-peptide
|
||||
// L-pyranose
|
||||
// M-peptide
|
||||
// NON-POLYMER
|
||||
// P-peptide
|
||||
// RNA
|
||||
// furanose
|
||||
// non-polymer
|
||||
// non_polymer
|
||||
// peptide
|
||||
// pyranose
|
||||
// saccharide
|
||||
|
||||
if (cif::iequals(id, "gly"))
|
||||
type = "peptide linking";
|
||||
else if (cif::iequals(group, "l-peptide") or cif::iequals(group, "L-peptide linking") or cif::iequals(group, "peptide") or cif::iequals(group, "p-peptide"))
|
||||
type = "L-peptide linking";
|
||||
else if (cif::iequals(group, "DNA"))
|
||||
type = "DNA linking";
|
||||
else if (cif::iequals(group, "RNA"))
|
||||
type = "RNA linking";
|
||||
else
|
||||
type = "non-polymer";
|
||||
|
||||
mCompounds.push_back(new Compound(db, id, name, type, group));
|
||||
result = mCompounds.back();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<CompoundFactory> CompoundFactory::sInstance;
|
||||
thread_local std::unique_ptr<CompoundFactory> CompoundFactory::tlInstance;
|
||||
bool CompoundFactory::sUseThreadLocalInstance;
|
||||
|
||||
void CompoundFactory::init(bool useThreadLocalInstanceOnly)
|
||||
{
|
||||
sUseThreadLocalInstance = useThreadLocalInstanceOnly;
|
||||
}
|
||||
|
||||
CompoundFactory::CompoundFactory()
|
||||
: mImpl(nullptr)
|
||||
{
|
||||
auto ccd = cif::loadResource("components.cif");
|
||||
if (ccd)
|
||||
mImpl.reset(new CCDCompoundFactoryImpl(mImpl));
|
||||
else if (cif::VERBOSE > 0)
|
||||
std::cerr << "CCD components.cif file was not found" << std::endl;
|
||||
|
||||
const char *clibd_mon = getenv("CLIBD_MON");
|
||||
if (clibd_mon != nullptr and fs::is_directory(clibd_mon))
|
||||
mImpl.reset(new CCP4CompoundFactoryImpl(clibd_mon));
|
||||
else if (cif::VERBOSE > 0)
|
||||
std::cerr << "CCP4 monomers library not found, CLIBD_MON is not defined" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
CompoundFactory::~CompoundFactory()
|
||||
{
|
||||
}
|
||||
|
||||
CompoundFactory &CompoundFactory::instance()
|
||||
{
|
||||
if (sUseThreadLocalInstance)
|
||||
{
|
||||
if (not tlInstance)
|
||||
tlInstance.reset(new CompoundFactory());
|
||||
return *tlInstance;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (not sInstance)
|
||||
sInstance.reset(new CompoundFactory());
|
||||
return *sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
void CompoundFactory::clear()
|
||||
{
|
||||
if (sUseThreadLocalInstance)
|
||||
tlInstance.reset(nullptr);
|
||||
else
|
||||
sInstance.reset();
|
||||
}
|
||||
|
||||
void CompoundFactory::setDefaultDictionary(const std::filesystem::path &inDictFile)
|
||||
{
|
||||
if (not fs::exists(inDictFile))
|
||||
throw std::runtime_error("file not found: " + inDictFile.string());
|
||||
|
||||
try
|
||||
{
|
||||
mImpl.reset(new CCDCompoundFactoryImpl(mImpl, inDictFile));
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
if (cif::VERBOSE >= 0)
|
||||
std::cerr << "Error loading dictionary " << inDictFile << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void CompoundFactory::pushDictionary(const std::filesystem::path &inDictFile)
|
||||
{
|
||||
if (not fs::exists(inDictFile))
|
||||
throw std::runtime_error("file not found: " + inDictFile.string());
|
||||
|
||||
// ifstream file(inDictFile);
|
||||
// if (not file.is_open())
|
||||
// throw std::runtime_error("Could not open peptide list " + inDictFile);
|
||||
|
||||
try
|
||||
{
|
||||
mImpl.reset(new CompoundFactoryImpl(inDictFile, mImpl));
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
if (cif::VERBOSE >= 0)
|
||||
std::cerr << "Error loading dictionary " << inDictFile << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void CompoundFactory::popDictionary()
|
||||
{
|
||||
if (mImpl)
|
||||
mImpl = mImpl->next();
|
||||
}
|
||||
|
||||
const Compound *CompoundFactory::create(std::string id)
|
||||
{
|
||||
// static bool warned = false;
|
||||
|
||||
// if (mImpl and warned == false)
|
||||
// {
|
||||
// std::cerr << "Warning: no compound information library was found, resulting data may be incorrect or incomplete" << std::endl;
|
||||
// warned = true;
|
||||
// }
|
||||
|
||||
return mImpl ? mImpl->get(id) : nullptr;
|
||||
}
|
||||
|
||||
bool CompoundFactory::isKnownPeptide(const std::string &resName) const
|
||||
{
|
||||
return mImpl ? mImpl->isKnownPeptide(resName) : kAAMap.count(resName) > 0;
|
||||
}
|
||||
|
||||
bool CompoundFactory::isKnownBase(const std::string &resName) const
|
||||
{
|
||||
return mImpl ? mImpl->isKnownBase(resName) : kBaseMap.count(resName) > 0;
|
||||
}
|
||||
|
||||
} // namespace mmcif
|
||||
11
src/Config-cmake.hpp.in
Normal file
11
src/Config-cmake.hpp.in
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Define to the name of this package. */
|
||||
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* Define the complete package string */
|
||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||
|
||||
/* Using resources? */
|
||||
#cmakedefine USE_RSRC @USE_RSRC@
|
||||
113
src/Config.hpp.in
Normal file
113
src/Config.hpp.in
Normal file
@@ -0,0 +1,113 @@
|
||||
/* src/Config.hpp.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* define if the Boost library is available */
|
||||
#undef HAVE_BOOST
|
||||
|
||||
/* define if the Boost::Date_Time library is available */
|
||||
#undef HAVE_BOOST_DATE_TIME
|
||||
|
||||
/* define if the Boost::IOStreams library is available */
|
||||
#undef HAVE_BOOST_IOSTREAMS
|
||||
|
||||
/* define if the Boost::Regex library is available */
|
||||
#undef HAVE_BOOST_REGEX
|
||||
|
||||
/* define if the compiler supports basic C++17 syntax */
|
||||
#undef HAVE_CXX17
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#undef HAVE_FLOOR
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `pow' function. */
|
||||
#undef HAVE_POW
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 if the system has the type `ptrdiff_t'. */
|
||||
#undef HAVE_PTRDIFF_T
|
||||
|
||||
/* Define to 1 if you have the `rint' function. */
|
||||
#undef HAVE_RINT
|
||||
|
||||
/* Define to 1 if you have the `sqrt' function. */
|
||||
#undef HAVE_SQRT
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#undef HAVE__BOOL
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Use mrc to store resources */
|
||||
#undef USE_RSRC
|
||||
6052
src/PDB2Cif.cpp
Normal file
6052
src/PDB2Cif.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1490
src/PDB2CifRemark3.cpp
Normal file
1490
src/PDB2CifRemark3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
533
src/Point.cpp
Normal file
533
src/Point.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <random>
|
||||
#include <valarray>
|
||||
|
||||
#include "cif++/Point.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
uint32_t dim_m() const { return m_m; }
|
||||
uint32_t dim_n() const { return m_n; }
|
||||
|
||||
double operator()(uint32_t i, uint32_t j) const
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
return m_data[i * m_n + j];
|
||||
}
|
||||
|
||||
double &operator()(uint32_t i, uint32_t j)
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
return m_data[i * m_n + j];
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_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;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
Quaternion Normalize(Quaternion q)
|
||||
{
|
||||
std::valarray<double> t(4);
|
||||
|
||||
t[0] = q.R_component_1();
|
||||
t[1] = q.R_component_2();
|
||||
t[2] = q.R_component_3();
|
||||
t[3] = q.R_component_4();
|
||||
|
||||
t *= t;
|
||||
|
||||
double length = std::sqrt(t.sum());
|
||||
|
||||
if (length > 0.001)
|
||||
q /= static_cast<Quaternion::value_type>(length);
|
||||
else
|
||||
q = Quaternion(1, 0, 0, 0);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
Quaternion ConstructFromAngleAxis(float angle, Point axis)
|
||||
{
|
||||
auto q = std::cos((angle * mmcif::kPI / 180) / 2);
|
||||
auto s = std::sqrt(1 - q * q);
|
||||
|
||||
axis.normalize();
|
||||
|
||||
return Normalize(Quaternion{
|
||||
static_cast<float>(q),
|
||||
static_cast<float>(s * axis.mX),
|
||||
static_cast<float>(s * axis.mY),
|
||||
static_cast<float>(s * axis.mZ)});
|
||||
}
|
||||
|
||||
std::tuple<double,Point> QuaternionToAngleAxis(Quaternion q)
|
||||
{
|
||||
if (q.R_component_1() > 1)
|
||||
q = Normalize(q);
|
||||
|
||||
// angle:
|
||||
double angle = 2 * std::acos(q.R_component_1());
|
||||
angle = angle * 180 / kPI;
|
||||
|
||||
// axis:
|
||||
float s = std::sqrt(1 - q.R_component_1() * q.R_component_1());
|
||||
if (s < 0.001)
|
||||
s = 1;
|
||||
|
||||
Point axis(q.R_component_2() / s, q.R_component_3() / s, q.R_component_4() / s);
|
||||
|
||||
return std::make_tuple(angle, axis);
|
||||
}
|
||||
|
||||
Point CenterPoints(std::vector<Point>& Points)
|
||||
{
|
||||
Point t;
|
||||
|
||||
for (Point& pt : Points)
|
||||
{
|
||||
t.mX += pt.mX;
|
||||
t.mY += pt.mY;
|
||||
t.mZ += pt.mZ;
|
||||
}
|
||||
|
||||
t.mX /= Points.size();
|
||||
t.mY /= Points.size();
|
||||
t.mZ /= Points.size();
|
||||
|
||||
for (Point& pt : Points)
|
||||
{
|
||||
pt.mX -= t.mX;
|
||||
pt.mY -= t.mY;
|
||||
pt.mZ -= t.mZ;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
Point Centroid(const std::vector<Point>& pts)
|
||||
{
|
||||
Point result;
|
||||
|
||||
for (auto &pt : pts)
|
||||
result += pt;
|
||||
|
||||
result /= static_cast<float>(pts.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double RMSd(const std::vector<Point>& a, const std::vector<Point>& b)
|
||||
{
|
||||
double sum = 0;
|
||||
for (uint32_t i = 0; i < a.size(); ++i)
|
||||
{
|
||||
std::valarray<double> d(3);
|
||||
|
||||
d[0] = b[i].mX - a[i].mX;
|
||||
d[1] = b[i].mY - a[i].mY;
|
||||
d[2] = b[i].mZ - a[i].mZ;
|
||||
|
||||
d *= d;
|
||||
|
||||
sum += d.sum();
|
||||
}
|
||||
|
||||
return std::sqrt(sum / a.size());
|
||||
}
|
||||
|
||||
// The next function returns the largest solution for a quartic equation
|
||||
// based on Ferrari's algorithm.
|
||||
// A depressed quartic is of the form:
|
||||
//
|
||||
// x^4 + ax^2 + bx + c = 0
|
||||
//
|
||||
// (since I'm too lazy to find out a better way, I've implemented the
|
||||
// routine using complex values to avoid nan's as a result of taking
|
||||
// sqrt of a negative number)
|
||||
double LargestDepressedQuarticSolution(double a, double b, double c)
|
||||
{
|
||||
std::complex<double> P = - (a * a) / 12 - c;
|
||||
std::complex<double> Q = - (a * a * a) / 108 + (a * c) / 3 - (b * b) / 8;
|
||||
std::complex<double> R = - Q / 2.0 + std::sqrt((Q * Q) / 4.0 + (P * P * P) / 27.0);
|
||||
|
||||
std::complex<double> U = std::pow(R, 1 / 3.0);
|
||||
|
||||
std::complex<double> y;
|
||||
if (U == 0.0)
|
||||
y = -5.0 * a / 6.0 + U - std::pow(Q, 1.0 / 3.0);
|
||||
else
|
||||
y = -5.0 * a / 6.0 + U - P / (3.0 * U);
|
||||
|
||||
std::complex<double> W = std::sqrt(a + 2.0 * y);
|
||||
|
||||
// And to get the final result:
|
||||
// result = (±W + std::sqrt(-(3 * alpha + 2 * y ± 2 * beta / W))) / 2;
|
||||
// We want the largest result, so:
|
||||
|
||||
std::valarray<double> t(4);
|
||||
|
||||
t[0] = (( W + std::sqrt(-(3.0 * a + 2.0 * y + 2.0 * b / W))) / 2.0).real();
|
||||
t[1] = (( W + std::sqrt(-(3.0 * a + 2.0 * y - 2.0 * b / W))) / 2.0).real();
|
||||
t[2] = ((-W + std::sqrt(-(3.0 * a + 2.0 * y + 2.0 * b / W))) / 2.0).real();
|
||||
t[3] = ((-W + std::sqrt(-(3.0 * a + 2.0 * y - 2.0 * b / W))) / 2.0).real();
|
||||
|
||||
return t.max();
|
||||
}
|
||||
|
||||
Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& pb)
|
||||
{
|
||||
// First calculate M, a 3x3 Matrix containing the sums of products of the coordinates of A and B
|
||||
Matrix M(3, 3, 0);
|
||||
|
||||
for (uint32_t i = 0; i < pa.size(); ++i)
|
||||
{
|
||||
const Point& a = pa[i];
|
||||
const Point& b = pb[i];
|
||||
|
||||
M(0, 0) += a.mX * b.mX; M(0, 1) += a.mX * b.mY; M(0, 2) += a.mX * b.mZ;
|
||||
M(1, 0) += a.mY * b.mX; M(1, 1) += a.mY * b.mY; M(1, 2) += a.mY * b.mZ;
|
||||
M(2, 0) += a.mZ * b.mX; M(2, 1) += a.mZ * b.mY; M(2, 2) += a.mZ * b.mZ;
|
||||
}
|
||||
|
||||
// Now calculate N, a symmetric 4x4 Matrix
|
||||
SymmetricMatrix N(4);
|
||||
|
||||
N(0, 0) = M(0, 0) + M(1, 1) + M(2, 2);
|
||||
N(0, 1) = M(1, 2) - M(2, 1);
|
||||
N(0, 2) = M(2, 0) - M(0, 2);
|
||||
N(0, 3) = M(0, 1) - M(1, 0);
|
||||
|
||||
N(1, 1) = M(0, 0) - M(1, 1) - M(2, 2);
|
||||
N(1, 2) = M(0, 1) + M(1, 0);
|
||||
N(1, 3) = M(0, 2) + M(2, 0);
|
||||
|
||||
N(2, 2) = -M(0, 0) + M(1, 1) - M(2, 2);
|
||||
N(2, 3) = M(1, 2) + M(2, 1);
|
||||
|
||||
N(3, 3) = -M(0, 0) - M(1, 1) + M(2, 2);
|
||||
|
||||
// det(N - λI) = 0
|
||||
// find the largest λ (λm)
|
||||
//
|
||||
// Aλ4 + Bλ3 + Cλ2 + Dλ + E = 0
|
||||
// A = 1
|
||||
// B = 0
|
||||
// and so this is a so-called depressed quartic
|
||||
// solve it using Ferrari's algorithm
|
||||
|
||||
double C = -2 * (
|
||||
M(0, 0) * M(0, 0) + M(0, 1) * M(0, 1) + M(0, 2) * M(0, 2) +
|
||||
M(1, 0) * M(1, 0) + M(1, 1) * M(1, 1) + M(1, 2) * M(1, 2) +
|
||||
M(2, 0) * M(2, 0) + M(2, 1) * M(2, 1) + M(2, 2) * M(2, 2));
|
||||
|
||||
double D = 8 * (M(0, 0) * M(1, 2) * M(2, 1) +
|
||||
M(1, 1) * M(2, 0) * M(0, 2) +
|
||||
M(2, 2) * M(0, 1) * M(1, 0)) -
|
||||
8 * (M(0, 0) * M(1, 1) * M(2, 2) +
|
||||
M(1, 2) * M(2, 0) * M(0, 1) +
|
||||
M(2, 1) * M(1, 0) * M(0, 2));
|
||||
|
||||
// E is the determinant of N:
|
||||
double E =
|
||||
(N(0,0) * N(1,1) - N(0,1) * N(0,1)) * (N(2,2) * N(3,3) - N(2,3) * N(2,3)) +
|
||||
(N(0,1) * N(0,2) - N(0,0) * N(2,1)) * (N(2,1) * N(3,3) - N(2,3) * N(1,3)) +
|
||||
(N(0,0) * N(1,3) - N(0,1) * N(0,3)) * (N(2,1) * N(2,3) - N(2,2) * N(1,3)) +
|
||||
(N(0,1) * N(2,1) - N(1,1) * N(0,2)) * (N(0,2) * N(3,3) - N(2,3) * N(0,3)) +
|
||||
(N(1,1) * N(0,3) - N(0,1) * N(1,3)) * (N(0,2) * N(2,3) - N(2,2) * N(0,3)) +
|
||||
(N(0,2) * N(1,3) - N(2,1) * N(0,3)) * (N(0,2) * N(1,3) - N(2,1) * N(0,3));
|
||||
|
||||
// solve quartic
|
||||
double lambda = LargestDepressedQuarticSolution(C, D, E);
|
||||
|
||||
// calculate t = (N - λI)
|
||||
Matrix t = N - IdentityMatrix(4) * lambda;
|
||||
|
||||
// calculate a Matrix of cofactors for t
|
||||
Matrix cf = Cofactors(t);
|
||||
|
||||
int maxR = 0;
|
||||
for (int r = 1; r < 4; ++r)
|
||||
{
|
||||
if (std::abs(cf(r, 0)) > std::abs(cf(maxR, 0)))
|
||||
maxR = r;
|
||||
}
|
||||
|
||||
Quaternion q(cf(maxR, 0), cf(maxR, 1), cf(maxR, 2), cf(maxR, 3));
|
||||
q = Normalize(q);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
Point Nudge(Point p, float offset)
|
||||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937_64 rng(rd());
|
||||
|
||||
std::uniform_real_distribution<> randomAngle(0, 2 * kPI);
|
||||
std::normal_distribution<> randomOffset(0, offset);
|
||||
|
||||
float theta = static_cast<float>(randomAngle(rng));
|
||||
float phi1 = static_cast<float>(randomAngle(rng) - kPI);
|
||||
float phi2 = static_cast<float>(randomAngle(rng) - kPI);
|
||||
|
||||
Quaternion q = boost::math::spherical(1.0f, theta, phi1, phi2);
|
||||
|
||||
Point r{ 0, 0, 1 };
|
||||
r.rotate(q);
|
||||
r *= static_cast<float>(randomOffset(rng));
|
||||
|
||||
return p + r;
|
||||
}
|
||||
|
||||
}
|
||||
1540
src/Secondary.cpp
Normal file
1540
src/Secondary.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2696
src/Structure.cpp
Normal file
2696
src/Structure.cpp
Normal file
File diff suppressed because it is too large
Load Diff
8660
src/SymOpTable_data.hpp
Normal file
8660
src/SymOpTable_data.hpp
Normal file
File diff suppressed because it is too large
Load Diff
155
src/Symmetry.cpp
Normal file
155
src/Symmetry.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
#include "cif++/Symmetry.hpp"
|
||||
#include "cif++/CifUtils.hpp"
|
||||
|
||||
#include "SymOpTable_data.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Unfortunately, clipper has a different numbering scheme than PDB
|
||||
// for rotation numbers. So we created a table to map those.
|
||||
// Perhaps a bit over the top, but hey....
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
int GetSpacegroupNumber(std::string spacegroup)
|
||||
{
|
||||
if (spacegroup == "P 21 21 2 A")
|
||||
spacegroup = "P 21 21 2 (a)";
|
||||
else if (spacegroup.empty())
|
||||
throw std::runtime_error("No spacegroup, cannot continue");
|
||||
|
||||
int result = 0;
|
||||
|
||||
const size_t N = kNrOfSpaceGroups;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
int32_t i = (L + R) / 2;
|
||||
|
||||
int d = spacegroup.compare(kSpaceGroups[i].name);
|
||||
|
||||
if (d > 0)
|
||||
L = i + 1;
|
||||
else if (d < 0)
|
||||
R = i - 1;
|
||||
else
|
||||
{
|
||||
result = kSpaceGroups[i].nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// not found, see if we can find a match based on xHM name
|
||||
if (result == 0)
|
||||
{
|
||||
for (size_t i = 0; i < kNrOfSpaceGroups; ++i)
|
||||
{
|
||||
auto& sp = kSpaceGroups[i];
|
||||
if (sp.xHM == spacegroup)
|
||||
{
|
||||
result = sp.nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
throw std::runtime_error("Spacegroup name " + spacegroup + " was not found in table");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
int GetSpacegroupNumber(std::string spacegroup, SpacegroupName type)
|
||||
{
|
||||
if (spacegroup == "P 21 21 2 A")
|
||||
spacegroup = "P 21 21 2 (a)";
|
||||
else if (spacegroup.empty())
|
||||
throw std::runtime_error("No spacegroup, cannot continue");
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (type == SpacegroupName::full)
|
||||
{
|
||||
const size_t N = kNrOfSpaceGroups;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
int32_t i = (L + R) / 2;
|
||||
|
||||
int d = spacegroup.compare(kSpaceGroups[i].name);
|
||||
|
||||
if (d > 0)
|
||||
L = i + 1;
|
||||
else if (d < 0)
|
||||
R = i - 1;
|
||||
else
|
||||
{
|
||||
result = kSpaceGroups[i].nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == SpacegroupName::xHM)
|
||||
{
|
||||
for (auto &sg : kSpaceGroups)
|
||||
{
|
||||
if (sg.xHM == spacegroup)
|
||||
{
|
||||
result = sg.nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &sg : kSpaceGroups)
|
||||
{
|
||||
if (sg.Hall == spacegroup)
|
||||
{
|
||||
result = sg.nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not found, see if we can find a match based on xHM name
|
||||
if (result == 0)
|
||||
throw std::runtime_error("Spacegroup name " + spacegroup + " was not found in table");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
1894
src/TlsParser.cpp
Normal file
1894
src/TlsParser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
test/1juh.cif.gz
Normal file
BIN
test/1juh.cif.gz
Normal file
Binary file not shown.
253
test/HEM.cif
Normal file
253
test/HEM.cif
Normal file
@@ -0,0 +1,253 @@
|
||||
data_HEM
|
||||
#
|
||||
|
||||
_chem_comp.id HEM
|
||||
_chem_comp.name "PROTOPORPHYRIN IX CONTAINING FE"
|
||||
_chem_comp.type NON-POLYMER
|
||||
_chem_comp.pdbx_type HETAIN
|
||||
_chem_comp.formula "C34 H32 Fe N4 O4"
|
||||
_chem_comp.mon_nstd_parent_comp_id ?
|
||||
_chem_comp.pdbx_synonyms HEME
|
||||
_chem_comp.pdbx_formal_charge 0
|
||||
_chem_comp.pdbx_initial_date 1999-07-08
|
||||
_chem_comp.pdbx_modified_date 2020-06-17
|
||||
_chem_comp.pdbx_ambiguous_flag Y
|
||||
_chem_comp.pdbx_release_status REL
|
||||
_chem_comp.pdbx_replaced_by ?
|
||||
_chem_comp.pdbx_replaces MHM
|
||||
_chem_comp.formula_weight 616.487
|
||||
_chem_comp.one_letter_code ?
|
||||
_chem_comp.three_letter_code HEM
|
||||
_chem_comp.pdbx_model_coordinates_details ?
|
||||
_chem_comp.pdbx_model_coordinates_missing_flag N
|
||||
_chem_comp.pdbx_ideal_coordinates_details Corina
|
||||
_chem_comp.pdbx_ideal_coordinates_missing_flag N
|
||||
_chem_comp.pdbx_model_coordinates_db_code 3IA3
|
||||
_chem_comp.pdbx_subcomponent_list ?
|
||||
_chem_comp.pdbx_processing_site RCSB
|
||||
# #
|
||||
loop_
|
||||
_chem_comp_atom.comp_id
|
||||
_chem_comp_atom.atom_id
|
||||
_chem_comp_atom.alt_atom_id
|
||||
_chem_comp_atom.type_symbol
|
||||
_chem_comp_atom.charge
|
||||
_chem_comp_atom.pdbx_align
|
||||
_chem_comp_atom.pdbx_aromatic_flag
|
||||
_chem_comp_atom.pdbx_leaving_atom_flag
|
||||
_chem_comp_atom.pdbx_stereo_config
|
||||
_chem_comp_atom.model_Cartn_x
|
||||
_chem_comp_atom.model_Cartn_y
|
||||
_chem_comp_atom.model_Cartn_z
|
||||
_chem_comp_atom.pdbx_model_Cartn_x_ideal
|
||||
_chem_comp_atom.pdbx_model_Cartn_y_ideal
|
||||
_chem_comp_atom.pdbx_model_Cartn_z_ideal
|
||||
_chem_comp_atom.pdbx_component_atom_id
|
||||
_chem_comp_atom.pdbx_component_comp_id
|
||||
_chem_comp_atom.pdbx_ordinal
|
||||
HEM CHA CHA C 0 1 N N N 2.748 -19.531 39.896 -2.161 -0.125 0.490 CHA HEM 1
|
||||
HEM CHB CHB C 0 1 N N N 3.258 -17.744 35.477 1.458 -3.419 0.306 CHB HEM 2
|
||||
HEM CHC CHC C 0 1 N N N 1.703 -21.900 33.637 4.701 0.169 -0.069 CHC HEM 3
|
||||
HEM CHD CHD C 0 1 N N N 1.149 -23.677 38.059 1.075 3.460 0.018 CHD HEM 4
|
||||
HEM C1A C1A C 0 1 Y N N 3.031 -18.673 38.872 -1.436 -1.305 0.380 C1A HEM 5
|
||||
HEM C2A C2A C 0 1 Y N N 3.578 -17.325 39.013 -2.015 -2.587 0.320 C2A HEM 6
|
||||
HEM C3A C3A C 0 1 Y N N 3.705 -16.820 37.785 -1.009 -3.500 0.270 C3A HEM 7
|
||||
HEM C4A C4A C 0 1 Y N N 3.256 -17.863 36.862 0.216 -2.803 0.298 C4A HEM 8
|
||||
HEM CMA CMA C 0 1 N N N 4.227 -15.469 37.393 -1.175 -4.996 0.197 CMA HEM 9
|
||||
HEM CAA CAA C 0 1 N N N 3.945 -16.670 40.296 -3.490 -2.893 0.314 CAA HEM 10
|
||||
HEM CBA CBA C 0 1 N N N 5.391 -17.138 40.581 -3.998 -2.926 -1.129 CBA HEM 11
|
||||
HEM CGA CGA C 0 1 N N N 6.095 -16.663 41.825 -5.473 -3.232 -1.136 CGA HEM 12
|
||||
HEM O1A O1A O 0 1 N N N 7.098 -15.928 41.683 -6.059 -3.405 -0.094 O1A HEM 13
|
||||
HEM O2A O2A O 0 1 N N N 5.657 -17.040 42.940 -6.137 -3.311 -2.300 O2A HEM 14
|
||||
HEM C1B C1B C 0 1 N N N 2.888 -18.698 34.579 2.664 -2.707 0.308 C1B HEM 15
|
||||
HEM C2B C2B C 0 1 N N N 2.933 -18.535 33.146 3.937 -3.328 0.418 C2B HEM 16
|
||||
HEM C3B C3B C 0 1 N N N 2.499 -19.716 32.632 4.874 -2.341 0.314 C3B HEM 17
|
||||
HEM C4B C4B C 0 1 N N N 2.187 -20.580 33.743 4.117 -1.079 0.139 C4B HEM 18
|
||||
HEM CMB CMB C 0 1 N N N 3.391 -17.290 32.422 4.203 -4.798 0.613 CMB HEM 19
|
||||
HEM CAB CAB C 0 1 N N N 2.345 -20.140 31.217 6.339 -2.497 0.365 CAB HEM 20
|
||||
HEM CBB CBB C 0 1 N N N 1.755 -19.492 30.233 6.935 -3.419 -0.385 CBB HEM 21
|
||||
HEM C1C C1C C 0 1 Y N N 1.395 -22.786 34.659 3.964 1.345 -0.174 C1C HEM 22
|
||||
HEM C2C C2C C 0 1 Y N N 0.854 -24.130 34.500 4.531 2.601 -0.445 C2C HEM 23
|
||||
HEM C3C C3C C 0 1 Y N N 0.689 -24.626 35.757 3.510 3.536 -0.437 C3C HEM 24
|
||||
HEM C4C C4C C 0 1 Y N N 1.139 -23.583 36.674 2.304 2.846 -0.139 C4C HEM 25
|
||||
HEM CMC CMC C 0 1 N N N 0.550 -24.782 33.175 5.991 2.880 -0.697 CMC HEM 26
|
||||
HEM CAC CAC C 0 1 N N N 0.164 -25.943 36.196 3.649 4.981 -0.692 CAC HEM 27
|
||||
HEM CBC CBC C 0 1 N N N 0.498 -27.158 35.750 4.201 5.407 -1.823 CBC HEM 28
|
||||
HEM C1D C1D C 0 1 N N N 1.550 -22.718 38.980 -0.102 2.753 0.298 C1D HEM 29
|
||||
HEM C2D C2D C 0 1 N N N 1.513 -22.879 40.415 -1.382 3.388 0.641 C2D HEM 30
|
||||
HEM C3D C3D C 0 1 N N N 1.951 -21.691 40.929 -2.283 2.389 0.774 C3D HEM 31
|
||||
HEM C4D C4D C 0 1 N N N 2.277 -20.826 39.811 -1.561 1.137 0.511 C4D HEM 32
|
||||
HEM CMD CMD C 0 1 N N N 1.055 -24.094 41.156 -1.639 4.863 0.811 CMD HEM 33
|
||||
HEM CAD CAD C 0 1 N N N 2.048 -21.326 42.352 -3.741 2.532 1.123 CAD HEM 34
|
||||
HEM CBD CBD C 0 1 N N N 0.741 -20.498 42.530 -4.573 2.563 -0.160 CBD HEM 35
|
||||
HEM CGD CGD C 0 1 N N N 0.578 -19.987 43.892 -6.032 2.706 0.189 CGD HEM 36
|
||||
HEM O1D O1D O 0 1 N N N 1.387 -19.103 44.303 -6.372 2.776 1.347 O1D HEM 37
|
||||
HEM O2D O2D O 0 1 N N N -0.401 -20.468 44.537 -6.954 2.755 -0.785 O2D HEM 38
|
||||
HEM NA NA N 0 1 Y N N 2.863 -18.969 37.554 -0.068 -1.456 0.321 NA HEM 39
|
||||
HEM NB NB N 0 1 N N N 2.439 -19.944 34.911 2.820 -1.386 0.207 NB HEM 40
|
||||
HEM NC NC N 0 1 Y N N 1.537 -22.509 35.976 2.604 1.506 -0.033 NC HEM 41
|
||||
HEM ND ND N 0 1 N N N 2.008 -21.465 38.663 -0.276 1.431 0.298 ND HEM 42
|
||||
HEM FE FE FE 0 0 N N N 2.196 -20.749 36.814 1.010 0.157 -0.060 FE HEM 43
|
||||
HEM HHB HHB H 0 1 N N N 3.587 -16.798 35.072 1.498 -4.508 0.309 HHB HEM 44
|
||||
HEM HHC HHC H 0 1 N N N 1.553 -22.268 32.633 5.786 0.229 -0.153 HHC HEM 45
|
||||
HEM HHD HHD H 0 1 N N N 0.802 -24.613 38.472 1.018 4.543 -0.083 HHD HEM 46
|
||||
HEM HMA HMA H 0 1 N N N 5.316 -15.524 37.249 -1.220 -5.306 -0.847 HMA HEM 47
|
||||
HEM HMAA HMAA H 0 0 N N N 3.749 -15.149 36.455 -0.328 -5.480 0.683 HMAA HEM 48
|
||||
HEM HMAB HMAB H 0 0 N N N 3.998 -14.743 38.187 -2.097 -5.285 0.702 HMAB HEM 49
|
||||
HEM HAA HAA H 0 1 N N N 3.905 -15.575 40.197 -3.662 -3.862 0.782 HAA HEM 50
|
||||
HEM HAAA HAAA H 0 0 N N N 3.268 -16.991 41.102 -4.024 -2.121 0.869 HAAA HEM 51
|
||||
HEM HBA HBA H 0 1 N N N 5.368 -18.237 40.627 -3.825 -1.956 -1.597 HBA HEM 52
|
||||
HEM HBAA HBAA H 0 0 N N N 6.004 -16.819 39.725 -3.464 -3.697 -1.684 HBAA HEM 53
|
||||
HEM HMB HMB H 0 1 N N N 3.319 -17.449 31.336 3.256 -5.336 0.660 HMB HEM 54
|
||||
HEM HMBA HMBA H 0 0 N N N 2.753 -16.442 32.711 4.794 -5.175 -0.222 HMBA HEM 55
|
||||
HEM HMBB HMBB H 0 0 N N N 4.435 -17.072 32.692 4.752 -4.948 1.543 HMBB HEM 56
|
||||
HEM HAB HAB H 0 1 N N N 2.770 -21.100 30.963 6.927 -1.863 1.011 HAB HEM 57
|
||||
HEM HBB HBB H 0 1 N N N 1.719 -19.927 29.245 7.994 -3.600 -0.277 HBB HEM 58
|
||||
HEM HBBA HBBA H 0 0 N N N 1.308 -18.526 30.414 6.360 -3.987 -1.102 HBBA HEM 59
|
||||
HEM HMC HMC H 0 1 N N N 0.153 -25.793 33.346 6.554 1.949 -0.639 HMC HEM 60
|
||||
HEM HMCA HMCA H 0 0 N N N -0.196 -24.182 32.634 6.110 3.316 -1.689 HMCA HEM 61
|
||||
HEM HMCB HMCB H 0 0 N N N 1.472 -24.846 32.578 6.362 3.578 0.053 HMCB HEM 62
|
||||
HEM HAC HAC H 0 1 N N N -0.583 -25.916 36.975 3.303 5.694 0.042 HAC HEM 63
|
||||
HEM HBC HBC H 0 1 N N N 0.027 -28.035 36.169 4.614 4.696 -2.523 HBC HEM 64
|
||||
HEM HBCA HBCA H 0 0 N N N 1.239 -27.263 34.971 4.235 6.464 -2.043 HBCA HEM 65
|
||||
HEM HMD HMD H 0 1 N N N 1.142 -23.919 42.238 -0.715 5.415 0.639 HMD HEM 66
|
||||
HEM HMDA HMDA H 0 0 N N N 0.006 -24.304 40.902 -2.394 5.185 0.094 HMDA HEM 67
|
||||
HEM HMDB HMDB H 0 0 N N N 1.680 -24.954 40.872 -1.994 5.055 1.824 HMDB HEM 68
|
||||
HEM HAD HAD H 0 1 N N N 2.055 -22.216 42.999 -4.052 1.687 1.738 HAD HEM 69
|
||||
HEM HADA HADA H 0 0 N N N 2.943 -20.719 42.554 -3.893 3.459 1.677 HADA HEM 70
|
||||
HEM HBD HBD H 0 1 N N N 0.767 -19.646 41.835 -4.262 3.408 -0.775 HBD HEM 71
|
||||
HEM HBDA HBDA H 0 0 N N N -0.119 -21.141 42.290 -4.421 1.636 -0.714 HBDA HEM 72
|
||||
HEM H2A H2A H 0 1 N N N 6.201 -16.682 43.632 -7.082 -3.510 -2.254 H2A HEM 73
|
||||
HEM H2D H2D H 0 1 N N N -0.445 -20.063 45.395 -7.877 2.847 -0.512 H2D HEM 74
|
||||
HEM HHA HHA H 0 1 N N N 2.913 -19.150 40.893 -3.246 -0.188 0.567 HHA HEM 75
|
||||
# #
|
||||
loop_
|
||||
_chem_comp_bond.comp_id
|
||||
_chem_comp_bond.atom_id_1
|
||||
_chem_comp_bond.atom_id_2
|
||||
_chem_comp_bond.value_order
|
||||
_chem_comp_bond.pdbx_aromatic_flag
|
||||
_chem_comp_bond.pdbx_stereo_config
|
||||
_chem_comp_bond.pdbx_ordinal
|
||||
HEM CHA C1A SING N N 1
|
||||
HEM CHA C4D DOUB N N 2
|
||||
HEM CHA HHA SING N N 3
|
||||
HEM CHB C4A SING N N 4
|
||||
HEM CHB C1B DOUB N N 5
|
||||
HEM CHB HHB SING N N 6
|
||||
HEM CHC C4B SING N N 7
|
||||
HEM CHC C1C DOUB N N 8
|
||||
HEM CHC HHC SING N N 9
|
||||
HEM CHD C4C DOUB N N 10
|
||||
HEM CHD C1D SING N N 11
|
||||
HEM CHD HHD SING N N 12
|
||||
HEM C1A C2A DOUB Y N 13
|
||||
HEM C1A NA SING Y N 14
|
||||
HEM C2A C3A SING Y N 15
|
||||
HEM C2A CAA SING N N 16
|
||||
HEM C3A C4A DOUB Y N 17
|
||||
HEM C3A CMA SING N N 18
|
||||
HEM C4A NA SING Y N 19
|
||||
HEM CMA HMA SING N N 20
|
||||
HEM CMA HMAA SING N N 21
|
||||
HEM CMA HMAB SING N N 22
|
||||
HEM CAA CBA SING N N 23
|
||||
HEM CAA HAA SING N N 24
|
||||
HEM CAA HAAA SING N N 25
|
||||
HEM CBA CGA SING N N 26
|
||||
HEM CBA HBA SING N N 27
|
||||
HEM CBA HBAA SING N N 28
|
||||
HEM CGA O1A DOUB N N 29
|
||||
HEM CGA O2A SING N N 30
|
||||
HEM C1B C2B SING N N 31
|
||||
HEM C1B NB SING N N 32
|
||||
HEM C2B C3B DOUB N N 33
|
||||
HEM C2B CMB SING N N 34
|
||||
HEM C3B C4B SING N N 35
|
||||
HEM C3B CAB SING N N 36
|
||||
HEM C4B NB DOUB N N 37
|
||||
HEM CMB HMB SING N N 38
|
||||
HEM CMB HMBA SING N N 39
|
||||
HEM CMB HMBB SING N N 40
|
||||
HEM CAB CBB DOUB N N 41
|
||||
HEM CAB HAB SING N N 42
|
||||
HEM CBB HBB SING N N 43
|
||||
HEM CBB HBBA SING N N 44
|
||||
HEM C1C C2C SING Y N 45
|
||||
HEM C1C NC SING Y N 46
|
||||
HEM C2C C3C DOUB Y N 47
|
||||
HEM C2C CMC SING N N 48
|
||||
HEM C3C C4C SING Y N 49
|
||||
HEM C3C CAC SING N N 50
|
||||
HEM C4C NC SING Y N 51
|
||||
HEM CMC HMC SING N N 52
|
||||
HEM CMC HMCA SING N N 53
|
||||
HEM CMC HMCB SING N N 54
|
||||
HEM CAC CBC DOUB N N 55
|
||||
HEM CAC HAC SING N N 56
|
||||
HEM CBC HBC SING N N 57
|
||||
HEM CBC HBCA SING N N 58
|
||||
HEM C1D C2D SING N N 59
|
||||
HEM C1D ND DOUB N N 60
|
||||
HEM C2D C3D DOUB N N 61
|
||||
HEM C2D CMD SING N N 62
|
||||
HEM C3D C4D SING N N 63
|
||||
HEM C3D CAD SING N N 64
|
||||
HEM C4D ND SING N N 65
|
||||
HEM CMD HMD SING N N 66
|
||||
HEM CMD HMDA SING N N 67
|
||||
HEM CMD HMDB SING N N 68
|
||||
HEM CAD CBD SING N N 69
|
||||
HEM CAD HAD SING N N 70
|
||||
HEM CAD HADA SING N N 71
|
||||
HEM CBD CGD SING N N 72
|
||||
HEM CBD HBD SING N N 73
|
||||
HEM CBD HBDA SING N N 74
|
||||
HEM CGD O1D DOUB N N 75
|
||||
HEM CGD O2D SING N N 76
|
||||
HEM O2A H2A SING N N 77
|
||||
HEM O2D H2D SING N N 78
|
||||
HEM FE NA SING N N 79
|
||||
HEM FE NB SING N N 80
|
||||
HEM FE NC SING N N 81
|
||||
HEM FE ND SING N N 82
|
||||
# #
|
||||
loop_
|
||||
_pdbx_chem_comp_descriptor.comp_id
|
||||
_pdbx_chem_comp_descriptor.type
|
||||
_pdbx_chem_comp_descriptor.program
|
||||
_pdbx_chem_comp_descriptor.program_version
|
||||
_pdbx_chem_comp_descriptor.descriptor
|
||||
HEM SMILES ACDLabs 12.01 "C=1c3c(c(c4C=C5C(=C(C=6C=C7C(=C(C8=CC=2C(=C(C=1N=2[Fe](n34)(N5=6)N78)CCC(=O)O)C)\C=C)C)\C=C)C)C)CCC(=O)O"
|
||||
HEM InChI InChI 1.03 "InChI=1S/C34H34N4O4.Fe/c1-7-21-17(3)25-13-26-19(5)23(9-11-33(39)40)31(37-26)16-32-24(10-12-34(41)42)20(6)28(38-32)15-30-22(8-2)18(4)27(36-30)14-29(21)35-25;/h7-8,13-16H,1-2,9-12H2,3-6H3,(H4,35,36,37,38,39,40,41,42);/q;+2/p-2/b25-13-,26-13-,27-14-,28-15-,29-14-,30-15-,31-16-,32-16-;"
|
||||
HEM InChIKey InChI 1.03 KABFMIBPWCXCRK-RGGAHWMASA-L
|
||||
HEM SMILES_CANONICAL CACTVS 3.385 "CC1=C(CCC(O)=O)C2=Cc3n4[Fe]5|6|N2=C1C=c7n5c(=CC8=N|6C(=Cc4c(C)c3CCC(O)=O)C(=C8C=C)C)c(C)c7C=C"
|
||||
HEM SMILES CACTVS 3.385 "CC1=C(CCC(O)=O)C2=Cc3n4[Fe]5|6|N2=C1C=c7n5c(=CC8=N|6C(=Cc4c(C)c3CCC(O)=O)C(=C8C=C)C)c(C)c7C=C"
|
||||
HEM SMILES_CANONICAL "OpenEye OEToolkits" 1.7.6 "Cc1c2n3c(c1CCC(=O)O)C=C4C(=C(C5=[N]4[Fe]36[N]7=C(C=C8N6C(=C5)C(=C8C)C=C)C(=C(C7=C2)C)C=C)C)CCC(=O)O"
|
||||
HEM SMILES "OpenEye OEToolkits" 1.7.6 "Cc1c2n3c(c1CCC(=O)O)C=C4C(=C(C5=[N]4[Fe]36[N]7=C(C=C8N6C(=C5)C(=C8C)C=C)C(=C(C7=C2)C)C=C)C)CCC(=O)O"
|
||||
# #
|
||||
loop_
|
||||
_pdbx_chem_comp_identifier.comp_id
|
||||
_pdbx_chem_comp_identifier.type
|
||||
_pdbx_chem_comp_identifier.program
|
||||
_pdbx_chem_comp_identifier.program_version
|
||||
_pdbx_chem_comp_identifier.identifier
|
||||
HEM "SYSTEMATIC NAME" "OpenEye OEToolkits" 1.6.1 "3-[(5Z,10Z,14Z,19Z)-18-(2-carboxyethyl)-8,13-bis(ethenyl)-3,7,12,17-tetramethyl-21,23-dihydroporphyrin-2-yl]propanoic acid"
|
||||
HEM "SYSTEMATIC NAME" ACDLabs 12.01 "[3,3'-(7,12-diethenyl-3,8,13,17-tetramethylporphyrin-2,18-diyl-kappa~4~N~21~,N~22~,N~23~,N~24~)dipropanoato(2-)]iron"
|
||||
# #
|
||||
loop_
|
||||
_pdbx_chem_comp_audit.comp_id
|
||||
_pdbx_chem_comp_audit.action_type
|
||||
_pdbx_chem_comp_audit.date
|
||||
_pdbx_chem_comp_audit.processing_site
|
||||
HEM "Create component" 1999-07-08 RCSB
|
||||
HEM "Other modification" 2016-01-20 RCSB
|
||||
HEM "Modify synonyms" 2020-06-05 PDBE
|
||||
#
|
||||
_pdbx_chem_comp_synonyms.ordinal 1
|
||||
_pdbx_chem_comp_synonyms.comp_id HEM
|
||||
_pdbx_chem_comp_synonyms.name HEME
|
||||
_pdbx_chem_comp_synonyms.provenance ?
|
||||
_pdbx_chem_comp_synonyms.type ?
|
||||
##
|
||||
|
||||
188
test/REA.cif
Normal file
188
test/REA.cif
Normal file
@@ -0,0 +1,188 @@
|
||||
data_REA
|
||||
#
|
||||
_chem_comp.id REA
|
||||
_chem_comp.name "RETINOIC ACID"
|
||||
_chem_comp.type NON-POLYMER
|
||||
_chem_comp.pdbx_type HETAIN
|
||||
_chem_comp.formula "C20 H28 O2"
|
||||
_chem_comp.mon_nstd_parent_comp_id ?
|
||||
_chem_comp.pdbx_synonyms ?
|
||||
_chem_comp.pdbx_formal_charge 0
|
||||
_chem_comp.pdbx_initial_date 1999-07-08
|
||||
_chem_comp.pdbx_modified_date 2016-10-18
|
||||
_chem_comp.pdbx_ambiguous_flag N
|
||||
_chem_comp.pdbx_release_status REL
|
||||
_chem_comp.pdbx_replaced_by ?
|
||||
_chem_comp.pdbx_replaces 3KV
|
||||
_chem_comp.formula_weight 300.435
|
||||
_chem_comp.one_letter_code ?
|
||||
_chem_comp.three_letter_code REA
|
||||
_chem_comp.pdbx_model_coordinates_details ?
|
||||
_chem_comp.pdbx_model_coordinates_missing_flag N
|
||||
_chem_comp.pdbx_ideal_coordinates_details Corina
|
||||
_chem_comp.pdbx_ideal_coordinates_missing_flag N
|
||||
_chem_comp.pdbx_model_coordinates_db_code 1CBS
|
||||
_chem_comp.pdbx_subcomponent_list ?
|
||||
_chem_comp.pdbx_processing_site RCSB
|
||||
#
|
||||
loop_
|
||||
_chem_comp_atom.comp_id
|
||||
_chem_comp_atom.atom_id
|
||||
_chem_comp_atom.alt_atom_id
|
||||
_chem_comp_atom.type_symbol
|
||||
_chem_comp_atom.charge
|
||||
_chem_comp_atom.pdbx_align
|
||||
_chem_comp_atom.pdbx_aromatic_flag
|
||||
_chem_comp_atom.pdbx_leaving_atom_flag
|
||||
_chem_comp_atom.pdbx_stereo_config
|
||||
_chem_comp_atom.model_Cartn_x
|
||||
_chem_comp_atom.model_Cartn_y
|
||||
_chem_comp_atom.model_Cartn_z
|
||||
_chem_comp_atom.pdbx_model_Cartn_x_ideal
|
||||
_chem_comp_atom.pdbx_model_Cartn_y_ideal
|
||||
_chem_comp_atom.pdbx_model_Cartn_z_ideal
|
||||
_chem_comp_atom.pdbx_component_atom_id
|
||||
_chem_comp_atom.pdbx_component_comp_id
|
||||
_chem_comp_atom.pdbx_ordinal
|
||||
REA C1 C1 C 0 1 N N N 21.972 29.831 16.739 -4.684 0.932 -0.497 C1 REA 1
|
||||
REA C2 C2 C 0 1 N N N 20.921 30.524 15.841 -5.837 0.190 -1.176 C2 REA 2
|
||||
REA C3 C3 C 0 1 N N N 20.245 29.635 14.848 -6.441 -0.798 -0.171 C3 REA 3
|
||||
REA C4 C4 C 0 1 N N N 19.555 28.479 15.488 -5.418 -1.903 0.100 C4 REA 4
|
||||
REA C5 C5 C 0 1 N N N 20.389 27.812 16.587 -4.082 -1.301 0.429 C5 REA 5
|
||||
REA C6 C6 C 0 1 N N N 21.425 28.446 17.218 -3.756 -0.048 0.161 C6 REA 6
|
||||
REA C7 C7 C 0 1 N N N 22.242 27.851 18.297 -2.457 0.396 0.516 C7 REA 7
|
||||
REA C8 C8 C 0 1 N N N 21.868 26.977 19.240 -1.363 -0.229 0.007 C8 REA 8
|
||||
REA C9 C9 C 0 1 N N N 22.705 26.434 20.286 -0.076 0.257 0.298 C9 REA 9
|
||||
REA C10 C10 C 0 1 N N N 22.159 25.536 21.131 1.022 -0.370 -0.213 C10 REA 10
|
||||
REA C11 C11 C 0 1 N N N 22.875 24.924 22.234 2.306 0.115 0.077 C11 REA 11
|
||||
REA C12 C12 C 0 1 N N N 22.237 24.026 22.990 3.405 -0.513 -0.435 C12 REA 12
|
||||
REA C13 C13 C 0 1 N N N 22.856 23.377 24.125 4.689 -0.028 -0.144 C13 REA 13
|
||||
REA C14 C14 C 0 1 N N N 22.135 22.473 24.834 5.787 -0.655 -0.656 C14 REA 14
|
||||
REA C15 C15 C 0 1 N N N 22.563 21.710 26.016 7.077 -0.265 -0.244 C15 REA 15
|
||||
REA C16 C16 C 0 1 N N N 22.238 30.737 17.948 -5.246 1.886 0.559 C16 REA 16
|
||||
REA C17 C17 C 0 1 N N N 23.292 29.620 15.948 -3.911 1.737 -1.544 C17 REA 17
|
||||
REA C18 C18 C 0 1 N N N 19.791 26.449 16.947 -3.056 -2.175 1.103 C18 REA 18
|
||||
REA C19 C19 C 0 1 N N N 24.181 26.841 20.385 0.090 1.471 1.175 C19 REA 19
|
||||
REA C20 C20 C 0 1 N N N 24.303 23.747 24.489 4.855 1.186 0.733 C20 REA 20
|
||||
REA O1 O1 O 0 1 N N N 23.640 21.075 25.978 7.210 0.553 0.648 O1 REA 21
|
||||
REA O2 O2 O 0 1 N N N 21.840 21.712 27.037 8.166 -0.798 -0.840 O2 REA 22
|
||||
REA H21 H21 H 0 1 N N N 20.147 30.955 16.494 -6.598 0.905 -1.490 H21 REA 23
|
||||
REA H22 H22 H 0 1 N N N 21.425 31.330 15.288 -5.462 -0.353 -2.044 H22 REA 24
|
||||
REA H31 H31 H 0 1 N N N 19.501 30.227 14.295 -6.673 -0.278 0.759 H31 REA 25
|
||||
REA H32 H32 H 0 1 N N N 21.001 29.250 14.148 -7.349 -1.234 -0.586 H32 REA 26
|
||||
REA H41 H41 H 0 1 N N N 18.613 28.835 15.931 -5.756 -2.511 0.938 H41 REA 27
|
||||
REA H42 H42 H 0 1 N N N 19.335 27.730 14.713 -5.322 -2.531 -0.786 H42 REA 28
|
||||
REA H7 H7 H 0 1 N N N 23.276 28.162 18.329 -2.337 1.230 1.191 H7 REA 29
|
||||
REA H8 H8 H 0 1 N N N 20.840 26.645 19.217 -1.482 -1.100 -0.622 H8 REA 30
|
||||
REA H10 H10 H 0 1 N N N 21.127 25.256 20.977 0.903 -1.241 -0.842 H10 REA 31
|
||||
REA H11 H11 H 0 1 N N N 23.902 25.189 22.440 2.425 0.985 0.706 H11 REA 32
|
||||
REA H12 H12 H 0 1 N N N 21.216 23.774 22.743 3.286 -1.383 -1.063 H12 REA 33
|
||||
REA H14 H14 H 0 1 N N N 21.127 22.292 24.490 5.667 -1.451 -1.376 H14 REA 34
|
||||
REA H161 H161 H 0 0 N N N 22.984 30.265 18.604 -5.802 1.316 1.303 H161 REA 35
|
||||
REA H162 H162 H 0 0 N N N 22.618 31.709 17.601 -4.426 2.415 1.044 H162 REA 36
|
||||
REA H163 H163 H 0 0 N N N 21.302 30.887 18.506 -5.911 2.605 0.081 H163 REA 37
|
||||
REA H171 H171 H 0 0 N N N 24.033 29.127 16.595 -4.598 2.394 -2.077 H171 REA 38
|
||||
REA H172 H172 H 0 0 N N N 23.095 28.989 15.069 -3.146 2.335 -1.050 H172 REA 39
|
||||
REA H173 H173 H 0 0 N N N 23.683 30.595 15.620 -3.439 1.054 -2.251 H173 REA 40
|
||||
REA H181 H181 H 0 0 N N N 20.397 25.979 17.736 -3.448 -3.187 1.201 H181 REA 41
|
||||
REA H182 H182 H 0 0 N N N 18.761 26.584 17.308 -2.145 -2.194 0.503 H182 REA 42
|
||||
REA H183 H183 H 0 0 N N N 19.786 25.804 16.056 -2.831 -1.775 2.092 H183 REA 43
|
||||
REA H191 H191 H 0 0 N N N 24.647 26.327 21.238 0.171 1.159 2.216 H191 REA 44
|
||||
REA H192 H192 H 0 0 N N N 24.702 26.559 19.458 0.993 2.008 0.885 H192 REA 45
|
||||
REA H193 H193 H 0 0 N N N 24.252 27.929 20.529 -0.774 2.125 1.058 H193 REA 46
|
||||
REA H201 H201 H 0 0 N N N 24.620 23.168 25.369 5.026 0.871 1.762 H201 REA 47
|
||||
REA H202 H202 H 0 0 N N N 24.965 23.516 23.641 5.707 1.771 0.386 H202 REA 48
|
||||
REA H203 H203 H 0 0 N N N 24.360 24.822 24.717 3.952 1.795 0.685 H203 REA 49
|
||||
REA HO2 HO2 H 0 1 N N N 22.244 21.180 27.713 9.006 -0.469 -0.490 HO2 REA 50
|
||||
#
|
||||
loop_
|
||||
_chem_comp_bond.comp_id
|
||||
_chem_comp_bond.atom_id_1
|
||||
_chem_comp_bond.atom_id_2
|
||||
_chem_comp_bond.value_order
|
||||
_chem_comp_bond.pdbx_aromatic_flag
|
||||
_chem_comp_bond.pdbx_stereo_config
|
||||
_chem_comp_bond.pdbx_ordinal
|
||||
REA C1 C2 SING N N 1
|
||||
REA C1 C6 SING N N 2
|
||||
REA C1 C16 SING N N 3
|
||||
REA C1 C17 SING N N 4
|
||||
REA C2 C3 SING N N 5
|
||||
REA C2 H21 SING N N 6
|
||||
REA C2 H22 SING N N 7
|
||||
REA C3 C4 SING N N 8
|
||||
REA C3 H31 SING N N 9
|
||||
REA C3 H32 SING N N 10
|
||||
REA C4 C5 SING N N 11
|
||||
REA C4 H41 SING N N 12
|
||||
REA C4 H42 SING N N 13
|
||||
REA C5 C6 DOUB N N 14
|
||||
REA C5 C18 SING N N 15
|
||||
REA C6 C7 SING N N 16
|
||||
REA C7 C8 DOUB N E 17
|
||||
REA C7 H7 SING N N 18
|
||||
REA C8 C9 SING N N 19
|
||||
REA C8 H8 SING N N 20
|
||||
REA C9 C10 DOUB N E 21
|
||||
REA C9 C19 SING N N 22
|
||||
REA C10 C11 SING N N 23
|
||||
REA C10 H10 SING N N 24
|
||||
REA C11 C12 DOUB N E 25
|
||||
REA C11 H11 SING N N 26
|
||||
REA C12 C13 SING N N 27
|
||||
REA C12 H12 SING N N 28
|
||||
REA C13 C14 DOUB N E 29
|
||||
REA C13 C20 SING N N 30
|
||||
REA C14 C15 SING N N 31
|
||||
REA C14 H14 SING N N 32
|
||||
REA C15 O1 DOUB N N 33
|
||||
REA C15 O2 SING N N 34
|
||||
REA C16 H161 SING N N 35
|
||||
REA C16 H162 SING N N 36
|
||||
REA C16 H163 SING N N 37
|
||||
REA C17 H171 SING N N 38
|
||||
REA C17 H172 SING N N 39
|
||||
REA C17 H173 SING N N 40
|
||||
REA C18 H181 SING N N 41
|
||||
REA C18 H182 SING N N 42
|
||||
REA C18 H183 SING N N 43
|
||||
REA C19 H191 SING N N 44
|
||||
REA C19 H192 SING N N 45
|
||||
REA C19 H193 SING N N 46
|
||||
REA C20 H201 SING N N 47
|
||||
REA C20 H202 SING N N 48
|
||||
REA C20 H203 SING N N 49
|
||||
REA O2 HO2 SING N N 50
|
||||
#
|
||||
loop_
|
||||
_pdbx_chem_comp_descriptor.comp_id
|
||||
_pdbx_chem_comp_descriptor.type
|
||||
_pdbx_chem_comp_descriptor.program
|
||||
_pdbx_chem_comp_descriptor.program_version
|
||||
_pdbx_chem_comp_descriptor.descriptor
|
||||
REA SMILES ACDLabs 12.01 "C1(CCCC(=C1\C=C\C(=C\C=C\C(=C\C(=O)O)C)C)C)(C)C"
|
||||
REA InChI InChI 1.03 "InChI=1S/C20H28O2/c1-15(8-6-9-16(2)14-19(21)22)11-12-18-17(3)10-7-13-20(18,4)5/h6,8-9,11-12,14H,7,10,13H2,1-5H3,(H,21,22)/b9-6+,12-11+,15-8+,16-14+"
|
||||
REA InChIKey InChI 1.03 SHGAZHPCJJPHSC-YCNIQYBTSA-N
|
||||
REA SMILES_CANONICAL CACTVS 3.385 "CC1=C(\C=C\C(C)=C\C=C\C(C)=C\C(O)=O)C(C)(C)CCC1"
|
||||
REA SMILES CACTVS 3.385 "CC1=C(C=CC(C)=CC=CC(C)=CC(O)=O)C(C)(C)CCC1"
|
||||
REA SMILES_CANONICAL "OpenEye OEToolkits" 1.7.6 "CC1=C(C(CCC1)(C)C)/C=C/C(=C/C=C/C(=C/C(=O)O)/C)/C"
|
||||
REA SMILES "OpenEye OEToolkits" 1.7.6 "CC1=C(C(CCC1)(C)C)C=CC(=CC=CC(=CC(=O)O)C)C"
|
||||
#
|
||||
loop_
|
||||
_pdbx_chem_comp_identifier.comp_id
|
||||
_pdbx_chem_comp_identifier.type
|
||||
_pdbx_chem_comp_identifier.program
|
||||
_pdbx_chem_comp_identifier.program_version
|
||||
_pdbx_chem_comp_identifier.identifier
|
||||
REA "SYSTEMATIC NAME" ACDLabs 12.01 "retinoic acid"
|
||||
REA "SYSTEMATIC NAME" "OpenEye OEToolkits" 1.7.6 "(2E,4E,6E,8E)-3,7-dimethyl-9-(2,6,6-trimethylcyclohexen-1-yl)nona-2,4,6,8-tetraenoic acid"
|
||||
#
|
||||
loop_
|
||||
_pdbx_chem_comp_audit.comp_id
|
||||
_pdbx_chem_comp_audit.action_type
|
||||
_pdbx_chem_comp_audit.date
|
||||
_pdbx_chem_comp_audit.processing_site
|
||||
REA "Create component" 1999-07-08 RCSB
|
||||
REA "Modify descriptor" 2011-06-04 RCSB
|
||||
REA "Other modification" 2016-10-18 RCSB
|
||||
#
|
||||
189
test/RXA.cif
Normal file
189
test/RXA.cif
Normal file
@@ -0,0 +1,189 @@
|
||||
data_RXA
|
||||
#
|
||||
_chem_comp.id RXA
|
||||
_chem_comp.name "RENAMED RETINOIC ACID"
|
||||
_chem_comp.type NON-POLYMER
|
||||
_chem_comp.pdbx_type HETAIN
|
||||
_chem_comp.formula "C20 H28 O2"
|
||||
_chem_comp.mon_nstd_parent_comp_id ?
|
||||
_chem_comp.pdbx_synonyms ?
|
||||
_chem_comp.pdbx_formal_charge 0
|
||||
_chem_comp.pdbx_initial_date 1999-07-08
|
||||
_chem_comp.pdbx_modified_date 2016-10-18
|
||||
_chem_comp.pdbx_ambiguous_flag N
|
||||
_chem_comp.pdbx_release_status REL
|
||||
_chem_comp.pdbx_replaced_by ?
|
||||
_chem_comp.pdbx_replaces 3KV
|
||||
_chem_comp.formula_weight 300.435
|
||||
_chem_comp.one_letter_code ?
|
||||
_chem_comp.three_letter_code RXA
|
||||
_chem_comp.pdbx_model_coordinates_details ?
|
||||
_chem_comp.pdbx_model_coordinates_missing_flag N
|
||||
_chem_comp.pdbx_ideal_coordinates_details Corina
|
||||
_chem_comp.pdbx_ideal_coordinates_missing_flag N
|
||||
_chem_comp.pdbx_model_coordinates_db_code 1CBS
|
||||
_chem_comp.pdbx_subcomponent_list ?
|
||||
_chem_comp.pdbx_processing_site RCSB
|
||||
#
|
||||
loop_
|
||||
_chem_comp_atom.comp_id
|
||||
_chem_comp_atom.atom_id
|
||||
_chem_comp_atom.alt_atom_id
|
||||
_chem_comp_atom.type_symbol
|
||||
_chem_comp_atom.charge
|
||||
_chem_comp_atom.pdbx_align
|
||||
_chem_comp_atom.pdbx_aromatic_flag
|
||||
_chem_comp_atom.pdbx_leaving_atom_flag
|
||||
_chem_comp_atom.pdbx_stereo_config
|
||||
_chem_comp_atom.model_Cartn_x
|
||||
_chem_comp_atom.model_Cartn_y
|
||||
_chem_comp_atom.model_Cartn_z
|
||||
_chem_comp_atom.pdbx_model_Cartn_x_ideal
|
||||
_chem_comp_atom.pdbx_model_Cartn_y_ideal
|
||||
_chem_comp_atom.pdbx_model_Cartn_z_ideal
|
||||
_chem_comp_atom.pdbx_component_atom_id
|
||||
_chem_comp_atom.pdbx_component_comp_id
|
||||
_chem_comp_atom.pdbx_ordinal
|
||||
RXA C1 C1 C 0 1 N N N 21.972 29.831 16.739 -4.684 0.932 -0.497 C1 RXA 1
|
||||
RXA C2 C2 C 0 1 N N N 20.921 30.524 15.841 -5.837 0.190 -1.176 C2 RXA 2
|
||||
RXA C3 C3 C 0 1 N N N 20.245 29.635 14.848 -6.441 -0.798 -0.171 C3 RXA 3
|
||||
RXA C4 C4 C 0 1 N N N 19.555 28.479 15.488 -5.418 -1.903 0.100 C4 RXA 4
|
||||
RXA C5 C5 C 0 1 N N N 20.389 27.812 16.587 -4.082 -1.301 0.429 C5 RXA 5
|
||||
RXA C6 C6 C 0 1 N N N 21.425 28.446 17.218 -3.756 -0.048 0.161 C6 RXA 6
|
||||
RXA C7 C7 C 0 1 N N N 22.242 27.851 18.297 -2.457 0.396 0.516 C7 RXA 7
|
||||
RXA C8 C8 C 0 1 N N N 21.868 26.977 19.240 -1.363 -0.229 0.007 C8 RXA 8
|
||||
RXA C9 C9 C 0 1 N N N 22.705 26.434 20.286 -0.076 0.257 0.298 C9 RXA 9
|
||||
RXA C10 C10 C 0 1 N N N 22.159 25.536 21.131 1.022 -0.370 -0.213 C10 RXA 10
|
||||
RXA C11 C11 C 0 1 N N N 22.875 24.924 22.234 2.306 0.115 0.077 C11 RXA 11
|
||||
RXA C12 C12 C 0 1 N N N 22.237 24.026 22.990 3.405 -0.513 -0.435 C12 RXA 12
|
||||
RXA C13 C13 C 0 1 N N N 22.856 23.377 24.125 4.689 -0.028 -0.144 C13 RXA 13
|
||||
RXA C14 C14 C 0 1 N N N 22.135 22.473 24.834 5.787 -0.655 -0.656 C14 RXA 14
|
||||
RXA C15 C15 C 0 1 N N N 22.563 21.710 26.016 7.077 -0.265 -0.244 C15 RXA 15
|
||||
RXA C16 C16 C 0 1 N N N 22.238 30.737 17.948 -5.246 1.886 0.559 C16 RXA 16
|
||||
RXA C17 C17 C 0 1 N N N 23.292 29.620 15.948 -3.911 1.737 -1.544 C17 RXA 17
|
||||
RXA C18 C18 C 0 1 N N N 19.791 26.449 16.947 -3.056 -2.175 1.103 C18 RXA 18
|
||||
RXA C19 C19 C 0 1 N N N 24.181 26.841 20.385 0.090 1.471 1.175 C19 RXA 19
|
||||
RXA C20 C20 C 0 1 N N N 24.303 23.747 24.489 4.855 1.186 0.733 C20 RXA 20
|
||||
RXA O1 O1 O 0 1 N N N 23.640 21.075 25.978 7.210 0.553 0.648 O1 RXA 21
|
||||
RXA O2 O2 O 0 1 N N N 21.840 21.712 27.037 8.166 -0.798 -0.840 O2 RXA 22
|
||||
RXA H21 H21 H 0 1 N N N 20.147 30.955 16.494 -6.598 0.905 -1.490 H21 RXA 23
|
||||
RXA H22 H22 H 0 1 N N N 21.425 31.330 15.288 -5.462 -0.353 -2.044 H22 RXA 24
|
||||
RXA H31 H31 H 0 1 N N N 19.501 30.227 14.295 -6.673 -0.278 0.759 H31 RXA 25
|
||||
RXA H32 H32 H 0 1 N N N 21.001 29.250 14.148 -7.349 -1.234 -0.586 H32 RXA 26
|
||||
RXA H41 H41 H 0 1 N N N 18.613 28.835 15.931 -5.756 -2.511 0.938 H41 RXA 27
|
||||
RXA H42 H42 H 0 1 N N N 19.335 27.730 14.713 -5.322 -2.531 -0.786 H42 RXA 28
|
||||
RXA H7 H7 H 0 1 N N N 23.276 28.162 18.329 -2.337 1.230 1.191 H7 RXA 29
|
||||
RXA H8 H8 H 0 1 N N N 20.840 26.645 19.217 -1.482 -1.100 -0.622 H8 RXA 30
|
||||
RXA H10 H10 H 0 1 N N N 21.127 25.256 20.977 0.903 -1.241 -0.842 H10 RXA 31
|
||||
RXA H11 H11 H 0 1 N N N 23.902 25.189 22.440 2.425 0.985 0.706 H11 RXA 32
|
||||
RXA H12 H12 H 0 1 N N N 21.216 23.774 22.743 3.286 -1.383 -1.063 H12 RXA 33
|
||||
RXA H14 H14 H 0 1 N N N 21.127 22.292 24.490 5.667 -1.451 -1.376 H14 RXA 34
|
||||
RXA H161 H161 H 0 0 N N N 22.984 30.265 18.604 -5.802 1.316 1.303 H161 RXA 35
|
||||
RXA H162 H162 H 0 0 N N N 22.618 31.709 17.601 -4.426 2.415 1.044 H162 RXA 36
|
||||
RXA H163 H163 H 0 0 N N N 21.302 30.887 18.506 -5.911 2.605 0.081 H163 RXA 37
|
||||
RXA H171 H171 H 0 0 N N N 24.033 29.127 16.595 -4.598 2.394 -2.077 H171 RXA 38
|
||||
RXA H172 H172 H 0 0 N N N 23.095 28.989 15.069 -3.146 2.335 -1.050 H172 RXA 39
|
||||
RXA H173 H173 H 0 0 N N N 23.683 30.595 15.620 -3.439 1.054 -2.251 H173 RXA 40
|
||||
RXA H181 H181 H 0 0 N N N 20.397 25.979 17.736 -3.448 -3.187 1.201 H181 RXA 41
|
||||
RXA H182 H182 H 0 0 N N N 18.761 26.584 17.308 -2.145 -2.194 0.503 H182 RXA 42
|
||||
RXA H183 H183 H 0 0 N N N 19.786 25.804 16.056 -2.831 -1.775 2.092 H183 RXA 43
|
||||
RXA H191 H191 H 0 0 N N N 24.647 26.327 21.238 0.171 1.159 2.216 H191 RXA 44
|
||||
RXA H192 H192 H 0 0 N N N 24.702 26.559 19.458 0.993 2.008 0.885 H192 RXA 45
|
||||
RXA H193 H193 H 0 0 N N N 24.252 27.929 20.529 -0.774 2.125 1.058 H193 RXA 46
|
||||
RXA H201 H201 H 0 0 N N N 24.620 23.168 25.369 5.026 0.871 1.762 H201 RXA 47
|
||||
RXA H202 H202 H 0 0 N N N 24.965 23.516 23.641 5.707 1.771 0.386 H202 RXA 48
|
||||
RXA H203 H203 H 0 0 N N N 24.360 24.822 24.717 3.952 1.795 0.685 H203 RXA 49
|
||||
RXA HO2 HO2 H 0 1 N N N 22.244 21.180 27.713 9.006 -0.469 -0.490 HO2 RXA 50
|
||||
#
|
||||
loop_
|
||||
_chem_comp_bond.comp_id
|
||||
_chem_comp_bond.atom_id_1
|
||||
_chem_comp_bond.atom_id_2
|
||||
_chem_comp_bond.value_order
|
||||
_chem_comp_bond.pdbx_aromatic_flag
|
||||
_chem_comp_bond.pdbx_stereo_config
|
||||
_chem_comp_bond.pdbx_ordinal
|
||||
RXA C1 C2 SING N N 1
|
||||
RXA C1 C6 SING N N 2
|
||||
RXA C1 C16 SING N N 3
|
||||
RXA C1 C17 SING N N 4
|
||||
RXA C2 C3 SING N N 5
|
||||
RXA C2 H21 SING N N 6
|
||||
RXA C2 H22 SING N N 7
|
||||
RXA C3 C4 SING N N 8
|
||||
RXA C3 H31 SING N N 9
|
||||
RXA C3 H32 SING N N 10
|
||||
RXA C4 C5 SING N N 11
|
||||
RXA C4 H41 SING N N 12
|
||||
RXA C4 H42 SING N N 13
|
||||
RXA C5 C6 DOUB N N 14
|
||||
RXA C5 C18 SING N N 15
|
||||
RXA C6 C7 SING N N 16
|
||||
RXA C7 C8 DOUB N E 17
|
||||
RXA C7 H7 SING N N 18
|
||||
RXA C8 C9 SING N N 19
|
||||
RXA C8 H8 SING N N 20
|
||||
RXA C9 C10 DOUB N E 21
|
||||
RXA C9 C19 SING N N 22
|
||||
RXA C10 C11 SING N N 23
|
||||
RXA C10 H10 SING N N 24
|
||||
RXA C11 C12 DOUB N E 25
|
||||
RXA C11 H11 SING N N 26
|
||||
RXA C12 C13 SING N N 27
|
||||
RXA C12 H12 SING N N 28
|
||||
RXA C13 C14 DOUB N E 29
|
||||
RXA C13 C20 SING N N 30
|
||||
RXA C14 C15 SING N N 31
|
||||
RXA C14 H14 SING N N 32
|
||||
RXA C15 O1 DOUB N N 33
|
||||
RXA C15 O2 SING N N 34
|
||||
RXA C16 H161 SING N N 35
|
||||
RXA C16 H162 SING N N 36
|
||||
RXA C16 H163 SING N N 37
|
||||
RXA C17 H171 SING N N 38
|
||||
RXA C17 H172 SING N N 39
|
||||
RXA C17 H173 SING N N 40
|
||||
RXA C18 H181 SING N N 41
|
||||
RXA C18 H182 SING N N 42
|
||||
RXA C18 H183 SING N N 43
|
||||
RXA C19 H191 SING N N 44
|
||||
RXA C19 H192 SING N N 45
|
||||
RXA C19 H193 SING N N 46
|
||||
RXA C20 H201 SING N N 47
|
||||
RXA C20 H202 SING N N 48
|
||||
RXA C20 H203 SING N N 49
|
||||
RXA O2 HO2 SING N N 50
|
||||
#
|
||||
loop_
|
||||
_pdbx_chem_comp_descriptor.comp_id
|
||||
_pdbx_chem_comp_descriptor.type
|
||||
_pdbx_chem_comp_descriptor.program
|
||||
_pdbx_chem_comp_descriptor.program_version
|
||||
_pdbx_chem_comp_descriptor.descriptor
|
||||
RXA SMILES ACDLabs 12.01 "C1(CCCC(=C1\C=C\C(=C\C=C\C(=C\C(=O)O)C)C)C)(C)C"
|
||||
RXA InChI InChI 1.03 "InChI=1S/C20H28O2/c1-15(8-6-9-16(2)14-19(21)22)11-12-18-17(3)10-7-13-20(18,4)5/h6,8-9,11-12,14H,7,10,13H2,1-5H3,(H,21,22)/b9-6+,12-11+,15-8+,16-14+"
|
||||
RXA InChIKey InChI 1.03 SHGAZHPCJJPHSC-YCNIQYBTSA-N
|
||||
RXA SMILES_CANONICAL CACTVS 3.385 "CC1=C(\C=C\C(C)=C\C=C\C(C)=C\C(O)=O)C(C)(C)CCC1"
|
||||
RXA SMILES CACTVS 3.385 "CC1=C(C=CC(C)=CC=CC(C)=CC(O)=O)C(C)(C)CCC1"
|
||||
RXA SMILES_CANONICAL "OpenEye OEToolkits" 1.7.6 "CC1=C(C(CCC1)(C)C)/C=C/C(=C/C=C/C(=C/C(=O)O)/C)/C"
|
||||
RXA SMILES "OpenEye OEToolkits" 1.7.6 "CC1=C(C(CCC1)(C)C)C=CC(=CC=CC(=CC(=O)O)C)C"
|
||||
#
|
||||
loop_
|
||||
_pdbx_chem_comp_identifier.comp_id
|
||||
_pdbx_chem_comp_identifier.type
|
||||
_pdbx_chem_comp_identifier.program
|
||||
_pdbx_chem_comp_identifier.program_version
|
||||
_pdbx_chem_comp_identifier.identifier
|
||||
RXA "SYSTEMATIC NAME" ACDLabs 12.01 "retinoic acid"
|
||||
RXA "SYSTEMATIC NAME" "OpenEye OEToolkits" 1.7.6 "(2E,4E,6E,8E)-3,7-dimethyl-9-(2,6,6-trimethylcyclohexen-1-yl)nona-2,4,6,8-tetraenoic acid"
|
||||
#
|
||||
loop_
|
||||
_pdbx_chem_comp_audit.comp_id
|
||||
_pdbx_chem_comp_audit.action_type
|
||||
_pdbx_chem_comp_audit.date
|
||||
_pdbx_chem_comp_audit.processing_site
|
||||
RXA "Create component" 1999-07-08 RCSB
|
||||
RXA "Modify descriptor" 2011-06-04 RCSB
|
||||
RXA "Other modification" 2016-10-18 RCSB
|
||||
#
|
||||
|
||||
152
test/UN_.cif
Normal file
152
test/UN_.cif
Normal file
@@ -0,0 +1,152 @@
|
||||
#
|
||||
data_comp_list
|
||||
loop_
|
||||
_chem_comp.id
|
||||
_chem_comp.three_letter_code
|
||||
_chem_comp.name
|
||||
_chem_comp.group
|
||||
_chem_comp.number_atoms_all
|
||||
_chem_comp.number_atoms_nh
|
||||
_chem_comp.desc_level
|
||||
UN_ UN_ UN_NINE L-peptide 13 6 .
|
||||
#
|
||||
data_comp_UN_
|
||||
#
|
||||
loop_
|
||||
_chem_comp_atom.comp_id
|
||||
_chem_comp_atom.atom_id
|
||||
_chem_comp_atom.type_symbol
|
||||
_chem_comp_atom.type_energy
|
||||
_chem_comp_atom.charge
|
||||
_chem_comp_atom.x
|
||||
_chem_comp_atom.y
|
||||
_chem_comp_atom.z
|
||||
UN_ N N NT3 1 0.227 -1.259 0.452
|
||||
UN_ H H H 0 0.069 -1.019 1.421
|
||||
UN_ H2 H H 0 1.104 -1.640 0.356
|
||||
UN_ H3 H H 0 -0.424 -1.909 0.174
|
||||
UN_ CA C CH1 0 0.103 -0.030 -0.392
|
||||
UN_ HA H H 0 0.160 -0.299 -1.339
|
||||
UN_ CB C CH3 0 -1.244 0.625 -0.159
|
||||
UN_ HB3 H H 0 -1.857 -0.018 0.234
|
||||
UN_ HB2 H H 0 -1.605 0.932 -1.008
|
||||
UN_ HB1 H H 0 -1.150 1.385 0.442
|
||||
UN_ C C C 0 1.270 0.922 -0.094
|
||||
UN_ O O O 0 2.008 1.323 -0.994
|
||||
UN_ OXT O OC -1 1.498 1.305 1.054
|
||||
|
||||
loop_
|
||||
_chem_comp_tree.comp_id
|
||||
_chem_comp_tree.atom_id
|
||||
_chem_comp_tree.atom_back
|
||||
_chem_comp_tree.atom_forward
|
||||
_chem_comp_tree.connect_type
|
||||
UN_ N n/a CA START
|
||||
UN_ H N . .
|
||||
UN_ H2 N . .
|
||||
UN_ H3 N . .
|
||||
UN_ CA N C .
|
||||
UN_ HA CA . .
|
||||
UN_ CB CA HB3 .
|
||||
UN_ HB1 CB . .
|
||||
UN_ HB2 CB . .
|
||||
UN_ HB3 CB . .
|
||||
UN_ C CA . END
|
||||
UN_ O C . .
|
||||
UN_ OXT C . .
|
||||
loop_
|
||||
_chem_comp_bond.comp_id
|
||||
_chem_comp_bond.atom_id_1
|
||||
_chem_comp_bond.atom_id_2
|
||||
_chem_comp_bond.type
|
||||
_chem_comp_bond.aromatic
|
||||
_chem_comp_bond.value_dist
|
||||
_chem_comp_bond.value_dist_esd
|
||||
UN_ CB CA SINGLE n 1.509 0.014
|
||||
UN_ CA C SINGLE n 1.533 0.011
|
||||
UN_ C O DOUBLE n 1.247 0.019
|
||||
UN_ C OXT SINGLE n 1.247 0.019
|
||||
UN_ CA N SINGLE n 1.482 0.010
|
||||
UN_ CB HB3 SINGLE n 0.972 0.015
|
||||
UN_ CB HB2 SINGLE n 0.972 0.015
|
||||
UN_ CB HB1 SINGLE n 0.972 0.015
|
||||
UN_ CA HA SINGLE n 0.986 0.020
|
||||
UN_ N H SINGLE n 0.911 0.020
|
||||
UN_ N H2 SINGLE n 0.911 0.020
|
||||
UN_ N H3 SINGLE n 0.911 0.020
|
||||
loop_
|
||||
_chem_comp_angle.comp_id
|
||||
_chem_comp_angle.atom_id_1
|
||||
_chem_comp_angle.atom_id_2
|
||||
_chem_comp_angle.atom_id_3
|
||||
_chem_comp_angle.value_angle
|
||||
_chem_comp_angle.value_angle_esd
|
||||
UN_ CA CB HB3 109.546 1.50
|
||||
UN_ CA CB HB2 109.546 1.50
|
||||
UN_ CA CB HB1 109.546 1.50
|
||||
UN_ HB3 CB HB2 109.386 1.50
|
||||
UN_ HB3 CB HB1 109.386 1.50
|
||||
UN_ HB2 CB HB1 109.386 1.50
|
||||
UN_ CB CA C 111.490 1.50
|
||||
UN_ CB CA N 109.912 1.50
|
||||
UN_ CB CA HA 108.878 1.50
|
||||
UN_ C CA N 109.627 1.50
|
||||
UN_ C CA HA 108.541 1.50
|
||||
UN_ N CA HA 108.529 1.50
|
||||
UN_ CA C O 117.159 1.57
|
||||
UN_ CA C OXT 117.159 1.57
|
||||
UN_ O C OXT 125.683 1.50
|
||||
UN_ CA N H 109.643 1.50
|
||||
UN_ CA N H2 109.643 1.50
|
||||
UN_ CA N H3 109.643 1.50
|
||||
UN_ H N H2 109.028 2.41
|
||||
UN_ H N H3 109.028 2.41
|
||||
UN_ H2 N H3 109.028 2.41
|
||||
loop_
|
||||
_chem_comp_tor.comp_id
|
||||
_chem_comp_tor.id
|
||||
_chem_comp_tor.atom_id_1
|
||||
_chem_comp_tor.atom_id_2
|
||||
_chem_comp_tor.atom_id_3
|
||||
_chem_comp_tor.atom_id_4
|
||||
_chem_comp_tor.value_angle
|
||||
_chem_comp_tor.value_angle_esd
|
||||
_chem_comp_tor.period
|
||||
UN_ hh1 N CA CB HB3 60.000 15.000 3
|
||||
UN_ sp2_sp3_1 O C CA CB 0.000 10.00 6
|
||||
UN_ sp3_sp3_10 CB CA N H 180.000 10.00 3
|
||||
loop_
|
||||
_chem_comp_chir.comp_id
|
||||
_chem_comp_chir.id
|
||||
_chem_comp_chir.atom_id_centre
|
||||
_chem_comp_chir.atom_id_1
|
||||
_chem_comp_chir.atom_id_2
|
||||
_chem_comp_chir.atom_id_3
|
||||
_chem_comp_chir.volume_sign
|
||||
UN_ chir_1 CA N C CB positive
|
||||
loop_
|
||||
_chem_comp_plane_atom.comp_id
|
||||
_chem_comp_plane_atom.plane_id
|
||||
_chem_comp_plane_atom.atom_id
|
||||
_chem_comp_plane_atom.dist_esd
|
||||
UN_ plan-1 C 0.020
|
||||
UN_ plan-1 CA 0.020
|
||||
UN_ plan-1 O 0.020
|
||||
UN_ plan-1 OXT 0.020
|
||||
loop_
|
||||
_pdbx_chem_comp_descriptor.comp_id
|
||||
_pdbx_chem_comp_descriptor.type
|
||||
_pdbx_chem_comp_descriptor.program
|
||||
_pdbx_chem_comp_descriptor.program_version
|
||||
_pdbx_chem_comp_descriptor.descriptor
|
||||
UN_ SMILES ACDLabs 10.04 "O=C(O)C(N)C"
|
||||
UN_ SMILES_CANONICAL CACTVS 3.341 "C[C@H](N)C(O)=O"
|
||||
UN_ SMILES CACTVS 3.341 "C[CH](N)C(O)=O"
|
||||
UN_ SMILES_CANONICAL "OpenEye OEToolkits" 1.5.0 "C[C@@H](C(=O)O)N"
|
||||
UN_ SMILES "OpenEye OEToolkits" 1.5.0 "CC(C(=O)O)N"
|
||||
UN_ InChI InChI 1.03 "InChI=1S/C3H7NO2/c1-2(4)3(5)6/h2H,4H2,1H3,(H,5,6)/t2-/m0/s1"
|
||||
UN_ InChIKey InChI 1.03 QNAYBMKLOCPYGJ-REOHCLBHSA-N
|
||||
UN_ ? acedrg 195 "dictionary generator"
|
||||
UN_ ? acedrg_database 11 "data source"
|
||||
UN_ ? rdkit 2017.03.2 "Chemoinformatics tool"
|
||||
UN_ ? refmac5 5.8.0189 "optimization tool"
|
||||
50
test/pdb2cif-test.cpp
Normal file
50
test/pdb2cif-test.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "../include/cif++/Cif++.hpp"
|
||||
#include "../include/cif++/PDB2Cif.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
// #include "pdb2cif.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
po::options_description desc("pdb2cif-test options");
|
||||
desc.add_options()
|
||||
("input,i", po::value<std::string>(), "Input file")
|
||||
("help,h", "Display help message")
|
||||
("verbose,v", "Verbose output")
|
||||
("debug,d", po::value<int>(), "Debug level (for even more verbose output)");
|
||||
|
||||
po::positional_options_description p;
|
||||
p.add("input", 1);
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
|
||||
po::notify(vm);
|
||||
|
||||
if (vm.count("help") or vm.count("input") == 0)
|
||||
{
|
||||
std::cerr << desc << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cif::VERBOSE = vm.count("verbose") != 0;
|
||||
if (vm.count("debug"))
|
||||
cif::VERBOSE = vm["debug"].as<int>();
|
||||
|
||||
std::ifstream is(vm["input"].as<std::string>());
|
||||
if (not is.is_open())
|
||||
throw std::runtime_error("Could not open file " + vm["input"].as<std::string>());
|
||||
|
||||
cif::File f;
|
||||
ReadPDBFile(is, f);
|
||||
f.save(std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
49
test/rename-compound-test.cpp
Normal file
49
test/rename-compound-test.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "../include/cif++/Cif++.hpp"
|
||||
#include "../include/cif++/PDB2Cif.hpp"
|
||||
#include "../include/cif++/Structure.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
cif::VERBOSE = 3;
|
||||
|
||||
try
|
||||
{
|
||||
std::filesystem::path testdir = std::filesystem::current_path();
|
||||
|
||||
if (argc == 3)
|
||||
testdir = argv[2];
|
||||
|
||||
if (std::filesystem::exists(testdir / ".." / "data" / "ccd-subset.cif"))
|
||||
cif::addFileResource("components.cif", testdir / ".." / "data" / "ccd-subset.cif");
|
||||
|
||||
if (std::filesystem::exists(testdir / ".." / "rsrc" / "mmcif_pdbx_v50.dic"))
|
||||
cif::addFileResource("mmcif_pdbx_v50.dic", testdir / ".." / "rsrc" / "mmcif_pdbx_v50.dic");
|
||||
|
||||
mmcif::CompoundFactory::instance().pushDictionary(testdir / "REA.cif");
|
||||
mmcif::CompoundFactory::instance().pushDictionary(testdir / "RXA.cif");
|
||||
|
||||
mmcif::File f(testdir / ".."/"examples"/"1cbs.cif.gz");
|
||||
mmcif::Structure structure(f);
|
||||
|
||||
auto &res = structure.getResidue("B");
|
||||
structure.changeResidue(res, "RXA", {});
|
||||
|
||||
structure.cleanupEmptyCategories();
|
||||
|
||||
f.save(std::cout);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
359
test/structure-test.cpp
Normal file
359
test/structure-test.cpp
Normal file
@@ -0,0 +1,359 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_ALTERNATIVE_INIT_API
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
#include "cif++/Structure.hpp"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::File operator""_cf(const char* text, size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char* text, size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} buffer(const_cast<char*>(text), length);
|
||||
|
||||
std::istream is(&buffer);
|
||||
return cif::File(is);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::filesystem::path gTestDir = std::filesystem::current_path();
|
||||
|
||||
bool init_unit_test()
|
||||
{
|
||||
cif::VERBOSE = 1;
|
||||
|
||||
// not a test, just initialize test dir
|
||||
if (boost::unit_test::framework::master_test_suite().argc == 2)
|
||||
gTestDir = boost::unit_test::framework::master_test_suite().argv[1];
|
||||
|
||||
// do this now, avoids the need for installing
|
||||
cif::addFileResource("mmcif_pdbx_v50.dic", gTestDir / ".." / "rsrc" / "mmcif_pdbx_v50.dic");
|
||||
|
||||
// initialize CCD location
|
||||
cif::addFileResource("components.cif", gTestDir / ".." / "data" / "ccd-subset.cif");
|
||||
|
||||
mmcif::CompoundFactory::instance().pushDictionary(gTestDir / "HEM.cif");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(create_nonpoly_1)
|
||||
{
|
||||
cif::VERBOSE = 1;
|
||||
|
||||
mmcif::File file;
|
||||
file.loadDictionary("mmcif_pdbx_v50.dic");
|
||||
file.emplace("TEST"); // create a datablock
|
||||
|
||||
mmcif::Structure structure(file);
|
||||
|
||||
std::string entity_id = structure.createNonPolyEntity("HEM");
|
||||
|
||||
auto atoms = R"(
|
||||
data_HEM
|
||||
loop_
|
||||
_atom_site.group_PDB
|
||||
_atom_site.type_symbol
|
||||
_atom_site.label_atom_id
|
||||
_atom_site.label_alt_id
|
||||
_atom_site.pdbx_PDB_ins_code
|
||||
_atom_site.Cartn_x
|
||||
_atom_site.Cartn_y
|
||||
_atom_site.Cartn_z
|
||||
_atom_site.occupancy
|
||||
_atom_site.B_iso_or_equiv
|
||||
_atom_site.pdbx_formal_charge
|
||||
HETATM C CHA . ? -5.248 39.769 -0.250 1.00 7.67 ?
|
||||
HETATM C CHB . ? -3.774 36.790 3.280 1.00 7.05 ?
|
||||
HETATM C CHC . ? -2.879 33.328 0.013 1.00 7.69 ?
|
||||
HETATM C CHD . ? -4.342 36.262 -3.536 1.00 8.00 ?
|
||||
# that's enough to test with
|
||||
)"_cf;
|
||||
|
||||
auto &hem_data = atoms["HEM"];
|
||||
auto &atom_site = hem_data["atom_site"];
|
||||
|
||||
auto hem_atoms = atom_site.rows();
|
||||
std::vector<mmcif::Atom> atom_data;
|
||||
for (auto &hem_atom: hem_atoms)
|
||||
atom_data.emplace_back(hem_data, hem_atom);
|
||||
|
||||
structure.createNonpoly(entity_id, atom_data);
|
||||
|
||||
auto expected = R"(
|
||||
data_TEST
|
||||
#
|
||||
_pdbx_nonpoly_scheme.asym_id A
|
||||
_pdbx_nonpoly_scheme.ndb_seq_num 1
|
||||
_pdbx_nonpoly_scheme.entity_id 1
|
||||
_pdbx_nonpoly_scheme.mon_id HEM
|
||||
_pdbx_nonpoly_scheme.pdb_seq_num 1
|
||||
_pdbx_nonpoly_scheme.auth_seq_num 1
|
||||
_pdbx_nonpoly_scheme.pdb_mon_id HEM
|
||||
_pdbx_nonpoly_scheme.auth_mon_id HEM
|
||||
_pdbx_nonpoly_scheme.pdb_strand_id A
|
||||
_pdbx_nonpoly_scheme.pdb_ins_code .
|
||||
#
|
||||
loop_
|
||||
_atom_site.id
|
||||
_atom_site.auth_asym_id
|
||||
_atom_site.label_alt_id
|
||||
_atom_site.label_asym_id
|
||||
_atom_site.label_atom_id
|
||||
_atom_site.label_comp_id
|
||||
_atom_site.label_entity_id
|
||||
_atom_site.label_seq_id
|
||||
_atom_site.type_symbol
|
||||
_atom_site.group_PDB
|
||||
_atom_site.pdbx_PDB_ins_code
|
||||
_atom_site.Cartn_x
|
||||
_atom_site.Cartn_y
|
||||
_atom_site.Cartn_z
|
||||
_atom_site.occupancy
|
||||
_atom_site.B_iso_or_equiv
|
||||
_atom_site.pdbx_formal_charge
|
||||
_atom_site.auth_seq_id
|
||||
_atom_site.auth_comp_id
|
||||
_atom_site.auth_atom_id
|
||||
_atom_site.pdbx_PDB_model_num
|
||||
1 A ? A CHA HEM 1 . C HETATM ? -5.248 39.769 -0.250 1.00 7.67 ? 1 HEM CHA 1
|
||||
2 A ? A CHB HEM 1 . C HETATM ? -3.774 36.790 3.280 1.00 7.05 ? 1 HEM CHB 1
|
||||
3 A ? A CHC HEM 1 . C HETATM ? -2.879 33.328 0.013 1.00 7.69 ? 1 HEM CHC 1
|
||||
4 A ? A CHD HEM 1 . C HETATM ? -4.342 36.262 -3.536 1.00 8.00 ? 1 HEM CHD 1
|
||||
#
|
||||
_chem_comp.id HEM
|
||||
_chem_comp.type NON-POLYMER
|
||||
_chem_comp.name 'PROTOPORPHYRIN IX CONTAINING FE'
|
||||
_chem_comp.formula 'C34 H32 Fe N4 O4'
|
||||
_chem_comp.formula_weight 616.487000
|
||||
#
|
||||
_pdbx_entity_nonpoly.entity_id 1
|
||||
_pdbx_entity_nonpoly.name 'PROTOPORPHYRIN IX CONTAINING FE'
|
||||
_pdbx_entity_nonpoly.comp_id HEM
|
||||
#
|
||||
_entity.id 1
|
||||
_entity.type non-polymer
|
||||
_entity.pdbx_description 'PROTOPORPHYRIN IX CONTAINING FE'
|
||||
_entity.formula_weight 616.487000
|
||||
#
|
||||
_struct_asym.id A
|
||||
_struct_asym.entity_id 1
|
||||
_struct_asym.pdbx_blank_PDB_chainid_flag N
|
||||
_struct_asym.pdbx_modified N
|
||||
_struct_asym.details ?
|
||||
#
|
||||
)"_cf;
|
||||
|
||||
expected.loadDictionary("mmcif_pdbx_v50.dic");
|
||||
|
||||
if (not (expected.firstDatablock() == structure.datablock()))
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
std::cout << expected.firstDatablock() << std::endl
|
||||
<< std::endl
|
||||
<< structure.datablock() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
// BOOST_AUTO_TEST_CASE(test_load_1)
|
||||
// {
|
||||
// mmcif::File cf(gTestDir / "5v3g.cif.gz");
|
||||
// mmcif::Structure s(cf);
|
||||
|
||||
// for (auto &poly : s.polymers())
|
||||
// {
|
||||
// std::cout << std::string(80, '=') << std::endl;
|
||||
// for (auto &res : poly)
|
||||
// {
|
||||
// std::cout << res << std::endl;
|
||||
|
||||
// for (auto &atom : res.atoms())
|
||||
// std::cout << " " << atom << std::endl;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_atom_id)
|
||||
{
|
||||
auto data = R"(
|
||||
data_TEST
|
||||
#
|
||||
_pdbx_nonpoly_scheme.asym_id A
|
||||
_pdbx_nonpoly_scheme.ndb_seq_num 1
|
||||
_pdbx_nonpoly_scheme.entity_id 1
|
||||
_pdbx_nonpoly_scheme.mon_id HEM
|
||||
_pdbx_nonpoly_scheme.pdb_seq_num 1
|
||||
_pdbx_nonpoly_scheme.auth_seq_num 1
|
||||
_pdbx_nonpoly_scheme.pdb_mon_id HEM
|
||||
_pdbx_nonpoly_scheme.auth_mon_id HEM
|
||||
_pdbx_nonpoly_scheme.pdb_strand_id A
|
||||
_pdbx_nonpoly_scheme.pdb_ins_code .
|
||||
#
|
||||
loop_
|
||||
_atom_site.id
|
||||
_atom_site.auth_asym_id
|
||||
_atom_site.label_alt_id
|
||||
_atom_site.label_asym_id
|
||||
_atom_site.label_atom_id
|
||||
_atom_site.label_comp_id
|
||||
_atom_site.label_entity_id
|
||||
_atom_site.label_seq_id
|
||||
_atom_site.type_symbol
|
||||
_atom_site.group_PDB
|
||||
_atom_site.pdbx_PDB_ins_code
|
||||
_atom_site.Cartn_x
|
||||
_atom_site.Cartn_y
|
||||
_atom_site.Cartn_z
|
||||
_atom_site.occupancy
|
||||
_atom_site.B_iso_or_equiv
|
||||
_atom_site.pdbx_formal_charge
|
||||
_atom_site.auth_seq_id
|
||||
_atom_site.auth_comp_id
|
||||
_atom_site.auth_atom_id
|
||||
_atom_site.pdbx_PDB_model_num
|
||||
1 A ? A CHA HEM 1 . C HETATM ? -5.248 39.769 -0.250 1.00 7.67 ? 1 HEM CHA 1
|
||||
3 A ? A CHB HEM 1 . C HETATM ? -3.774 36.790 3.280 1.00 7.05 ? 1 HEM CHB 1
|
||||
2 A ? A CHC HEM 1 . C HETATM ? -2.879 33.328 0.013 1.00 7.69 ? 1 HEM CHC 1
|
||||
4 A ? A CHD HEM 1 . C HETATM ? -4.342 36.262 -3.536 1.00 8.00 ? 1 HEM CHD 1
|
||||
#
|
||||
_chem_comp.id HEM
|
||||
_chem_comp.type NON-POLYMER
|
||||
_chem_comp.name 'PROTOPORPHYRIN IX CONTAINING FE'
|
||||
_chem_comp.formula 'C34 H32 Fe N4 O4'
|
||||
_chem_comp.formula_weight 616.487000
|
||||
#
|
||||
_pdbx_entity_nonpoly.entity_id 1
|
||||
_pdbx_entity_nonpoly.name 'PROTOPORPHYRIN IX CONTAINING FE'
|
||||
_pdbx_entity_nonpoly.comp_id HEM
|
||||
#
|
||||
_entity.id 1
|
||||
_entity.type non-polymer
|
||||
_entity.pdbx_description 'PROTOPORPHYRIN IX CONTAINING FE'
|
||||
_entity.formula_weight 616.487000
|
||||
#
|
||||
_struct_asym.id A
|
||||
_struct_asym.entity_id 1
|
||||
_struct_asym.pdbx_blank_PDB_chainid_flag N
|
||||
_struct_asym.pdbx_modified N
|
||||
_struct_asym.details ?
|
||||
#
|
||||
)"_cf;
|
||||
|
||||
data.loadDictionary("mmcif_pdbx_v50.dic");
|
||||
|
||||
mmcif::Structure s(data);
|
||||
|
||||
BOOST_CHECK_EQUAL(s.getAtomByID("1").authAtomID(), "CHA");
|
||||
BOOST_CHECK_EQUAL(s.getAtomByID("2").authAtomID(), "CHC");
|
||||
BOOST_CHECK_EQUAL(s.getAtomByID("3").authAtomID(), "CHB");
|
||||
BOOST_CHECK_EQUAL(s.getAtomByID("4").authAtomID(), "CHD");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(atom_numbers_1)
|
||||
{
|
||||
const std::filesystem::path test1(gTestDir / ".." / "examples" / "1cbs.cif.gz");
|
||||
mmcif::File file(test1.string());
|
||||
mmcif::Structure structure(file);
|
||||
|
||||
auto &db = file.data();
|
||||
|
||||
auto &atoms = structure.atoms();
|
||||
auto ai = atoms.begin();
|
||||
|
||||
for (const auto &[id, label_asym_id, label_seq_id, label_atom_id, auth_seq_id, label_comp_id] :
|
||||
db["atom_site"].rows<std::string,std::string,int,std::string,std::string,std::string>("id", "label_asym_id", "label_seq_id", "label_atom_id", "auth_seq_id", "label_comp_id"))
|
||||
{
|
||||
auto atom = structure.getAtomByID(id);
|
||||
|
||||
BOOST_CHECK_EQUAL(atom.labelAsymID(), label_asym_id);
|
||||
BOOST_CHECK_EQUAL(atom.labelSeqID(), label_seq_id);
|
||||
BOOST_CHECK_EQUAL(atom.labelAtomID(), label_atom_id);
|
||||
BOOST_CHECK_EQUAL(atom.authSeqID(), auth_seq_id);
|
||||
BOOST_CHECK_EQUAL(atom.labelCompID(), label_comp_id);
|
||||
|
||||
BOOST_ASSERT(ai != atoms.end());
|
||||
|
||||
BOOST_CHECK_EQUAL(ai->id(), id);
|
||||
++ai;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(ai == atoms.end());
|
||||
}
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_load_1)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / ".." / "examples" / "1cbs.cif.gz");
|
||||
mmcif::File file(example.string());
|
||||
|
||||
auto &db = file.data();
|
||||
|
||||
mmcif::Structure s(file);
|
||||
|
||||
BOOST_CHECK(s.polymers().size() == 1);
|
||||
|
||||
auto &pdbx_poly_seq_scheme = db["pdbx_poly_seq_scheme"];
|
||||
|
||||
for (auto &poly : s.polymers())
|
||||
{
|
||||
BOOST_CHECK_EQUAL(poly.size(), pdbx_poly_seq_scheme.find("asym_id"_key == poly.asymID()).size());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(remove_residue_1)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / ".." / "examples" / "1cbs.cif.gz");
|
||||
mmcif::File file(example.string());
|
||||
|
||||
mmcif::Structure s(file);
|
||||
s.removeResidue(s.getResidue("B"));
|
||||
|
||||
BOOST_CHECK_NO_THROW(s.validateAtoms());
|
||||
}
|
||||
168
test/sugar-test.cpp
Normal file
168
test/sugar-test.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_ALTERNATIVE_INIT_API
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "cif++/Cif++.hpp"
|
||||
#include "cif++/Structure.hpp"
|
||||
#include "cif++/CifValidator.hpp"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::File operator""_cf(const char* text, size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char* text, size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} buffer(const_cast<char*>(text), length);
|
||||
|
||||
std::istream is(&buffer);
|
||||
return cif::File(is);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::filesystem::path gTestDir = std::filesystem::current_path();
|
||||
|
||||
bool init_unit_test()
|
||||
{
|
||||
cif::VERBOSE = 1;
|
||||
|
||||
// not a test, just initialize test dir
|
||||
if (boost::unit_test::framework::master_test_suite().argc == 2)
|
||||
gTestDir = boost::unit_test::framework::master_test_suite().argv[1];
|
||||
|
||||
// do this now, avoids the need for installing
|
||||
cif::addFileResource("mmcif_pdbx_v50.dic", gTestDir / ".." / "rsrc" / "mmcif_pdbx_v50.dic");
|
||||
|
||||
// initialize CCD location
|
||||
cif::addFileResource("components.cif", gTestDir / ".." / "data" / "ccd-subset.cif");
|
||||
|
||||
mmcif::CompoundFactory::instance().pushDictionary(gTestDir / "HEM.cif");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sugar_name_1)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
mmcif::File file(example.string());
|
||||
mmcif::Structure s(file);
|
||||
|
||||
auto &db = s.datablock();
|
||||
auto &entity = db["entity"];
|
||||
|
||||
auto &branches = s.branches();
|
||||
|
||||
BOOST_CHECK_EQUAL(branches.size(), 4);
|
||||
|
||||
for (auto &branch : branches)
|
||||
{
|
||||
auto entityID = branch.front().entityID();
|
||||
|
||||
auto name = entity.find1<std::string>("id"_key == entityID, "pdbx_description");
|
||||
BOOST_CHECK_EQUAL(branch.name(), name);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(create_sugar_1)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
mmcif::File file(example.string());
|
||||
mmcif::Structure s(file);
|
||||
|
||||
// collect atoms from asym L first
|
||||
auto &NAG = s.getResidue("L");
|
||||
auto nagAtoms = NAG.atoms();
|
||||
|
||||
std::vector<std::vector<cif::Item>> ai;
|
||||
|
||||
auto &db = s.datablock();
|
||||
auto &as = db["atom_site"];
|
||||
|
||||
for (auto r : as.find("label_asym_id"_key == "L"))
|
||||
ai.emplace_back(r.begin(), r.end());
|
||||
|
||||
s.removeResidue(NAG);
|
||||
|
||||
auto &branch = s.createBranch(ai);
|
||||
|
||||
BOOST_CHECK_EQUAL(branch.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose");
|
||||
BOOST_CHECK_EQUAL(branch.size(), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(branch[0].atoms().size(), nagAtoms.size());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(create_sugar_2)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
mmcif::File file(example.string());
|
||||
mmcif::Structure s(file);
|
||||
|
||||
// Get branch for H
|
||||
auto &bH = s.getBranchByAsymID("H");
|
||||
|
||||
BOOST_CHECK_EQUAL(bH.size(), 2);
|
||||
|
||||
std::vector<std::vector<cif::Item>> ai[2];
|
||||
|
||||
auto &db = s.datablock();
|
||||
auto &as = db["atom_site"];
|
||||
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1))
|
||||
ai[i].emplace_back(r.begin(), r.end());
|
||||
}
|
||||
|
||||
s.removeBranch(bH);
|
||||
|
||||
auto &bN = s.createBranch(ai[0]);
|
||||
s.extendBranch(bN.asymID(), ai[1], 1, "O4");
|
||||
|
||||
BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose-(1-4)-2-acetamido-2-deoxy-beta-D-glucopyranose");
|
||||
BOOST_CHECK_EQUAL(bN.size(), 2);
|
||||
|
||||
file.save(gTestDir / "test-create_sugar_2.cif");
|
||||
}
|
||||
1922
test/unit-test.cpp
Normal file
1922
test/unit-test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
13
tools/m4esc.sh
Executable file
13
tools/m4esc.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
file="$1"
|
||||
|
||||
echo -n "[["
|
||||
while IFS= read -r line; do
|
||||
echo $line | sed -e 's/\[/@<:@/g' -e 's/\]/@:>@/g' -e 's/#/@%:@/g' -e 's/\$/@S|@/g'
|
||||
echo
|
||||
done < "$file"
|
||||
|
||||
echo -n "]]"
|
||||
464
tools/symop-map-generator.cpp
Normal file
464
tools/symop-map-generator.cpp
Normal file
@@ -0,0 +1,464 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
std::regex kNameRx(R"(^(\d+) +(\d+) +(\d+) +(\S+) +(\S+) +(\S+) +'([^']+)'( +'([^']+)')?(?: +!.+)?$)");
|
||||
|
||||
class SymopParser
|
||||
{
|
||||
public:
|
||||
SymopParser() {}
|
||||
|
||||
std::array<int,15> parse(const std::string& s)
|
||||
{
|
||||
m_p = s.begin();
|
||||
m_e = s.end();
|
||||
m_lookahead = next_token();
|
||||
|
||||
parsepart(0);
|
||||
match((Token)',');
|
||||
parsepart(1);
|
||||
match((Token)',');
|
||||
parsepart(2);
|
||||
|
||||
if (m_lookahead != 0 or m_p != m_e)
|
||||
throw std::runtime_error("symmetry expression contains more data than expected");
|
||||
|
||||
return {
|
||||
m_rot[0][0], m_rot[0][1], m_rot[0][2],
|
||||
m_rot[1][0], m_rot[1][1], m_rot[1][2],
|
||||
m_rot[2][0], m_rot[2][1], m_rot[2][2],
|
||||
m_trn[0][0], m_trn[0][1],
|
||||
m_trn[1][0], m_trn[1][1],
|
||||
m_trn[2][0], m_trn[2][1]
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum Token : int { Eof = 0, Number = 256, XYZ };
|
||||
|
||||
std::string to_string(Token t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case Eof: return "end of expression";
|
||||
case Number: return "number";
|
||||
case XYZ: return "'x', 'y' or 'z'";
|
||||
default:
|
||||
if (isprint(t))
|
||||
return std::string({'\'', static_cast<char>(t), '\''});
|
||||
return "invalid character " + std::to_string(static_cast<int>(t));
|
||||
}
|
||||
}
|
||||
|
||||
Token next_token()
|
||||
{
|
||||
Token result = Eof;
|
||||
while (m_p != m_e)
|
||||
{
|
||||
char ch = *m_p++;
|
||||
if (ch == ' ')
|
||||
continue;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case 'x':
|
||||
case 'X':
|
||||
result = XYZ;
|
||||
m_nr = 0;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
case 'Y':
|
||||
result = XYZ;
|
||||
m_nr = 1;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
case 'Z':
|
||||
result = XYZ;
|
||||
m_nr = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit(ch))
|
||||
{
|
||||
m_nr = ch - '0';
|
||||
result = Number;
|
||||
}
|
||||
else
|
||||
result = (Token)ch;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void match(Token token)
|
||||
{
|
||||
if (m_lookahead != token)
|
||||
throw std::runtime_error("Unexpected character " + to_string(m_lookahead) + " expected " + to_string(token));
|
||||
|
||||
m_lookahead = next_token();
|
||||
}
|
||||
|
||||
void parsepart(int row)
|
||||
{
|
||||
do
|
||||
{
|
||||
int sign = m_lookahead == '-' ? -1 : 1;
|
||||
if (m_lookahead == '-' or m_lookahead == '+')
|
||||
match(m_lookahead);
|
||||
|
||||
if (m_lookahead == Number)
|
||||
{
|
||||
m_trn[row][0] = sign * m_nr;
|
||||
match(Number);
|
||||
|
||||
match((Token)'/');
|
||||
|
||||
m_trn[row][1] = m_nr;
|
||||
match(Number);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rot[row][m_nr] = sign;
|
||||
match(XYZ);
|
||||
}
|
||||
}
|
||||
while (m_lookahead == '+' or m_lookahead == '-');
|
||||
}
|
||||
|
||||
Token m_lookahead;
|
||||
int m_nr;
|
||||
|
||||
std::string m_s;
|
||||
std::string::const_iterator m_p, m_e;
|
||||
|
||||
int m_rot[3][3] = {};
|
||||
int m_trn[3][2] = {};
|
||||
};
|
||||
|
||||
std::array<int,15> move_symop(std::array<int,15> symop, const std::array<int,15>& cenop)
|
||||
{
|
||||
for (int i = 9; i < 15; i += 2)
|
||||
{
|
||||
if (cenop[i] == 0)
|
||||
continue;
|
||||
|
||||
assert(cenop[i + 1] != 0);
|
||||
|
||||
if (symop[i] == 0)
|
||||
{
|
||||
assert(symop[i + 1] == 0);
|
||||
symop[i] = cenop[i];
|
||||
symop[i + 1] = cenop[i + 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (symop[i + 1] == cenop[i + 1])
|
||||
symop[i] += cenop[i];
|
||||
else
|
||||
{
|
||||
int d = symop[i + 1] * cenop[i + 1];
|
||||
int n = symop[i] * cenop[i + 1] + symop[i + 1] * cenop[i];
|
||||
|
||||
symop[i] = n;
|
||||
symop[i + 1] = d;
|
||||
}
|
||||
|
||||
for (int j = 5; j > 1; --j)
|
||||
if (symop[i] % j == 0 and symop[i + 1] % j == 0)
|
||||
{
|
||||
symop[i] /= j;
|
||||
symop[i + 1] /= j;
|
||||
}
|
||||
|
||||
symop[i] = (symop[i] + symop[i + 1]) % symop[i + 1];
|
||||
|
||||
if (symop[i] == 0)
|
||||
symop[i + 1] = 0;
|
||||
}
|
||||
|
||||
return symop;
|
||||
}
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
fs::path tmpFile;
|
||||
|
||||
try
|
||||
{
|
||||
po::options_description visible_options("symop-map-generator symlib-file output-file");
|
||||
visible_options.add_options()
|
||||
( "help,h", "Display help message" )
|
||||
( "verbose,v", "Verbose output") ;
|
||||
|
||||
po::options_description hidden_options("hidden options");
|
||||
hidden_options.add_options()
|
||||
( "input,i", po::value<std::string>(), "Input file")
|
||||
( "output,o", po::value<std::string>(), "Output file");
|
||||
|
||||
po::options_description cmdline_options;
|
||||
cmdline_options.add(visible_options).add(hidden_options);
|
||||
|
||||
po::positional_options_description p;
|
||||
p.add("input", 1);
|
||||
p.add("output", 1);
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm);
|
||||
po::notify(vm);
|
||||
|
||||
if (vm.count("input") == 0 or vm.count("output") == 0 or vm.count("help"))
|
||||
{
|
||||
std::cerr << visible_options << std::endl;
|
||||
exit(vm.count("help") == 0);
|
||||
}
|
||||
|
||||
fs::path input(vm["input"].as<std::string>());
|
||||
fs::path output(vm["output"].as<std::string>());
|
||||
|
||||
tmpFile = output.parent_path() / (output.filename().string() + ".tmp");
|
||||
|
||||
std::ofstream out(tmpFile);
|
||||
if (not out.is_open())
|
||||
throw std::runtime_error("Failed to open output file");
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// store symop data here
|
||||
std::vector<std::tuple<int,int,std::array<int,15>>> data;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct SymInfoBlock
|
||||
{
|
||||
int nr;
|
||||
std::string xHM;
|
||||
std::string Hall;
|
||||
std::string old[2];
|
||||
};
|
||||
|
||||
std::map<int,SymInfoBlock> symInfo;
|
||||
int symopnr, mysymnr = 10000;
|
||||
|
||||
std::ifstream file(input);
|
||||
if (not file.is_open())
|
||||
throw std::runtime_error("Could not open syminfo.lib file");
|
||||
|
||||
enum class State { skip, spacegroup } state = State::skip;
|
||||
|
||||
std::string line;
|
||||
|
||||
const std::regex rx(R"(^symbol +(Hall|xHM|old) +'(.+?)'(?: +'(.+?)')?$)"),
|
||||
rx2(R"(symbol ccp4 (\d+))");;
|
||||
|
||||
SymInfoBlock cur = {};
|
||||
|
||||
std::vector<std::array<int,15>> symops, cenops;
|
||||
|
||||
while (getline(file, line))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case State::skip:
|
||||
if (line == "begin_spacegroup")
|
||||
{
|
||||
state = State::spacegroup;
|
||||
symopnr = 1;
|
||||
++mysymnr;
|
||||
cur = { mysymnr };
|
||||
}
|
||||
break;
|
||||
|
||||
case State::spacegroup:
|
||||
{
|
||||
std::smatch m;
|
||||
if (std::regex_match(line, m, rx))
|
||||
{
|
||||
if (m[1] == "old")
|
||||
{
|
||||
cur.old[0] = m[2];
|
||||
if (m[3].matched)
|
||||
cur.old[1] = m[3];
|
||||
}
|
||||
else if (m[1] == "xHM")
|
||||
cur.xHM = m[2];
|
||||
else if (m[1] == "Hall")
|
||||
cur.Hall = m[2];
|
||||
}
|
||||
else if (regex_match(line, m, rx2))
|
||||
{
|
||||
int nr = stoi(m[1]);
|
||||
if (nr != 0)
|
||||
cur.nr = nr;
|
||||
}
|
||||
else if (line.compare(0, 6, "symop ") == 0)
|
||||
{
|
||||
SymopParser p;
|
||||
symops.emplace_back(p.parse(line.substr(6)));
|
||||
}
|
||||
else if (line.compare(0, 6, "cenop ") == 0)
|
||||
{
|
||||
SymopParser p;
|
||||
cenops.emplace_back(p.parse(line.substr(6)));
|
||||
}
|
||||
else if (line == "end_spacegroup")
|
||||
{
|
||||
for (auto& cenop: cenops)
|
||||
{
|
||||
for (auto symop: symops)
|
||||
{
|
||||
symop = move_symop(symop, cenop);
|
||||
|
||||
data.emplace_back(cur.nr, symopnr, symop);
|
||||
++symopnr;
|
||||
}
|
||||
}
|
||||
|
||||
symInfo.emplace(cur.nr, cur);
|
||||
state = State::skip;
|
||||
|
||||
symops.clear();
|
||||
cenops.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
sort(data.begin(), data.end());
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
out << R"(// This file was generated from $CLIBD/symop.lib
|
||||
// and $CLIBD/syminfo.lib using symop-map-generator,
|
||||
// part of the PDB-REDO suite of programs.
|
||||
|
||||
#include "cif++/Symmetry.hpp"
|
||||
|
||||
namespace mmcif
|
||||
{
|
||||
|
||||
const Spacegroup kSpaceGroups[] =
|
||||
{
|
||||
)";
|
||||
|
||||
std::vector<std::tuple<std::string,int,std::string,std::string>> spacegroups;
|
||||
|
||||
for (auto& [nr, info]: symInfo)
|
||||
{
|
||||
spacegroups.emplace_back(info.old[0], nr, info.xHM, info.Hall);
|
||||
if (info.old[1].empty() == false)
|
||||
spacegroups.emplace_back(info.old[1], nr, info.xHM, info.Hall);
|
||||
}
|
||||
|
||||
sort(spacegroups.begin(), spacegroups.end());
|
||||
|
||||
for (auto [old, nr, xHM, Hall]: spacegroups)
|
||||
{
|
||||
old = '"' + old + '"' + std::string(20 - old.length(), ' ');
|
||||
xHM = '"' + xHM + '"' + std::string(30 - xHM.length(), ' ');
|
||||
|
||||
for (std::string::size_type p = Hall.length(); p > 0; --p)
|
||||
{
|
||||
if (Hall[p - 1] == '"')
|
||||
Hall.insert(p - 1, "\\", 1);
|
||||
}
|
||||
|
||||
Hall = '"' + Hall + '"' + std::string(40 - Hall.length(), ' ');
|
||||
|
||||
out << "\t{ " << old << ", " << xHM << ", " << Hall << ", " << nr << " }," << std::endl;
|
||||
}
|
||||
|
||||
out << R"(
|
||||
};
|
||||
|
||||
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(Spacegroup);
|
||||
|
||||
const SymopDataBlock kSymopNrTable[] = {
|
||||
)" << std::endl;
|
||||
|
||||
int spacegroupNr = 0;
|
||||
for (auto& sd: data)
|
||||
{
|
||||
int sp, o;
|
||||
std::tie(sp, o, std::ignore) = sd;
|
||||
|
||||
if (sp > spacegroupNr)
|
||||
out << " // " << symInfo[sp].xHM << std::endl;
|
||||
spacegroupNr = sp;
|
||||
|
||||
out << " { " << std::setw(3) << sp
|
||||
<< ", " << std::setw(3) << o << ", { ";
|
||||
for (auto& i: std::get<2>(sd))
|
||||
out << std::setw(2) << i << ',';
|
||||
out << " } }," << std::endl;
|
||||
}
|
||||
|
||||
out << R"(};
|
||||
|
||||
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(SymopDataBlock);
|
||||
|
||||
} // namespace mmcif
|
||||
)" << std::endl;
|
||||
|
||||
out.close();
|
||||
fs::rename(tmpFile, output);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "Program terminated due to error:" << std::endl
|
||||
<< ex.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
47
tools/update-dictionary-script
Normal file
47
tools/update-dictionary-script
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -ne 0 ]
|
||||
then echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -f /etc/libcifpp.conf ] ; then
|
||||
. /etc/libcifpp.conf
|
||||
fi
|
||||
|
||||
# check to see if we're supposed to run at all
|
||||
if [ "$update" != "true" ] ; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# if cache directory doesn't exist, exit.
|
||||
if ! [ -d /var/cache/libcifpp ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
fetch_dictionary () {
|
||||
dict=$1
|
||||
source=$2
|
||||
|
||||
wget -O${dict}.gz ${source}
|
||||
|
||||
# be careful not to nuke an existing dictionary file
|
||||
# extract to a temporary file first
|
||||
|
||||
gunzip -c ${dict}.gz > ${dict}-tmp
|
||||
|
||||
# then move the extracted file to the final location
|
||||
|
||||
mv ${dict}-tmp ${dict}
|
||||
|
||||
# and clean up afterwards
|
||||
|
||||
rm ${dict}.gz
|
||||
}
|
||||
|
||||
# fetch the dictionaries
|
||||
|
||||
fetch_dictionary "/var/cache/libcifpp/mmcif_pdbx_v50.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz"
|
||||
fetch_dictionary "/var/cache/libcifpp/components.cif" "ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz"
|
||||
53
tools/update-libcifpp-data.in
Executable file
53
tools/update-libcifpp-data.in
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -ne 0 ]
|
||||
then echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -f /etc/libcifpp.conf ] ; then
|
||||
. /etc/libcifpp.conf
|
||||
fi
|
||||
|
||||
# check to see if we're supposed to run at all
|
||||
if [ "$update" != "true" ] ; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# if cache directory doesn't exist, exit.
|
||||
if ! [ -d @CIFPP_CACHE_DIR@ ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
fetch_dictionary () {
|
||||
dict=$1
|
||||
source=$2
|
||||
|
||||
wget -O${dict}.gz ${source}
|
||||
|
||||
# be careful not to nuke an existing dictionary file
|
||||
# extract to a temporary file first
|
||||
|
||||
gunzip -c ${dict}.gz > ${dict}-tmp
|
||||
|
||||
# then move the extracted file to the final location
|
||||
|
||||
mv ${dict}-tmp ${dict}
|
||||
|
||||
# and clean up afterwards
|
||||
|
||||
rm ${dict}.gz
|
||||
}
|
||||
|
||||
# fetch the dictionaries
|
||||
|
||||
fetch_dictionary "@CIFPP_CACHE_DIR@/mmcif_pdbx_v50.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz"
|
||||
fetch_dictionary "@CIFPP_CACHE_DIR@/components.cif" "ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz"
|
||||
|
||||
# notify subscribers
|
||||
|
||||
if [ -d /etc/libcifpp/cache-update.d ] && [ -x /bin/run-parts ]; then
|
||||
run-parts --arg "@CIFPP_CACHE_DIR@" -- /etc/libcifpp/cache-update.d
|
||||
fi
|
||||
Reference in New Issue
Block a user