Skip to content

Commit 7818f96

Browse files
committed
add scripting download for histograms & phases; add TOF self-test; remove subprocess.terminate after .poll() shows done
1 parent 28e3faf commit 7818f96

File tree

3 files changed

+132
-39
lines changed

3 files changed

+132
-39
lines changed

GSASII/GSASIIctrlGUI.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9191,11 +9191,6 @@ def gitFetch(G2frame):
91919191
wx.GetApp().Yield()
91929192
if not ok:
91939193
return
9194-
G2frame.UpdateTask.terminate()
9195-
try:
9196-
G2frame.UpdateTask.wait(1)
9197-
except TimeoutExpired:
9198-
pass
91999194

92009195
if GSASIIpath.GetConfigValue('debug'): print('background update complete')
92019196
# try update one more time just to make sure

GSASII/GSASIIscriptable.py

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -388,31 +388,38 @@ class G2ImportException(Exception):
388388
class G2ScriptException(Exception):
389389
pass
390390

391+
def downloadFile(URL,download_loc=None):
392+
'''Download the URL
393+
'''
394+
395+
import requests
396+
fname = os.path.split(URL)[1]
397+
if download_loc is None:
398+
import tempfile
399+
download_loc = tempfile.gettempdir()
400+
elif os.path.isdir(download_loc) and os.path.exists(download_loc):
401+
pass
402+
elif os.path.exists(os.path.dirname(download_loc)):
403+
download_loc,fname = os.path.split(download_loc)
404+
pass
405+
else:
406+
raise G2ScriptException(f"Import error: Cannot download to {download_loc}")
407+
G2fil.G2Print(f'Preparing to download {URL}')
408+
response = requests.get(URL)
409+
filename = os.path.join(download_loc,fname)
410+
with open(filename,'wb') as fp:
411+
fp.write(response.content)
412+
G2fil.G2Print(f'File {filename} written')
413+
return filename
414+
391415
def import_generic(filename, readerlist, fmthint=None, bank=None,
392416
URL=False, download_loc=None):
393417
"""Attempt to import a filename, using a list of reader objects.
394418
395419
Returns the first reader object which worked."""
396-
# Translated from OnImportGeneric method in GSASII.py
397420
if URL is True:
398-
import requests
399-
fname = os.path.split(filename)[1]
400-
if download_loc is None:
401-
import tempfile
402-
download_loc = tempfile.gettempdir()
403-
elif os.path.isdir(download_loc) and os.path.exists(download_loc):
404-
pass
405-
elif os.path.exists(os.path.dirname(download_loc)):
406-
download_loc,fname = os.path.split(download_loc)
407-
pass
408-
else:
409-
raise G2ScriptException(f"Import error: Cannot download to {download_loc}")
410-
G2fil.G2Print(f'Preparing to download {filename}')
411-
response = requests.get(filename)
412-
filename = os.path.join(download_loc,fname)
413-
with open(filename,'wb') as fp:
414-
fp.write(response.content)
415-
G2fil.G2Print(f'File {filename} written')
421+
filename = downloadFile(filename,download_loc)
422+
# Translated from OnImportGeneric method in GSASII.py
416423
primaryReaders, secondaryReaders = [], []
417424
for reader in readerlist:
418425
if fmthint is not None and fmthint not in reader.formatName: continue
@@ -952,8 +959,8 @@ def save(self, filename=None):
952959
SaveDictToProjFile(self.data, self.names, self.filename)
953960

954961
def add_powder_histogram(self, datafile, iparams=None, phases=[],
955-
fmthint=None,
956-
databank=None, instbank=None, multiple=False):
962+
fmthint=None, databank=None, instbank=None,
963+
multiple=False, URL=False):
957964
"""Loads a powder data histogram or multiple powder histograms
958965
into the project.
959966
@@ -965,7 +972,7 @@ def add_powder_histogram(self, datafile, iparams=None, phases=[],
965972
:param str datafile: A filename with the powder data file to read.
966973
Note that in unix fashion, "~" can be used to indicate the
967974
home directory (e.g. ~/G2data/data.fxye).
968-
:param str iparams: A filenme for an instrument parameters file,
975+
:param str iparams: A filename for an instrument parameters file,
969976
or a pair of instrument parameter dicts from :func:`load_iprms`.
970977
This may be omitted for readers that provide the instrument
971978
parameters in the file. (Only a few importers do this.)
@@ -992,21 +999,33 @@ def add_powder_histogram(self, datafile, iparams=None, phases=[],
992999
:param bool multiple: If False (default) only one dataset is read, but if
9931000
specified as True, all selected banks of data (see databank)
9941001
are read in.
1002+
:param bool URL: if True, the contents of datafile is a URL and
1003+
if not a dict, the contents of iparams is also a URL.
1004+
both files will be downloaded to a temporary location
1005+
and read. The downloaded files will not be saved.
1006+
If URL is specified and the Python requests package is
1007+
not installed, a `ModuleNotFoundError` Exception will occur.
1008+
will occur.
9951009
:returns: A :class:`G2PwdrData` object representing
9961010
the histogram, or if multiple is True, a list of :class:`G2PwdrData`
9971011
objects is returned.
9981012
"""
9991013
LoadG2fil()
1000-
datafile = os.path.abspath(os.path.expanduser(datafile))
1001-
try:
1002-
iparams = os.path.abspath(os.path.expanduser(iparams))
1003-
except:
1004-
pass
1005-
pwdrreaders = import_generic(datafile, Readers['Pwdr'],fmthint=fmthint,bank=databank)
1014+
if not URL:
1015+
datafile = os.path.abspath(os.path.expanduser(datafile))
1016+
pwdrreaders = import_generic(datafile, Readers['Pwdr'],fmthint=fmthint,
1017+
bank=databank, URL=URL)
10061018
if not multiple: pwdrreaders = pwdrreaders[0:1]
10071019
histlist = []
1020+
if URL:
1021+
iparmfile = downloadFile(iparams)
1022+
else:
1023+
try:
1024+
iparmfile = os.path.abspath(os.path.expanduser(iparams))
1025+
except:
1026+
pass
10081027
for r in pwdrreaders:
1009-
histname, new_names, pwdrdata = load_pwd_from_reader(r, iparams,
1028+
histname, new_names, pwdrdata = load_pwd_from_reader(r, iparmfile,
10101029
[h.name for h in self.histograms()],bank=instbank)
10111030
if histname in self.data:
10121031
G2fil.G2Print("Warning - redefining histogram", histname)
@@ -1235,7 +1254,7 @@ def add_simulated_powder_histogram(self, histname, iparams, Tmin, Tmax, Tstep=No
12351254

12361255
def add_phase(self, phasefile=None, phasename=None, histograms=[],
12371256
fmthint=None, mag=False,
1238-
spacegroup='P 1',cell=None):
1257+
spacegroup='P 1',cell=None, URL=False):
12391258
"""Loads a phase into the project, usually from a .cif file
12401259
12411260
:param str phasefile: The CIF file (or other file type, see fmthint)
@@ -1259,6 +1278,12 @@ def add_phase(self, phasefile=None, phasename=None, histograms=[],
12591278
this is only used when phasefile is None.
12601279
:param list cell: a list with six unit cell constants
12611280
(a, b, c, alpha, beta and gamma in Angstrom/degrees).
1281+
:param bool URL: if True, the contents of phasefile is a URL
1282+
and the file will be downloaded to a temporary location
1283+
and read. The downloaded file will not be saved.
1284+
If URL is specified and the Python requests package is
1285+
not installed, a `ModuleNotFoundError` Exception will occur.
1286+
will occur.
12621287
12631288
:returns: A :class:`G2Phase` object representing the
12641289
new phase.
@@ -1302,11 +1327,15 @@ def add_phase(self, phasefile=None, phasename=None, histograms=[],
13021327
self.update_ids()
13031328
return self.phase(phasename)
13041329

1305-
phasefile = os.path.abspath(os.path.expanduser(phasefile))
1306-
if not os.path.exists(phasefile):
1307-
raise G2ImportException(f'File {phasefile} does not exist')
1330+
if not URL:
1331+
phasefile = os.path.abspath(os.path.expanduser(phasefile))
1332+
if not os.path.exists(phasefile):
1333+
raise G2ImportException(f'File {phasefile} does not exist')
1334+
else:
1335+
print(f'reading phase from URL {phasefile}')
13081336
# TODO: handle multiple phases in a file
1309-
phasereaders = import_generic(phasefile, Readers['Phase'], fmthint=fmthint)
1337+
phasereaders = import_generic(phasefile, Readers['Phase'],
1338+
fmthint=fmthint, URL=URL)
13101339
phasereader = phasereaders[0]
13111340

13121341
if phasereader.MPhase and mag:

tests/test_tofref.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# perform a TOF GSAS-II refinement using GSASIIscriptable and tutorial
2+
# data. This tests the TOF diffraction code and that Marquardt damping works
3+
4+
import os
5+
import sys
6+
import tempfile
7+
import numpy.testing as npt
8+
home = os.path.dirname(__file__)
9+
work = tempfile.gettempdir()
10+
11+
import importlib.util
12+
G2loc = None
13+
try:
14+
G2loc = importlib.util.find_spec('GSASII.GSASIIscriptable')
15+
except ModuleNotFoundError:
16+
print('ModuleNotFound for GSASII.GSASIIscriptable')
17+
18+
if G2loc is None: # fixup path if GSASII not installed into Python
19+
print('GSAS-II not installed in Python; Hacking sys.path')
20+
sys.path.append(os.path.dirname(home))
21+
22+
import GSASII
23+
import GSASII.GSASIIscriptable as G2sc
24+
25+
def test_refine():
26+
def testR(msg,w1):
27+
print(f"*** {msg}: Rwp(h1)={h1.residuals['wR']:.5f}")
28+
npt.assert_allclose([h1.residuals['wR']], [w1], rtol=0.0001)
29+
30+
print('test_refine(): test a small TOF refinement')
31+
dataloc = lambda fil: os.path.join(home,'testinp',fil)
32+
workloc = lambda fil: os.path.join(work,fil)
33+
gpx = G2sc.G2Project(newgpx=workloc('test_scripting.gpx'))
34+
# setup step 1: add two phases from a original GSAS .EXP file on the web
35+
URL = "https://advancedphotonsource.github.io/GSAS-II-tutorials/TOF-CW%20Joint%20Refinement/data/NAC.cif"
36+
phase0 = gpx.add_phase(URL, phasename="NAC", URL=True)
37+
URL = "https://advancedphotonsource.github.io/GSAS-II-tutorials/TOF-CW%20Joint%20Refinement/data/CaF2.cif"
38+
phase1 = gpx.add_phase(URL, phasename="CaF2", URL=True)
39+
URL = "https://advancedphotonsource.github.io/GSAS-II-tutorials/TOF-CW%20Joint%20Refinement/data/PG3_22048.gsa"
40+
URLprm = "https://advancedphotonsource.github.io/GSAS-II-tutorials/TOF-CW%20Joint%20Refinement/data/POWGEN_2665.instprm"
41+
# setup step 2: a TOF histogram to the project
42+
h1 = gpx.add_powder_histogram(URL, URLprm, fmthint='GSAS powder',
43+
URL=True, phases='all')
44+
h1.set_refinements({'Limits': [11000.,100000]})
45+
gpx.set_Controls('cycles', 2)
46+
h1.set_refinements({"Background": { "no. coeffs": 6, "refine": True }})
47+
gpx.refine()
48+
testR('After first refinement',27.34119)
49+
50+
phase0.set_HAP_refinements({'Scale':True},[h1])
51+
gpx.refine()
52+
testR('2nd refinement w/Phase fraction',23.272757)
53+
54+
phase0.set_refinements({'Cell':True})
55+
phase1.set_refinements({'Cell':True})
56+
gpx.refine()
57+
testR('3rd refinement w/cell',20.966857)
58+
59+
phase0.set_HAP_refinements({'Mustrain':{'refine':True}},[h1])
60+
gpx.refine()
61+
testR('4th refinement w/Mstrain',17.202073)
62+
print('OK')
63+
64+
if __name__ == '__main__':
65+
import time
66+
start = time.time()
67+
test_refine()
68+
print('elapsed=',time.time()-start)
69+

0 commit comments

Comments
 (0)