Skip to content

Commit 848b25e

Browse files
committed
Add devutils script
1 parent 31f61f5 commit 848b25e

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed

devutils/sgtbx_extra_groups.py

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#!/usr/bin/env python
2+
3+
"""Quick and extremely dirty script for generating code for SpaceGroup that
4+
are defined in cctbx, but not in mmLib. It was used to generate module
5+
sgtbxspacegroups.
6+
7+
This is a utility script that should not be included with code distribution.
8+
9+
Not to be included with code distributions.
10+
"""
11+
12+
13+
import math
14+
import re
15+
16+
import numpy
17+
from cctbx import sgtbx
18+
19+
from diffpy.structure.spacegroups import IsSpaceGroupIdentifier, SpaceGroup, SymOp, mmLibSpaceGroupList
20+
21+
22+
def tupleToSGArray(tpl):
23+
if not _rtarrays:
24+
import diffpy.structure.SpaceGroups as sgmod
25+
26+
for n in dir(sgmod):
27+
if not n.startswith("Rot_") and not n.startswith("Tr_"):
28+
continue
29+
a = getattr(sgmod, n)
30+
t = tuple(a.flatten())
31+
_rtarrays[t] = a
32+
if len(tpl) == 3:
33+
tpl = tuple([(x - math.floor(x)) for x in tpl])
34+
if tpl not in _rtarrays:
35+
_rtarrays[tpl] = numpy.array(tpl, dtype=float)
36+
return _rtarrays[tpl]
37+
38+
39+
_rtarrays = {}
40+
41+
42+
def mmSpaceGroupFromSymbol(symbol):
43+
"""Construct SpaceGroup instance from a string symbol using sgtbx data."""
44+
sginfo = sgtbx.space_group_info(symbol)
45+
symop_list = []
46+
symop_list = getSymOpList(sginfo.group())
47+
sgtype = sginfo.type()
48+
uhm = sgtype.lookup_symbol()
49+
sgsmbls = sgtbx.space_group_symbols(uhm)
50+
kw = {}
51+
kw["number"] = sgtype.number()
52+
kw["num_sym_equiv"] = len(symop_list)
53+
kw["num_primitive_sym_equiv"] = countUniqueRotations(symop_list)
54+
kw["short_name"] = sgsmbls.hermann_mauguin().replace(" ", "")
55+
pgt = sgsmbls.point_group_type()
56+
pgn = "PG" + re.sub(r"-(\d)", "\\1bar", pgt)
57+
kw["point_group_name"] = pgn
58+
kw["crystal_system"] = sgsmbls.crystal_system().upper()
59+
kw["pdb_name"] = sgsmbls.hermann_mauguin()
60+
kw["symop_list"] = symop_list
61+
mmsg = SpaceGroup(**kw)
62+
return mmsg
63+
64+
65+
def adjustMMSpaceGroupNumber(mmsg):
66+
sg0 = [x for x in mmLibSpaceGroupList if x.number == mmsg.number]
67+
if sg0 and cmpSpaceGroups(sg0[0], mmsg):
68+
return
69+
while mmsg.number in sgnumbers:
70+
mmsg.number += 1000
71+
sgnumbers.append(mmsg.number)
72+
73+
74+
def getSymOpList(grp):
75+
symop_list = []
76+
for op in grp:
77+
r_sgtbx = op.r().as_double()
78+
t_sgtbx = op.t().as_double()
79+
R = tupleToSGArray(r_sgtbx)
80+
t = tupleToSGArray(t_sgtbx)
81+
symop_list.append(SymOp(R, t))
82+
return symop_list
83+
84+
85+
def countUniqueRotations(symop_list):
86+
unique_rotations = set()
87+
for op in symop_list:
88+
tpl = tuple(op.R.flatten())
89+
unique_rotations.add(tpl)
90+
return len(unique_rotations)
91+
92+
93+
def cmpSpaceGroups(sg0, sg1):
94+
if sg0 is sg1:
95+
return True
96+
s0 = hashMMSpaceGroup(sg0)
97+
s1 = hashMMSpaceGroup(sg1)
98+
return s0 == s1
99+
100+
101+
def findEquivalentMMSpaceGroup(grp):
102+
if not _equivmmsg:
103+
for sgn in mmLibSpaceGroupList:
104+
ssgn = hashMMSpaceGroup(sgn)
105+
_equivmmsg.setdefault(ssgn, sgn)
106+
ssg = hashSgtbxGroup(grp)
107+
return _equivmmsg.get(ssg)
108+
109+
110+
_equivmmsg = {}
111+
112+
113+
def findEquivalentSgtbxSpaceGroup(sgmm):
114+
if not _equivsgtbx:
115+
for smbls in sgtbx.space_group_symbol_iterator():
116+
uhm = smbls.universal_hermann_mauguin()
117+
grp = sgtbx.space_group_info(uhm).group()
118+
hgrp = hashSgtbxGroup(grp)
119+
_equivsgtbx.setdefault(hgrp, grp)
120+
hgmm = hashMMSpaceGroup(sgmm)
121+
return _equivsgtbx.get(hgmm)
122+
123+
124+
_equivsgtbx = {}
125+
126+
127+
def hashMMSpaceGroup(sg):
128+
lines = [str(sg.number % 1000)] + sorted(map(str, sg.iter_symops()))
129+
s = "\n".join(lines)
130+
return s
131+
132+
133+
def hashSgtbxGroup(grp):
134+
n = grp.type().number()
135+
lines = [str(n)] + sorted(map(str, getSymOpList(grp)))
136+
s = "\n".join(lines)
137+
return s
138+
139+
140+
sgnumbers = [sg.number for sg in mmLibSpaceGroupList]
141+
142+
_SGsrc = """\
143+
sg%(number)i = SpaceGroup(
144+
number = %(number)i,
145+
num_sym_equiv = %(num_sym_equiv)i,
146+
num_primitive_sym_equiv = %(num_sym_equiv)i,
147+
short_name = %(short_name)r,
148+
point_group_name = %(point_group_name)r,
149+
crystal_system = %(crystal_system)r,
150+
pdb_name = %(pdb_name)r,
151+
symop_list = [
152+
@SYMOPS@
153+
]
154+
)
155+
"""
156+
157+
158+
def SGCode(mmsg):
159+
src0 = _SGsrc % mmsg.__dict__
160+
src1 = src0.replace("@SYMOPS@", SymOpsCode(mmsg))
161+
return src1
162+
163+
164+
def SymOpsCode(mmsg):
165+
lst = ["%8s%s," % ("", SymOpCode(op)) for op in mmsg.iter_symops()]
166+
src = "\n".join(lst).strip()
167+
return src
168+
169+
170+
def SymOpCode(op):
171+
if not _rtnames:
172+
import diffpy.structure.SpaceGroups as sgmod
173+
174+
for n in dir(sgmod):
175+
if not n.startswith("Rot_") and not n.startswith("Tr_"):
176+
continue
177+
a = getattr(sgmod, n)
178+
at = tuple(a.flatten())
179+
_rtnames[at] = "sgmod." + n
180+
nR = _rtnames[tuple(op.R.flatten())]
181+
nt = _rtnames[tuple(op.t)]
182+
src = "SymOp(%s, %s)" % (nR, nt)
183+
return src
184+
185+
186+
_rtnames = {}
187+
188+
189+
def main():
190+
duplicates = set()
191+
for smbls in sgtbx.space_group_symbol_iterator():
192+
uhm = smbls.universal_hermann_mauguin()
193+
grp = sgtbx.space_group_info(uhm).group()
194+
if findEquivalentMMSpaceGroup(grp):
195+
continue
196+
shn = smbls.hermann_mauguin().replace(" ", "")
197+
if IsSpaceGroupIdentifier(shn):
198+
continue
199+
sg = mmSpaceGroupFromSymbol(uhm)
200+
hsg = hashMMSpaceGroup(sg)
201+
if hsg in duplicates:
202+
continue
203+
adjustMMSpaceGroupNumber(sg)
204+
duplicates.add(hsg)
205+
print(SGCode(sg))
206+
return
207+
208+
209+
if __name__ == "__main__":
210+
main()

0 commit comments

Comments
 (0)