1 | # -*- coding: utf-8 -*- |
---|
2 | """ |
---|
3 | *kSUBGROUPSMAG: Interface to Bilbao k-SUBGROUPSMAG web page* |
---|
4 | ------------------------------- |
---|
5 | |
---|
6 | Extraction of magnetic space groups for a given space group and a propagation vector |
---|
7 | from the k-SUBGROUPSMAG web page on the Bilbao Crystallographic server |
---|
8 | |
---|
9 | """ |
---|
10 | ########### SVN repository information ################### |
---|
11 | # $Date: 2020-03-12 20:22:30 +0000 (Thu, 12 Mar 2020) $ |
---|
12 | # $Author: toby $ |
---|
13 | # $Revision: 4365 $ |
---|
14 | # $URL: trunk/kSUBGROUPSMAG.py $ |
---|
15 | # $Id: kSUBGROUPSMAG.py 4365 2020-03-12 20:22:30Z toby $ |
---|
16 | ########### SVN repository information ################### |
---|
17 | from __future__ import division, print_function |
---|
18 | import requests |
---|
19 | try: |
---|
20 | import HTMLParser as HTML |
---|
21 | except ImportError: |
---|
22 | import html.parser as HTML # Python 3 |
---|
23 | import GSASIIspc as G2spc |
---|
24 | import GSASIIpath |
---|
25 | GSASIIpath.SetBinaryPath() |
---|
26 | submagSite = 'http://www.cryst.ehu.es/cgi-bin/cryst/programs/subgrmag1_k.pl' |
---|
27 | |
---|
28 | class TableParser(HTML.HTMLParser): |
---|
29 | def __init__(self): |
---|
30 | HTML.HTMLParser.__init__(self) |
---|
31 | self.spgp = '' |
---|
32 | self.in_sp = False |
---|
33 | self.in_pre = False |
---|
34 | self.in_sub = False |
---|
35 | self.MV = '' |
---|
36 | self.BNS = '' |
---|
37 | self.beg = False |
---|
38 | self.SPGPs = [] |
---|
39 | self.MVs = [] |
---|
40 | self.BNSs = [] |
---|
41 | |
---|
42 | def handle_starttag(self, tag, attrs): |
---|
43 | # print('tag:',tag,self.beg,self.in_sp) |
---|
44 | if tag == 'i' and self.beg: |
---|
45 | if not self.in_sp: |
---|
46 | self.in_sp = True |
---|
47 | self.spgp = '' |
---|
48 | self.BNS = '' |
---|
49 | elif tag == 'pre': |
---|
50 | self.in_pre = True |
---|
51 | self.MV = '' |
---|
52 | elif tag == 'sub': |
---|
53 | self.in_sub = True |
---|
54 | |
---|
55 | def handle_data(self, data): |
---|
56 | # print('*',data) |
---|
57 | if self.in_sp: |
---|
58 | if 'No.' in data: |
---|
59 | self.spgp += data.split('(')[0] #pick up trailing number! |
---|
60 | self.in_sp = False |
---|
61 | self.SPGPs.append(self.spgp) |
---|
62 | self.BNSs.append(self.BNS) |
---|
63 | # print('space group:',self.spgp,' BNS: ',self.BNS) |
---|
64 | else: |
---|
65 | if self.in_sub and len(self.spgp) == 1: |
---|
66 | self.spgp += '_' |
---|
67 | self.spgp += data |
---|
68 | if len(self.spgp) == 3 and '_' in self.spgp: |
---|
69 | self.spgp += ' ' |
---|
70 | self.BNS = data |
---|
71 | if 'P_S' in self.spgp: #fix ambiguous std. symbol for triclinics |
---|
72 | self.spgp.replace('_S','_c') |
---|
73 | self.BNS = 'c' |
---|
74 | # print(self.spgp,self.BNS) |
---|
75 | if self.in_pre: |
---|
76 | self.MV = data |
---|
77 | |
---|
78 | def handle_endtag(self, tag): |
---|
79 | # print (' end tag: %s'%(tag)) |
---|
80 | if tag == 'script': |
---|
81 | self.beg = True |
---|
82 | elif tag == 'pre': |
---|
83 | self.in_pre = False |
---|
84 | MV = self.MV.split() |
---|
85 | MV = ['[[%s,%s,%s],[%s,%s,%s],[%s,%s,%s]]'%(MV[0],MV[4],MV[8],MV[1],MV[5],MV[9],MV[2],MV[6],MV[10]),'[%s.,%s.,%s.]'%(MV[3],MV[7],MV[11])] |
---|
86 | self.MVs.append(MV) |
---|
87 | # print('MV:',self.MV) |
---|
88 | elif tag == 'sub': |
---|
89 | self.in_sub = False |
---|
90 | |
---|
91 | def GetNonStdSubgroupsmag(SGData, kvec,star=False,landau=False,maximal=False): |
---|
92 | '''Run Bilboa's k-Subgroupsmag for a non-standard space group. |
---|
93 | This requires doing a post to the Bilboa site, which returns all |
---|
94 | magnetic subgroups of the entered subgroup as the text of a web page |
---|
95 | with a table containing the BNS magnetic space group symbol, the |
---|
96 | transformation matrix and index for each subgroup. |
---|
97 | |
---|
98 | :params list kvec: propogation vector as a list of three numbers |
---|
99 | :params SGData: space group object (see :ref:`Space Group object<SGData_table>`) |
---|
100 | |
---|
101 | :returns: (error,text) error: if True no error or False; where |
---|
102 | text containts a possible web page text |
---|
103 | ''' |
---|
104 | print(''' |
---|
105 | For use of k-SUBGROUPSMAG, please cite: |
---|
106 | Symmetry-Based Computational Tools for Magnetic Crystallography, |
---|
107 | J.M. Perez-Mato, S.V. Gallego, E.S. Tasci, L. Elcoro, G. de la Flor, and M.I. Aroyo |
---|
108 | Annu. Rev. Mater. Res. 2015. 45,217-48. |
---|
109 | doi: 10.1146/annurev-matsci-070214-021008 |
---|
110 | ''') |
---|
111 | starmag = 'no' |
---|
112 | if star: |
---|
113 | starmag = 'yes' |
---|
114 | land = 'no' |
---|
115 | if landau: |
---|
116 | land = 'yes' |
---|
117 | celtodas = 'no' |
---|
118 | limite = 'spgroup' |
---|
119 | if maximal: |
---|
120 | limite = 'maximal' |
---|
121 | postdict = {'centrosymmetry':'0','crystalsystem':'0','landau':land, |
---|
122 | 'eleccion':'subgrmag1_k','inicio':'nostandard','celtodas':celtodas, |
---|
123 | 'limite':limite,'list':'Submit','listado':'lista','starmagnetica':starmag, |
---|
124 | 'pointgroup':'0','polarity':'0','sub':'1.1', |
---|
125 | 'super':'','tipog':'gmag','wyckoffstrain':''} |
---|
126 | text,table = G2spc.SGPrint(SGData) |
---|
127 | OpList = G2spc.TextOps(text,table,reverse=True) |
---|
128 | # GenList = G2spc.TextGen(SGData,reverse=True) |
---|
129 | for item in OpList: |
---|
130 | item += '\n' |
---|
131 | sym = "" |
---|
132 | for i in OpList: |
---|
133 | if sym: sym += '\n' |
---|
134 | #if sym: sym += ' ' # use this for testing to generate an error in place of previous |
---|
135 | sym += i.lower() |
---|
136 | postdict['generators'] = sym |
---|
137 | for j in [1,2,3]: |
---|
138 | if kvec[3*j-3] == ' ': |
---|
139 | break |
---|
140 | for i,k in zip(('x','y','z'),kvec[3*j-3:3*j]): |
---|
141 | postdict['km%d%s'%(j,i)] = k |
---|
142 | try: |
---|
143 | r = requests.get(submagSite,params=postdict) |
---|
144 | except: #ConnectionError? |
---|
145 | page = '' |
---|
146 | print('connection error - not on internet') |
---|
147 | return None,None |
---|
148 | if r.status_code == 200: |
---|
149 | print('request OK') |
---|
150 | page = r.text |
---|
151 | page = page.replace('<font style= "text-decoration: overline;">','<font>-') |
---|
152 | else: |
---|
153 | page = '' |
---|
154 | print('request failed. Reason=',r.reason) |
---|
155 | return None,None |
---|
156 | r.close() |
---|
157 | |
---|
158 | p = TableParser() |
---|
159 | p.feed(page) |
---|
160 | nItms = len(p.MVs) |
---|
161 | result = list(zip(p.SPGPs,p.BNSs,p.MVs,range(nItms),nItms*[[],],nItms*['[]',])) |
---|
162 | return result,range(nItms) |
---|
163 | |
---|
164 | def GetNonStdSubgroups(SGData, kvec,star=False,landau=False,maximal=False): |
---|
165 | '''Run Bilboa's SUBGROUPS for a non-standard space group. |
---|
166 | This requires doing a post to the Bilboa site, which returns all |
---|
167 | subgroups of the entered space group as the text of a web page |
---|
168 | with a table containing the space group symbol, the |
---|
169 | transformation matrix and index for each subgroup. |
---|
170 | |
---|
171 | :params list kvec: propogation vector as a list of nine string fractions or blank |
---|
172 | :params SGData: space group object (see :ref:`Space Group object<SGData_table>`) |
---|
173 | |
---|
174 | :returns: (error,text) error: if True no error or False; where |
---|
175 | text containts a possible web page text |
---|
176 | ''' |
---|
177 | print(''' |
---|
178 | For use of SUBGROUPS, please cite: |
---|
179 | Symmetry-Based Computational Tools for Magnetic Crystallography, |
---|
180 | J.M. Perez-Mato, S.V. Gallego, E.S. Tasci, L. Elcoro, G. de la Flor, and M.I. Aroyo |
---|
181 | Annu. Rev. Mater. Res. 2015. 45,217-48. |
---|
182 | doi: 10.1146/annurev-matsci-070214-021008 |
---|
183 | ''') |
---|
184 | starmag = 'no' |
---|
185 | if star: |
---|
186 | starmag = 'yes' |
---|
187 | land = 'no' |
---|
188 | if landau: |
---|
189 | land = 'yes' |
---|
190 | celtodas = 'no' |
---|
191 | limite = 'spgroup' |
---|
192 | if maximal: |
---|
193 | limite = 'maximal' |
---|
194 | postdict = {'centrosymmetry':'0','crystalsystem':'0','landau':land, |
---|
195 | 'eleccion':'subgrmag1_k','inicio':'nostandard','celtodas':celtodas, |
---|
196 | 'limite':limite,'list':'Submit','listado':'lista','starmagnetica':starmag, |
---|
197 | 'pointgroup':'0','polarity':'0','sub':'1', |
---|
198 | 'super':'','tipog':'gesp','wyckoffstrain':''} |
---|
199 | text,table = G2spc.SGPrint(SGData) |
---|
200 | OpList = G2spc.TextOps(text,table,reverse=True) |
---|
201 | # GenList = G2spc.TextGen(SGData,reverse=True) |
---|
202 | for item in OpList: |
---|
203 | item += '\n' |
---|
204 | sym = "" |
---|
205 | for i in OpList: |
---|
206 | if sym: sym += '\n' |
---|
207 | #if sym: sym += ' ' # use this for testing to generate an error in place of previous |
---|
208 | sym += i.lower() |
---|
209 | postdict['generators'] = sym |
---|
210 | for j in [1,2,3]: |
---|
211 | if kvec[3*j-3] == ' ': |
---|
212 | break |
---|
213 | for i,k in zip(('x','y','z'),kvec[3*j-3:3*j]): |
---|
214 | postdict['knm%d%s'%(j,i)] = k |
---|
215 | try: |
---|
216 | r = requests.get(submagSite,params=postdict) |
---|
217 | except: #ConnectionError? |
---|
218 | page = '' |
---|
219 | print('connection error - not on internet') |
---|
220 | return None |
---|
221 | if r.status_code == 200: |
---|
222 | print('request OK') |
---|
223 | page = r.text |
---|
224 | page = page.replace('<font style= "text-decoration: overline;">','<font>-') |
---|
225 | else: |
---|
226 | page = '' |
---|
227 | print('request failed. Reason=',r.reason) |
---|
228 | return None |
---|
229 | r.close() |
---|
230 | |
---|
231 | p = TableParser() |
---|
232 | p.feed(page) |
---|
233 | nItms = len(p.MVs) |
---|
234 | result = list(zip(p.SPGPs,p.MVs,range(nItms),range(nItms),nItms*[0,])) |
---|
235 | return result,range(nItms) |
---|
236 | |
---|
237 | def test(): |
---|
238 | SGData = G2spc.SpcGroup('p -3 m 1')[1] |
---|
239 | results,baseList = GetNonStdSubgroupsmag(SGData,('1/3','1/3','1/2',' ',' ',' ',' ',' ',' ',' ')) |
---|
240 | if results: |
---|
241 | print(results) |
---|
242 | for [spgp,mv,bns,gid,altList,supList] in results.text: |
---|
243 | if gid in baseList: |
---|
244 | print('Space group:',spgp, 'BNS:',bns) |
---|
245 | print('MV') |
---|
246 | print(mv) |
---|
247 | results,baseList = GetNonStdSubgroupsmag(SGData,('1/3','1/3','1/2',' ',' ',' ',' ',' ',' ',' ')) |
---|
248 | if results: |
---|
249 | for [spgp,mv,gid,altList,supList] in results.text: |
---|
250 | if gid in baseList: |
---|
251 | print('Space group:',spgp) |
---|
252 | print('MV') |
---|
253 | print(mv) |
---|
254 | |
---|
255 | |
---|
256 | if __name__ == '__main__': |
---|
257 | # run self-tests |
---|
258 | selftestquiet = False |
---|
259 | test() |
---|
260 | print ("OK") |
---|