source: trunk/ISODISTORT.py @ 5352

Last change on this file since 5352 was 5130, checked in by vondreele, 3 years ago

revise ISODISTORT operation - now uses Method 4 by default.
Revise ISODISTORT cif import to retain mode displacements
ApplyModeDisp? now uses mode normalization
move OnRunISODISTORT to UpdateISODISTORT - where it is now called from
revise UpdateISODISTORT to allow Method 4 along with 1; 2 & 3 are not currently supported in GSAS-II
mode display sliders now initialized from ISODISTORT cif data; reset goes back to cif values (not zeros)
fix errors in instrument parm plots; also provide alert in plot title if negatives encountered
recover _iso_displacivemode_value from ISODISTORT cif file
revise ISODISTORT.py to work with method 4 as well as method 1.

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