source: trunk/ISODISTORT.py @ 5484

Last change on this file since 5484 was 5360, checked in by toby, 3 years ago

note use of requests package (now optional); deal w/wx4.2.0 bug; save NIST*LATTICE snapshot

File size: 9.9 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3*ISODISTORT: Interface to BYU ISODISTORT web pages*
4------------------------------------------------------
5
6
7"""
8########### SVN repository information ###################
9# $Date: 2018-07-10 11:41:00 -0500 (Tue, 10 Jul 2018) $
10# $Author: vondreele $
11# $Revision: 3465 $
12# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/kSUBGROUPSMAG.py $
13# $Id: kSUBGROUPSMAG.py 3465 2018-07-10 16:41:00Z vondreele $
14########### SVN repository information ###################
15from __future__ import division, print_function
16import subprocess as subp
17import os
18import os.path
19try:
20    import requests
21except:
22    print('Module requests not installed, access to ISODISTORT not possible')
23import copy
24import GSASIIscriptable as G2sc
25import tempfile
26isouploadsite = 'https://stokes.byu.edu/iso/isodistortuploadfile.php'
27isoformsite = 'https://iso.byu.edu/iso/isodistortform.php'
28
29def HandleError(out):
30    open('out.html','wb').write(out.encode("utf-8"))
31    url = os.path.realpath('out.html')
32    try:
33        os.startfile(url)
34    except AttributeError:
35        try: # should work on MacOS and most linux versions
36            subp.call(['open', url])
37        except:
38            print('Could not open URL')
39           
40def UploadCIF(cifname):
41       #upload cif file to BYU web site
42    ciffile = open(cifname,'rb')
43    up1 = {'toProcess':(cifname,ciffile),}
44    out1 = requests.post(isouploadsite,files=up1).text
45    ciffile.close()
46   
47    #retrieve BYU temp file name for cif file   
48   
49    pos = out1.index('<INPUT')+7
50    pos1 = out1.index('VALUE=',pos)+7
51    filename = out1[pos1:out1.index('"',pos1)]
52   
53    print('ciffile %s uploaded to ISODISTORT to make %s'%(cifname,filename))
54    return filename
55
56def MakePhaseCif(data):
57    data['pId'] = data.get('pId',0) # needs a pId
58    proj = G2sc.G2Project(newgpx='tmp4cif.gpx')
59    ph = G2sc.G2Phase(data,data['General']['Name'],proj)
60    tempcif = 'ISOin.cif'
61    ph.export_CIF(tempcif)
62    return tempcif
63
64def GetISODISTORT(Phase):
65    '''Run Stokes & Campbell ISODISTORT.
66    This requires doing a post to the BYU upload site with a cif file, which returns a BYU local
67    copy. This is then sent to the BYU form site with various options, which returns all
68    subgroups of the entered space group as the text of a web page with a table containing the space
69    group symbol, the transformation matrix and index for each subgroup. Selection of one of these is
70    returned to the BYU form site which returns the text of a cif file to be used to create the new phase
71    which can apply the distortion mode constraints
72
73    :params dict Phase: GSAS-II phase data
74
75    :returns: radio: dict of possible distortion structures
76    :returns: data2: list of str input for next run of isositortform for extracting cif file
77    '''
78
79    print('''
80    For use of ISODISTORT, please cite:
81      H. T. Stokes, D. M. Hatch, and B. J. Campbell, ISODISTORT, ISOTROPY Software Suite, iso.byu.edu.
82      B. J. Campbell, H. T. Stokes, D. E. Tanner, and D. M. Hatch, "ISODISPLACE: An Internet Tool for Exploring Structural Distortions."
83      J. Appl. Cryst. 39, 607-614 (2006).
84    ''')
85                   
86    ISOdata = Phase['ISODISTORT']
87    parentcif = ISOdata['ParentCIF']
88    childcif = None
89    if 'Use this phase' in parentcif:
90        parentcif = MakePhaseCif(Phase)
91    print(' Run ISODISTORT with %s as parent cif'%parentcif)
92    ISOparentcif = UploadCIF(parentcif)
93   
94    #submit cif for processing by ISODISTORT
95   
96    up2 = {'filename':ISOparentcif,'input':'uploadparentcif'}
97    out2 = requests.post(isoformsite,up2).text
98   
99    #recover required info for the distortion search; includes info from cif file (no longer needed)
100    try:
101        pos = out2.index('<p><FORM')
102    except ValueError:
103        HandleError(out2)
104        return [],[]
105    data = {}
106    while True:
107        try:
108            posB = out2[pos:].index('INPUT TYPE')+pos
109            posF = out2[posB:].index('>')+posB
110            items = out2[posB:posF].split('=',3)
111            name = items[2].split()[0].replace('"','')
112            if 'isosystem' in name:
113                break
114            vals = items[3].replace('"','')
115            data[name] = vals
116            pos = posF
117        except ValueError:
118            break
119    #save copy for future use
120    data2 = copy.deepcopy(data)
121           
122    #no limits on space group or lattice
123       
124    if ISOdata['ISOmethod'] == 1:
125        data['isosubgroup'] = 'no choice'
126        data['isolattice'] = 'no choice'
127        data['isoplattice'] = 'no choice'
128       
129    elif ISOdata['ISOmethod'] == 3:
130        print('method  3 TBD')
131        return [],[]
132    elif ISOdata['ISOmethod'] == 4:
133        childcif = ISOdata['ChildCIF']
134        if 'Use this phase' in childcif:
135            childcif = MakePhaseCif(Phase)
136        print(' Run ISODISTORT with %s as child cif'%childcif)
137        ISOchildcif = UploadCIF(childcif)
138        data['input'] = 'uploadsubgroupcif'
139        data['filename'] = ISOchildcif
140        out24 = requests.post(isoformsite,data=data).text
141        posB = out24.index('OPTION VALUE=')
142        posF = out24[posB:].index('>')+posB
143        value = out24[posB+13:posF]
144        data['input'] = 'distort'
145        data['origintype'] = 'method4'
146        data['inputbasis'] = 'list'
147        data['basisselect'] = value[1:-1]
148        data['chooseorigin'] = False
149        data['trynearest'] = True
150        data['dmax'] = '1'
151        out25 = requests.post(isoformsite,data=data).text
152        cifout = GetISOcif(out25,4)
153        if cifout is None:
154            return None,None
155        cifFile = '%s_%s.cif'%(Phase['General']['Name'],'child')
156        fl = open(cifFile,'wb')
157        fl.write(cifout.encode("utf-8"))
158        fl.close()
159        return [],cifFile
160       
161    #do the distortion search - result is radio button list of choices
162   
163    out3 = requests.post(isoformsite,data=data).text
164   
165    #extract the radio button collection
166   
167    radio = {}
168    num = 0
169    try:
170        pos = out3.index('RADIO')
171    except ValueError:
172        HandleError(out3)
173        return [],[]
174       
175    while True:
176        try:
177            posF = out3[pos:].index('<BR>')+pos
178            num += 1
179            items = out3[pos:posF].split('=',2)[2].split('>')[0]
180            radio['orderparam%d'%num] = items.replace('"','').replace('CHECKED','')
181            pos = out3[posF:].index('RADIO')+posF
182        except ValueError:
183            break
184       
185    if parentcif == 'ISOin.cif' or childcif == 'ISOin.cif':
186        os.remove('ISOin.cif')
187   
188    return radio,data2
189
190def GetISOcif(out4,method):
191   
192    try:
193        pos = out4.index('<FORM ACTION')
194    except ValueError:
195        HandleError(out4)
196        return None
197    data3 = {}
198    while True:
199        try:
200            posB = out4[pos:].index('INPUT TYPE')+pos
201            posF = out4[posB:].index('>')+posB
202            items = out4[posB:posF].split('=',3)
203            name = items[2].split()[0].replace('"','')
204            if 'subsetting' in name:
205                data3[name] = ''
206                pos = posF
207                continue
208            elif 'atomsfile' in name:
209                data3[name] = ' '
210                pos = posF
211                continue
212            vals = items[3].replace('"','')
213            data3[name] = vals
214            pos = posF
215            if 'origintype' in name:
216                break
217        except ValueError:
218            break
219    if method == 4:
220        try:
221            pos = out4[posF:].index('Enter mode')+posF
222            pos = out4[pos:].index('<p>')+pos
223        except ValueError:
224            HandleError(out4)
225        while True:
226            try:
227                posB = out4[pos:].index('name')+pos
228                posF = out4[posB:].index('>')+posB
229                items = out4[posB:posF].split('=')
230                name = items[1].split()[0].replace('"','')
231                if name == 'atomicradius':
232                    break
233                vals = items[2].split()[0].replace('"','')
234                data3[name] = vals
235                pos = posF
236            except ValueError:
237                break
238        data3['zeromodes'] = False
239       
240   #request a cif file   
241       
242    data3['origintype'] = 'structurefile'
243    data3['inputvalues'] = 'false'
244    data3['atomicradius'] = '0.4'
245    data3['bondlength'] = '2.50'
246    data3['modeamplitude'] = '1.0'
247    data3['strainamplitude'] = '0.1'
248    # for item in data3:
249    #     print(item,data3[item])
250    k = requests.post(isoformsite,data=data3)
251    out5 = k.text   #this is output cif!
252    #print(out5)
253    return out5
254   
255
256def GetISODISTORTcif(Phase):
257    '''Run Stokes & Campbell ISODISTORT.
258    Selection of one of the order parameter disrections is returned to the BYU
259    form site which returns the text of a cif file to be used to create the new phase
260    which can apply the distortion mode constraints
261     
262    :params dict Phase: GSAS-II phase data; contains result of GetISODISTORT above & selection
263   
264    :returns: CIFfile str: name of cif file created by this in local directory
265    '''
266   
267    ISOdata = Phase['ISODISTORT']
268    data2 = ISOdata['rundata']
269    #choose one & resubmit
270    data2['origintype'] = 'method1'
271    data2['orderparam'] = ISOdata['selection'][1]
272    data2['input'] = 'distort'
273    # for item in data2:
274    #     print(item,data2[item])
275    out4 = requests.post(isoformsite,data=data2).text
276    #print(out4)
277    #open('pyout4.html','wb').write(out4.encode("utf-8"))
278     
279    #retrieve data needed for next(last) step
280   
281    out5 = GetISOcif(out4,1)
282    names = ISOdata['selection'][1].split()
283    cifFile = '%s_%s%s%s.cif'%(Phase['General']['Name'],names[1],names[2].replace('*','_'),names[3])
284    fl = open(cifFile,'wb')
285    fl.write(out5.encode("utf-8"))
286    fl.close()
287
288    return cifFile
Note: See TracBrowser for help on using the repository browser.