# -*- coding: utf-8 -*-
'''
Misc routines for GUI-based input and output, including image reading follow.
This module contains quite a bit of older code that could use some attention,
or possibly movement into other modules. It was previously called GSASIIIO.py
which is why most modules reference it as G2IO.
'''
from __future__ import division, print_function
# # Allow this to be imported without wx present.
# try:
# import wx
# except ImportError:
# print('wx failed')
# # was needed by sphinx, but probably not anymore
# class Placeholder(object):
# def __init__(self):
# self.Dialog = object
# wx = Placeholder()
import math
import os
import re
import copy
#import platform
import pickle
import sys
import random as ran
import numpy as np
import numpy.ma as ma
import wx
from . import GSASIIpath
from . import GSASIIdataGUI as G2gd
from . import GSASIIobj as G2obj
#import GSASIIpwdGUI as G2pdG
from . import GSASIIimgGUI as G2imG
from . import GSASIIElem as G2el
from . import GSASIIfiles as G2fil
from . import GSASIIctrlGUI as G2G
from . import GSASIImath as G2mth
from . import GSASIIElem as G2elem
from . import GSASIIspc as G2spc
from . import GSASIIlattice as G2lat
from . import GSASIIpwd as G2pwd
DEBUG = False #=True for various prints
TRANSP = False #=true to transpose images for testing
if GSASIIpath.GetConfigValue('Transpose'): TRANSP = True
npsind = lambda x: np.sin(x*np.pi/180.)
[docs]
def FileDlgFixExt(dlg,file):
'this is needed to fix a problem in linux wx.FileDialog'
ext = dlg.GetWildcard().split('|')[2*dlg.GetFilterIndex()+1].strip('*')
if ext not in file:
file += ext
return file
[docs]
def GetPowderPeaks(fileName):
'Read powder peaks from a file'
sind = lambda x: math.sin(x*math.pi/180.)
asind = lambda x: 180.*math.asin(x)/math.pi
wave = 1.54052
File = open(fileName,'r')
Comments = []
peaks = []
S = File.readline()
while S:
if S[:1] == '#':
Comments.append(S[:-1])
else:
item = S.split()
if len(item) == 1:
peaks.append([float(item[0]),1.0])
elif len(item) > 1:
peaks.append([float(item[0]),float(item[1])])
S = File.readline()
File.close()
if Comments:
print ('Comments on file:')
for Comment in Comments:
print (Comment)
if 'wavelength' in Comment:
wave = float(Comment.split('=')[1])
Peaks = []
if peaks[0][0] > peaks[-1][0]: # d-spacings - assume CuKa
for peak in peaks:
dsp = peak[0]
sth = wave/(2.0*dsp)
if sth < 1.0:
tth = 2.0*asind(sth)
else:
break
Peaks.append([tth,peak[1],True,False,0,0,0,dsp,0.0])
else: #2-thetas - assume Cuka (for now)
for peak in peaks:
tth = peak[0]
dsp = wave/(2.0*sind(tth/2.0))
Peaks.append([tth,peak[1],True,False,0,0,0,dsp,0.0])
limits = [1000.,0.]
for peak in Peaks:
limits[0] = min(limits[0],peak[0])
limits[1] = max(limits[1],peak[0])
limits[0] = max(1.,(int(limits[0]-1.)/5)*5.)
limits[1] = min(170.,(int(limits[1]+1.)/5)*5.)
return Comments,Peaks,limits,wave
[docs]
def GetCheckImageFile(G2frame,treeId):
'''Try to locate an image file if the project and image have been moved
together. If the image file cannot be found, request the location from
the user.
:param wx.Frame G2frame: main GSAS-II Frame and data object
:param wx.Id treeId: Id for the main tree item for the image
:returns: Npix,imagefile,imagetag with (Npix) number of pixels,
imagefile, if it exists, or the name of a file that does exist or False if the user presses Cancel
and (imagetag) an optional image number
'''
Npix,Imagefile,imagetag = G2frame.GPXtree.GetImageLoc(treeId)
if isinstance(Imagefile,list):
imagefile,imagetag = Imagefile
else:
imagefile = Imagefile
if not os.path.exists(imagefile):
print ('Image file '+imagefile+' not found')
fil = imagefile.replace('\\','/') # windows?!
# see if we can find a file with same name or in a similarly named sub-dir
pth,fil = os.path.split(fil)
prevpth = None
while pth and pth != prevpth:
prevpth = pth
if os.path.exists(os.path.join(G2frame.dirname,fil)):
imagefile = os.path.join(G2frame.dirname,fil)
print (f'found image file {imagefile}')
G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
return Npix,imagefile,imagetag
if os.path.exists(os.path.join(G2frame.LastGPXdir,fil)):
imagefile = os.path.join(G2frame.LastGPXdir,fil)
print (f'found image file {imagefile}')
G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
return Npix,imagefile,imagetag
pth,enddir = os.path.split(pth)
fil = os.path.join(enddir,fil)
# not found as a subdirectory, drop common parts of path for last saved & image file names
# if image was .../A/B/C/imgs/ima.ge
# & GPX was .../A/B/C/refs/fil.gpx but is now .../NEW/TEST/TEST1
# will look for .../NEW/TEST/TEST1/imgs/ima.ge, .../NEW/TEST/imgs/ima.ge, .../NEW/imgs/ima.ge and so on
Controls = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Controls'))
gpxPath = Controls.get('LastSavedAs','').replace('\\','/').split('/') # blank in older .GPX files
imgPath = imagefile.replace('\\','/').split('/')
for p1,p2 in zip(gpxPath,imgPath):
if p1 == p2:
gpxPath.pop(0),imgPath.pop(0)
else:
break
fil = os.path.join(*imgPath) # file with non-common prefix elements
prevpth = None
pth = os.path.abspath(G2frame.dirname)
while pth and pth != prevpth:
prevpth = pth
if os.path.exists(os.path.join(pth,fil)):
print ('found image file '+os.path.join(pth,fil))
imagefile = os.path.join(pth,fil)
G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
return Npix,imagefile,imagetag
pth,enddir = os.path.split(pth)
#GSASIIpath.IPyBreak()
if not os.path.exists(imagefile):
# note that this fails (at least on Mac) to get an image during the GUI initialization
prevnam = os.path.split(imagefile)[1]
prevext = os.path.splitext(imagefile)[1]
wildcard = 'Image format (*'+prevext+')|*'+prevext
dlg = wx.FileDialog(G2frame, 'Previous image file ('+prevnam+') not found; open here', '.', prevnam,
wildcard,wx.FD_OPEN)
try:
dlg.SetFilename(''+os.path.split(imagefile)[1])
if dlg.ShowModal() == wx.ID_OK:
imagefile = dlg.GetPath()
G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
else:
imagefile = None # was False
finally:
dlg.Destroy()
return Npix,imagefile,imagetag
def EditImageParms(parent,Data,Comments,Image,filename):
dlg = wx.Dialog(parent, wx.ID_ANY, 'Edit image parameters',
style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
def onClose(event):
dlg.EndModal(wx.ID_OK)
mainsizer = wx.BoxSizer(wx.VERTICAL)
h,w = Image.size[:2]
mainsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'File '+str(filename)+'\nImage size: '+str(h)+' x '+str(w)),
0,wx.ALIGN_LEFT|wx.ALL, 2)
vsizer = wx.BoxSizer(wx.HORIZONTAL)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'Wavelength (\xC5) '),
0,wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Data,'wavelength')
vsizer.Add(wdgt)
mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
vsizer = wx.BoxSizer(wx.HORIZONTAL)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'Pixel size (\xb5m). Width '),
0,wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Data['pixelSize'],0,size=(50,-1))
vsizer.Add(wdgt)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,' Height '),wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Data['pixelSize'],1,size=(50,-1))
vsizer.Add(wdgt)
mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
vsizer = wx.BoxSizer(wx.HORIZONTAL)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'Sample to detector (mm) '),
0,wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Data,'distance')
vsizer.Add(wdgt)
mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
vsizer = wx.BoxSizer(wx.HORIZONTAL)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'Beam center (pixels). X = '),
0,wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Data['center'],0,size=(75,-1))
vsizer.Add(wdgt)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,' Y = '),wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Data['center'],1,size=(75,-1))
vsizer.Add(wdgt)
mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
vsizer = wx.BoxSizer(wx.HORIZONTAL)
vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'Comments '),
0,wx.ALIGN_LEFT|wx.ALL, 2)
wdgt = G2G.ValidatedTxtCtrl(dlg,Comments,0,size=(250,-1))
vsizer.Add(wdgt)
mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
btnsizer = wx.StdDialogButtonSizer()
OKbtn = wx.Button(dlg, wx.ID_OK, 'Continue')
OKbtn.SetDefault()
OKbtn.Bind(wx.EVT_BUTTON,onClose)
btnsizer.AddButton(OKbtn) # not sure why this is needed
btnsizer.Realize()
mainsizer.Add(btnsizer, 1, wx.ALL|wx.EXPAND, 5)
dlg.SetSizer(mainsizer)
dlg.CenterOnParent()
dlg.ShowModal()
[docs]
def LoadImage2Tree(imagefile,G2frame,Comments,Data,Npix,Image):
'''Load an image into the tree. Saves the location of the image, as well as the
ImageTag (where there is more than one image in the file), if defined.
'''
ImgNames = G2gd.GetGPXtreeDataNames(G2frame,['IMG ',])
TreeLbl = 'IMG '+os.path.basename(imagefile)
ImageTag = Data.get('ImageTag')
ImageSection = Data.get('ImageSection','') #used only in HDF5 at present
if ImageTag:
if ImageSection and ImageTag[1] is None:
TreeLbl += f" {ImageSection}"
elif ImageSection:
TreeLbl += f" {ImageSection} #{ImageTag[1]:04d}"
else:
TreeLbl += f' #{ImageTag:04d}'
imageInfo = (imagefile,ImageTag)
else:
imageInfo = imagefile
TreeName = G2obj.MakeUniqueLabel(TreeLbl,ImgNames)
Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=TreeName)
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Comments'),Comments)
Imax = int(np.amax(Image))
if G2frame.imageDefault:
Data.update(copy.deepcopy(G2frame.imageDefault))
Data['showLines'] = True
Data['ring'] = []
Data['rings'] = []
Data['cutoff'] = 10.
Data['pixLimit'] = 20
Data['edgemin'] = 100000000
Data['calibdmin'] = 0.5
Data['calibskip'] = 0
Data['ellipses'] = []
Data['calibrant'] = ''
Data['GonioAngles'] = [0.,0.,0.]
Data['DetDepthRef'] = False
else:
Data['type'] = 'PWDR'
Data['color'] = GSASIIpath.GetConfigValue('Contour_color','Paired')
if 'tilt' not in Data: #defaults if not preset in e.g. Bruker importer
Data['tilt'] = 0.0
Data['rotation'] = 0.0
Data['pixLimit'] = 20
Data['calibdmin'] = 0.5
Data['cutoff'] = 10.
Data['showLines'] = False
Data['calibskip'] = 0
Data['ring'] = []
Data['rings'] = []
Data['edgemin'] = 100000000
Data['ellipses'] = []
Data['GonioAngles'] = [0.,0.,0.]
Data['DetDepth'] = 0.
Data['DetDepthRef'] = False
Data['calibrant'] = ''
Data['IOtth'] = [5.0,50.0]
if GSASIIpath.GetConfigValue('Image_2theta_min'):
try:
Data['IOtth'][0] = float(GSASIIpath.GetConfigValue('Image_2theta_min'))
except:
pass
if GSASIIpath.GetConfigValue('Image_2theta_max'):
try:
Data['IOtth'][1] = float(GSASIIpath.GetConfigValue('Image_2theta_max'))
except:
pass
Data['LRazimuth'] = [0.,180.]
Data['azmthOff'] = 0.0
Data['outChannels'] = 2500
Data['outAzimuths'] = 1
Data['centerAzm'] = False
Data['fullIntegrate'] = GSASIIpath.GetConfigValue('fullIntegrate',True)
Data['setRings'] = False
Data['background image'] = ['',-1.0]
Data['dark image'] = ['',-1.0]
Data['Flat Bkg'] = 0.0
Data['Oblique'] = [0.5,False]
Data['setDefault'] = False
Data['range'] = [(0,Imax),[0,Imax]]
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Image Controls'),Data)
Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Frames':[],
'Thresholds':[(0,Imax),[0,Imax]],
'SpotMask':{'esdMul':3.,'spotMask':None}}
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Masks'),Masks)
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Stress/Strain'),
{'Type':'True','d-zero':[],'Sample phi':0.0,'Sample z':0.0,'Sample load':0.0})
G2frame.GPXtree.SetItemPyData(Id,[Npix,imageInfo])
G2frame.PickId = Id
G2frame.PickIdText = G2frame.GetTreeItemsList(G2frame.PickId)
G2frame.Image = Id
[docs]
def ReadImages(G2frame,imagefile):
'''Read one or more images from a file and put them into the Tree
using image importers. Called only in :meth:`AutoIntFrame.OnTimerLoop`.
ToDo: Images are most commonly read in :meth:`GSASIIdataGUI.GSASII.OnImportGeneric`
which is called from :meth:`GSASIIdataGUI.GSASII.OnImportImage`
it would be good if these routines used a common code core so that changes need to
be made in only one place.
:param wx.Frame G2frame: main GSAS-II Frame and data object.
:param str imagefile: name of image file
:returns: a list of the id's of the IMG tree items created
'''
# determine which formats are compatible with this file
primaryReaders = []
secondaryReaders = []
for rd in G2frame.ImportImageReaderlist:
flag = rd.ExtensionValidator(imagefile)
if flag is None:
secondaryReaders.append(rd)
elif flag:
primaryReaders.append(rd)
if len(secondaryReaders) + len(primaryReaders) == 0:
print('Error: No matching format for file '+imagefile)
raise Exception('No image read')
errorReport = ''
rdbuffer = {} # create temporary storage for file reader
for rd in primaryReaders+secondaryReaders:
rd.ReInitialize() # purge anything from a previous read
rd.errors = "" # clear out any old errors
if not rd.ContentsValidator(imagefile): # rejected on cursory check
errorReport += "\n "+rd.formatName + ' validator error'
if rd.errors:
errorReport += ': '+rd.errors
continue
ParentFrame = G2frame
block = 0
repeat = True
CreatedIMGitems = []
while repeat: # loop if the reader asks for another pass on the file
block += 1
repeat = False
if GSASIIpath.GetConfigValue('debug'):
flag = rd.Reader(imagefile,ParentFrame,blocknum=block,Buffer=rdbuffer)
else:
flag = False
try:
flag = rd.Reader(imagefile,ParentFrame,blocknum=block,Buffer=rdbuffer)
except rd.ImportException as detail:
rd.errors += "\n Read exception: "+str(detail)
except Exception as detail:
import traceback
rd.errors += "\n Unhandled read exception: "+str(detail)
rd.errors += "\n Traceback info:\n"+str(traceback.format_exc())
if flag: # this read succeeded
if rd.Image is None:
raise Exception('No image read. Strange!')
if GSASIIpath.GetConfigValue('Transpose'):
print ('Transposing Image!')
rd.Image = rd.Image.T
rd.Data['ImageTag'] = rd.repeatcount
rd.readfilename = imagefile
# Load generic metadata, as configured
G2fil.GetColumnMetadata(rd)
LoadImage2Tree(imagefile,G2frame,rd.Comments,rd.Data,rd.Npix,rd.Image)
repeat = rd.repeat
CreatedIMGitems.append(G2frame.Image)
if CreatedIMGitems: return CreatedIMGitems
else:
print('Error reading file '+imagefile)
print('Error messages(s)\n'+errorReport)
return []
#raise Exception('No image read')
def SaveMultipleImg(G2frame):
if not G2frame.GPXtree.GetCount():
print ('no images!')
return
choices = G2gd.GetGPXtreeDataNames(G2frame,['IMG ',])
if len(choices) == 1:
names = choices
else:
dlg = G2G.G2MultiChoiceDialog(G2frame,'Stress/Strain fitting','Select images to fit:',choices)
dlg.SetSelections([])
names = []
if dlg.ShowModal() == wx.ID_OK:
names = [choices[sel] for sel in dlg.GetSelections()]
dlg.Destroy()
if not names: return
for name in names:
Id = G2gd.GetGPXtreeItemId(G2frame, G2frame.root, name)
Npix,imagefile,imagetag = G2frame.GPXtree.GetImageLoc(Id)
imroot = os.path.splitext(imagefile)[0]
if imagetag:
imroot += '_' + str(imagetag)
Data = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id, 'Image Controls'))
print('Writing '+imroot+'.imctrl')
File = open(imroot+'.imctrl','w')
keys = ['type','wavelength','calibrant','distance','center',
'tilt','rotation','azmthOff','fullIntegrate','LRazimuth',
'IOtth','outChannels','outAzimuths','invert_x','invert_y','DetDepth',
'calibskip','pixLimit','cutoff','calibdmin','chisq','Flat Bkg',
'binType','SampleShape','PolaVal','SampleAbs','dark image','background image']
for key in keys:
if key not in Data: continue #uncalibrated!
File.write(key+':'+str(Data[key])+'\n')
File.close()
mask = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id, 'Masks'))
G2imG.CleanupMasks(mask)
print('Writing '+imroot+'.immask')
File = open(imroot+'.immask','w')
for key in ['Points','Rings','Arcs','Polygons','Frames','Thresholds']:
File.write(key+':'+str(mask[key])+'\n')
File.close()
[docs]
def PutG2Image(filename,Comments,Data,Npix,image):
'Write an image as a python pickle - might be better as an .edf file?'
File = open(filename,'wb')
pickle.dump([Comments,Data,Npix,image],File,2)
File.close()
return
objectScanIgnore = [int,bool,float,str,np.float64,np.float32,np.int32,np.int64,np.int16,np.ndarray,G2obj.G2VarObj,G2obj.ExpressionObj,np.bool_]
try:
objectScanIgnore += [ma.MaskedArray] # fails in doc builds
except AttributeError:
pass
[docs]
def objectScan(data,tag,indexStack=[]):
'''Recursively scan an object looking for unexpected data types.
This is used in debug mode to scan .gpx files for objects we did not
intend to be there.
'''
if type(data) is list or type(data) is tuple:
for i in range(len(data)):
val = objectScan(data[i],tag,indexStack+[i])
if val:
data[i] = val
print('...fixed')
elif type(data) is dict:
for key in data:
val = objectScan(data[key],tag,indexStack+[key])
if val:
data[key] = val
print('...fixed')
elif data is None:
return None
elif type(data) in objectScanIgnore:
return None
# not always recognized:
elif 'GSASIIobj.G2VarObj' in str(type(data)):
return None
elif 'GSASIIobj.ExpressionObj' in str(type(data)):
return None
else:
s = 'unexpected object in '+tag
for i in indexStack:
s += "[{}]".format(i)
#print(s,data.__class__.__name__) # loses full name of class
print(s,type(data))
global unexpectedObject
unexpectedObject = True
# fix bad objects
if "gdi.Colour" in str(type(data)):
return tuple(data)
return
def pickleLoad(fp):
return pickle.load(fp,encoding='latin-1')
[docs]
def ProjFileOpen(G2frame,showProvenance=True):
'Read a GSAS-II project file and load into the G2 data tree'
if not os.path.exists(G2frame.GSASprojectfile):
print ('\n*** Error attempt to open project file that does not exist:\n '+
str(G2frame.GSASprojectfile))
return
LastSavedUsing = None
filep = open(G2frame.GSASprojectfile,'rb')
if showProvenance: print ('loading from file: '+G2frame.GSASprojectfile)
GPXphase = os.path.splitext(G2frame.GSASprojectfile)[0]+'.seqPhase'
GPXhist = os.path.splitext(G2frame.GSASprojectfile)[0]+'.seqHist'
deleteSeq = False
hist = None
tmpHistIndex = {}
updateFromSeq = False
if os.path.exists(GPXphase) and os.path.exists(GPXhist):
dlg = wx.MessageDialog(G2frame,
'Load results from crashed sequential fit?\nNo deletes the files!', 'Recover partial sequential fit?', wx.YES | wx.NO | wx.CANCEL)
dlg.CenterOnParent()
try:
result = dlg.ShowModal()
deleteSeq = result != wx.ID_CANCEL
if result == wx.ID_YES:
updateFromSeq = True
fp = open(GPXphase,'rb')
data = pickleLoad(fp) # first block in file should be Phases
if data[0][0] != 'Phases':
raise Exception('Unexpected block in {} file. How did this happen?'
.format(GPXphase))
Phases = {}
for name,vals in data[1:]:
Phases[name] = vals
name,CovData = pickleLoad(fp)[0] # 2nd block in file should be Covariance
name,RigidBodies = pickleLoad(fp)[0] # 3rd block in file should be Rigid Bodies
fp.close()
# index the histogram updates
hist = open(GPXhist,'rb')
try:
while True:
loc = hist.tell()
datum = pickleLoad(hist)[0]
tmpHistIndex[datum[0]] = loc
except EOFError:
pass
finally:
dlg.Destroy()
wx.BeginBusyCursor()
try:
if GSASIIpath.GetConfigValue('show_gpxSize'):
posPrev = 0
sizeList = {}
while True:
try:
data = pickleLoad(filep)
except EOFError:
break
datum = data[0]
if GSASIIpath.GetConfigValue('show_gpxSize'):
sizeList[datum[0]] = filep.tell()-posPrev
posPrev = filep.tell()
# scan the GPX file for unexpected objects
if GSASIIpath.GetConfigValue('debug'):
global unexpectedObject
unexpectedObject = False
objectScan(data,'tree item "{}" entry '.format(datum[0]))
#if unexpectedObject:
# print(datum[0])
# GSASIIpath.IPyBreak()
Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=datum[0])
if datum[0] == 'Phases' and GSASIIpath.GetConfigValue('SeparateHistPhaseTreeItem',False):
G2frame.GPXtree.AppendItem(parent=G2frame.root,text='Hist/Phase')
if updateFromSeq and datum[0] == 'Phases':
for pdata in data[1:]:
if pdata[0] in Phases:
pdata[1].update(Phases[pdata[0]])
elif updateFromSeq and datum[0] == 'Covariance':
data[0][1] = CovData
elif updateFromSeq and datum[0] == 'Rigid bodies':
data[0][1] = RigidBodies
elif updateFromSeq and datum[0] in tmpHistIndex:
hist.seek(tmpHistIndex[datum[0]])
hdata = pickleLoad(hist)
if data[0][0] != hdata[0][0]:
print('Error! Updating {} with {}'.format(data[0][0],hdata[0][0]))
datum = hdata[0]
xferItems = ['Background','Instrument Parameters','Sample Parameters','Reflection Lists']
hItems = {name:j+1 for j,(name,val) in enumerate(hdata[1:]) if name in xferItems}
for j,(name,val) in enumerate(data[1:]):
if name not in xferItems: continue
data[j+1][1] = hdata[hItems[name]][1]
if datum[0].startswith('PWDR'):
if 'ranId' not in datum[1][0]: # patch: add random Id if not present
datum[1][0]['ranId'] = ran.randint(0,sys.maxsize)
G2frame.GPXtree.SetItemPyData(Id,datum[1][:3]) #temp. trim off junk (patch?)
elif datum[0].startswith('HKLF'):
if 'ranId' not in datum[1][0]: # patch: add random Id if not present
datum[1][0]['ranId'] = ran.randint(0,sys.maxsize)
G2frame.GPXtree.SetItemPyData(Id,datum[1])
else:
G2frame.GPXtree.SetItemPyData(Id,datum[1])
if datum[0] == 'Controls' and 'LastSavedUsing' in datum[1]:
LastSavedUsing = datum[1]['LastSavedUsing']
if datum[0] == 'Controls' and 'PythonVersions' in datum[1] and GSASIIpath.GetConfigValue('debug') and showProvenance:
print('DBG_Packages used to create .GPX file:')
if 'dict' in str(type(datum[1]['PythonVersions'])): #patch
for p in sorted(datum[1]['PythonVersions'],key=lambda s: s.lower()):
print(" {:<14s}: {:s}".format(p[0],p[1]))
else:
for p in datum[1]['PythonVersions']:
print(" {:<12s} {:s}".format(p[0]+':',p[1]))
oldPDF = False
for datus in data[1:]:
#patch - 1/23/17 PDF cleanup
if datus[0][:4] in ['I(Q)','S(Q)','F(Q)','G(R)']:
oldPDF = True
data[1][1][datus[0][:4]] = copy.deepcopy(datus[1][:2])
continue
#end PDF cleanup
sub = G2frame.GPXtree.AppendItem(Id,datus[0])
#patch
if datus[0] == 'Instrument Parameters' and len(datus[1]) == 1:
if datum[0].startswith('PWDR'):
datus[1] = [dict(zip(datus[1][3],zip(datus[1][0],datus[1][1],datus[1][2]))),{}]
else:
datus[1] = [dict(zip(datus[1][2],zip(datus[1][0],datus[1][1]))),{}]
for item in datus[1][0]: #zip makes tuples - now make lists!
datus[1][0][item] = list(datus[1][0][item])
#end patch
G2frame.GPXtree.SetItemPyData(sub,datus[1])
if 'PDF ' in datum[0][:4] and oldPDF:
sub = G2frame.GPXtree.AppendItem(Id,'PDF Peaks')
G2frame.GPXtree.SetItemPyData(sub,{'Limits':[1.,5.],'Background':[2,[0.,-0.2*np.pi],False],'Peaks':[]})
if datum [0].startswith('IMG'): #retrieve image default flag & data if set
Data = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id,'Image Controls'))
if Data['setDefault']:
G2frame.imageDefault = Data
G2frame.imageDefault['setDefault'] = False
if 'formatName' in G2frame.imageDefault: del G2frame.imageDefault['formatName']
if LastSavedUsing:
print('GPX load successful. Last saved with GSAS-II revision '+LastSavedUsing)
else:
print('project load successful')
if GSASIIpath.GetConfigValue('show_gpxSize'):
print(50*'=')
print('File section sizes (Kb)')
for item in sizeList:
print(' {:20s} {:10.3f}'.format(
item[:20],sizeList[item]/1024.))
print(50*'=')
G2frame.NewPlot = True
except Exception as errmsg:
if GSASIIpath.GetConfigValue('debug'):
print('\nError reading GPX file:',errmsg)
import traceback
print (traceback.format_exc())
msg = wx.MessageDialog(G2frame,message="Error reading file "+
str(G2frame.GSASprojectfile)+". This is not a current GSAS-II .gpx file",
caption="Load Error",style=wx.ICON_ERROR | wx.OK | wx.STAY_ON_TOP)
msg.ShowModal()
finally:
filep.close()
wx.EndBusyCursor()
G2frame.Status.SetStatusText('Mouse RB drag/drop to reorder',0)
if deleteSeq:
if hist: hist.close()
try:
os.remove(GPXphase)
except:
print('Warning: unable to delete {}'.format(GPXphase))
try:
os.remove(GPXhist)
except:
print('Warning: unable to delete {}'.format(GPXhist))
G2frame.SetTitleByGPX()
if LastSavedUsing:
try:
G2G.updateNotifier(G2frame,int(LastSavedUsing.split()[0]))
except:
pass
[docs]
def ProjFileSave(G2frame):
'Save a GSAS-II project file'
if not G2frame.GPXtree.IsEmpty():
try:
gpxfile = open(G2frame.GSASprojectfile,'wb')
except PermissionError:
G2G.G2MessageBox(G2frame,'Read only file','Project cannot be saved; change permission & try again')
return
print ('save to file: '+G2frame.GSASprojectfile)
# stick the file name into the tree and version info into tree so they are saved.
# (Controls should always have been created in tree at this point)
try:
Controls = G2frame.GPXtree.GetItemPyData(
G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Controls'))
Controls['PythonVersions'] = G2frame.PackageVersions
Controls['LastSavedAs'] = os.path.abspath(G2frame.GSASprojectfile)
Controls['LastSavedUsing'] = f"#{GSASIIpath.GetVersionNumber()}, {GSASIIpath.GetVersionTag()}"
if GSASIIpath.HowIsG2Installed().startswith('git'):
g2repo = GSASIIpath.openGitRepo(GSASIIpath.path2GSAS2)
commit = g2repo.head.commit
Controls['LastSavedUsing'] += f" git {commit.hexsha[:8]}"
else:
gv = GSASIIpath.getSavedVersionInfo()
if gv is not None:
Controls['LastSavedUsing'] += f" static {gv.git_version[:8]}"
except:
pass
wx.BeginBusyCursor()
try:
item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.root)
while item:
data = []
name = G2frame.GPXtree.GetItemText(item)
if name.startswith('Hist/Phase'): # skip over this
item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie)
continue
data.append([name,G2frame.GPXtree.GetItemPyData(item)])
item2, cookie2 = G2frame.GPXtree.GetFirstChild(item)
while item2:
name = G2frame.GPXtree.GetItemText(item2)
data.append([name,G2frame.GPXtree.GetItemPyData(item2)])
item2, cookie2 = G2frame.GPXtree.GetNextChild(item, cookie2)
item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie)
pickle.dump(data,gpxfile,2)
gpxfile.close()
pth = os.path.split(os.path.abspath(G2frame.GSASprojectfile))[0]
if GSASIIpath.GetConfigValue('Save_paths'): G2G.SaveGPXdirectory(pth)
G2frame.LastGPXdir = pth
finally:
wx.EndBusyCursor()
print('project save successful')
[docs]
def SaveIntegration(G2frame,PickId,data,Overwrite=False):
'Save image integration results as powder pattern(s)'
waves = {'Cu':[1.54051,1.54433],'Ti':[2.74841,2.75207],'Cr':[2.28962,2.29351],
'Fe':[1.93597,1.93991],'Co':[1.78892,1.79278],'Mo':[0.70926,0.713543],
'Ag':[0.559363,0.563775]}
azms = G2frame.Integrate[1]
X = G2frame.Integrate[2][:-1]
N = len(X)
Id = G2frame.GPXtree.GetItemParent(PickId)
name = G2frame.GPXtree.GetItemText(Id)
name = name.replace('IMG ',data['type']+' ')
Comments = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id, 'Comments'))
Controls = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Controls'))
Comments.append('Dark image = %s\n'%str(data['dark image']))
Comments.append('Background image = %s\n'%str(data['background image']))
Comments.append('Gain map = %s\n'%str(data['Gain map']))
if 'PWDR' in name:
if 'target' in data:
names = ['Type','Lam1','Lam2','I(L2)/I(L1)','Zero','Polariz.','U','V','W','X','Y','Z','SH/L','Azimuth']
codes = [0 for i in range(14)]
else:
if data.get('IfPink',False):
names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','Z','alpha-0','alpha-1','beta-0','beta-1','Azimuth']
codes = [0 for i in range(15)]
else:
names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','Z','SH/L','Azimuth']
codes = [0 for i in range(12)]
elif 'SASD' in name:
names = ['Type','Lam','Zero','Azimuth']
codes = [0 for i in range(4)]
X = 4.*np.pi*npsind(X/2.)/data['wavelength'] #convert to q
Xminmax = [X[0],X[-1]]
Azms = np.zeros(data['outAzimuths'])
dazm = 0.
if data['outAzimuths'] > 1:
dazm = np.min(np.abs(np.diff(azms)))/2.
G2frame.IntgOutList = []
for i,azm in enumerate(azms[:-1]):
Aname = name+" Azm= %.2f"%((azm+dazm)%360.)
item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.root)
# if Overwrite delete any duplicate
if Overwrite and G2gd.GetGPXtreeItemId(G2frame,G2frame.root,Aname):
print('Replacing '+Aname)
item = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,Aname)
G2frame.GPXtree.Delete(item)
else:
nOcc = 0
while item:
Name = G2frame.GPXtree.GetItemText(item)
if Aname in Name:
nOcc += 1
item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie)
if nOcc:
Aname += '(%d)'%(nOcc)
Sample = G2obj.SetDefaultSample() #set as Debye-Scherrer
Sample['Gonio. radius'] = data['distance']
Sample['Omega'] = data['GonioAngles'][0]
Sample['Chi'] = data['GonioAngles'][1]
Sample['Phi'] = data['GonioAngles'][2]
Sample['Azimuth'] = (azm+dazm)%360. #put here as bin center
polariz = data['PolaVal'][0]
# Scan the comments, but take ones containing "GSAS" as a priority
priorityG2 = [j for j,item in enumerate(Comments) if 'gsas' in item.lower()]
priorityList = priorityG2 + [i for i in range(len(Comments)) if i not in priorityG2]
for key in ('Temperature','Pressure','Time','FreePrm1','FreePrm2',
'FreePrm3','Omega','Chi','Phi'):
for j in priorityList:
item = Comments[j]
if '=' in item:
itemSp = item.split('=')
elif ':' in item:
itemSp = item.split(':')
else:
continue
if key.lower() in itemSp[0].lower():
try:
Sample[key] = float(itemSp[1])
if GSASIIpath.GetConfigValue('debug'):
print(f'Setting {key} from {item}')
break
except:
pass
if 'label_prm' in item.lower():
for num in ('1','2','3'):
if 'label_prm'+num in item.lower():
Controls['FreePrm'+num] = item.split('=')[1].strip()
if 'PWDR' in Aname:
if 'target' in data: #from lab x-ray 2D imaging data
wave1,wave2 = waves[data['target']]
parms = ['PXC',wave1,wave2,0.5,0.0,polariz,290.,-40.,30.,6.,-14.,0.0,0.0001,Azms[i]]
else:
if data.get('IfPink',False):
parms = ['PXB',data['wavelength'],0.0,polariz,0.,8000.,-150.,-24.,0.,0.,0.,13.,-1300.,3.,-7.,Azms[i]] #from Sect 35 LSS
else:
parms = ['PXC',data['wavelength'],0.0,polariz,1.0,-0.10,0.4,0.30,1.0,0.0,0.0001,Azms[i]]
elif 'SASD' in Aname:
Sample['Trans'] = data['SampleAbs'][0]
parms = ['LXC',data['wavelength'],0.0,Azms[i]]
Y = G2frame.Integrate[0][i]
Ymin = np.min(Y)
Ymax = np.max(Y)
W = np.where(Y>0.,1./Y,1.e-6) #probably not true
Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=Aname)
G2frame.IntgOutList.append(Id)
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Comments'),Comments)
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Limits'),copy.deepcopy([tuple(Xminmax),Xminmax]))
if 'PWDR' in Aname:
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Background'),[['chebyschev-1',1,3,1.0,0.0,0.0],
{'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[],'background PWDR':['',1.0,False]}])
inst = [dict(zip(names,zip(parms,parms,codes))),{}]
for item in inst[0]:
inst[0][item] = list(inst[0][item])
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Instrument Parameters'),inst)
if 'PWDR' in Aname:
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Sample Parameters'),Sample)
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Peak List'),{'sigDict':{},'peaks':[]})
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Index Peak List'),[[],[]])
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Unit Cells List'),[])
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Reflection Lists'),{})
elif 'SASD' in Aname:
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Substances'),G2pwd.SetDefaultSubstances())
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Sample Parameters'),Sample)
G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Models'),G2pwd.SetDefaultSASDModel())
valuesdict = {
'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxsize),'Offset':[0.0,0.0],'delOffset':0.02*Ymax,
'refOffset':-0.1*Ymax,'refDelt':0.1*Ymax,'Yminmax':[Ymin,Ymax]}
G2frame.GPXtree.SetItemPyData(Id,[valuesdict,
[np.array(X),np.array(Y),np.array(W),np.zeros(N),np.zeros(N),np.zeros(N)]])
return Id #last powder pattern generated
[docs]
def XYsave(G2frame,XY,labelX='X',labelY='Y',names=[]):
'Save XY table data'
pth = G2G.GetExportPath(G2frame)
dlg = wx.FileDialog(
G2frame, 'Enter csv filename for XY table', pth, '',
'XY table file (*.csv)|*.csv',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
try:
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
filename = os.path.splitext(filename)[0]+'.csv'
File = open(filename,'w')
else:
filename = None
finally:
dlg.Destroy()
if not filename:
return
for i in range(len(XY)):
if len(names):
header = '%s,%s(%s)\n'%(labelX,labelY,names[i])
else:
header = '%s,%s(%d)\n'%(labelX,labelY,i)
File.write(header)
for x,y in XY[i].T:
File.write('%.3f,%.3f\n'%(x,y))
File.close()
print (' XY data saved to: '+filename)
[docs]
def PeakListSave(G2frame,file,peaks):
'Save powder peaks to a data file'
print ('save peak list to file: '+G2frame.peaklistfile)
if not peaks:
dlg = wx.MessageDialog(G2frame, 'No peaks!', 'Nothing to save!', wx.OK)
try:
dlg.ShowModal()
finally:
dlg.Destroy()
return
for peak in peaks:
file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
(peak[0],peak[2],peak[4],peak[6]))
print ('peak list saved')
[docs]
def IndexPeakListSave(G2frame,peaks):
'Save powder peaks from the indexing list'
file = open(G2frame.peaklistfile,'wa')
print ('save index peak list to file: '+G2frame.peaklistfile)
wx.BeginBusyCursor()
try:
if not peaks:
dlg = wx.MessageDialog(G2frame, 'No peaks!', 'Nothing to save!', wx.OK)
try:
dlg.ShowModal()
finally:
dlg.Destroy()
return
for peak in peaks:
file.write("%12.6f\n" % (peak[7]))
file.close()
finally:
wx.EndBusyCursor()
print ('index peak list saved')
######################################################################
[docs]
def ExportPowderList(G2frame):
'''Returns a list of extensions supported by :func:`ExportPowder`
along with their descriptions (note that a extension may be repeated
but descriptions are unique).
This is used in :meth:`GSASIIimgGUI.AutoIntFrame` only.
:param wx.Frame G2frame: the GSAS-II main data tree window
'''
extList = []
extLabel = []
for obj in G2frame.exporterlist:
if 'powder' in obj.exporttype:
try:
obj.Writer
extList.append(obj.extension)
extLabel.append(obj.formatName)
except AttributeError:
pass
return extList,extLabel
[docs]
def ExportPowder(G2frame,TreeName,fileroot,extension,hint=''):
'''Writes a single powder histogram using the Export routines.
This is used in :meth:`GSASIIimgGUI.AutoIntFrame` only.
:param wx.Frame G2frame: the GSAS-II main data tree window
:param str TreeName: the name of the histogram (PWDR ...) in the data tree
:param str fileroot: name for file to be written, extension ignored
:param str extension: extension for file to be written (start with '.'). Must
match a powder export routine that has a Writer object.
:param str hint: a string that must match the export's format
'''
filename = os.path.abspath(os.path.splitext(fileroot)[0]+extension)
for obj in G2frame.exporterlist:
if obj.extension == extension and 'powder' in obj.exporttype:
if hint and hint not in obj.formatName: continue
obj.currentExportType = 'powder'
obj.InitExport(None)
obj.loadTree() # load all histograms in tree into dicts
if TreeName not in obj.Histograms:
raise Exception('Histogram not found: '+str(TreeName))
try:
obj.Writer
except AttributeError:
continue
try:
obj.Writer(TreeName,filename)
print('wrote file '+filename)
return
except Exception:
print('Export Routine for '+extension+' failed.')
else:
print('No Export routine supports extension '+extension)
[docs]
def ExportSequentialFullCIF(G2frame,seqData,Controls):
'''Handles access to CIF exporter a bit differently for sequential fits, as this is
not accessed via the usual export menus
'''
from . import exports
from GSASII.exports import G2export_CIF
##################### debug code to reload exporter before each use ####
#import importlib as imp
#imp.reload(G2export_CIF)
#print('reload G2export_CIF')
########################################################################
obj = G2export_CIF.ExportProjectCIF(G2frame)
obj.Exporter(None,seqData=seqData,Controls=Controls)
[docs]
def ExportSequential(G2frame,data,obj,exporttype):
'''
Used to export from every phase/dataset in a sequential refinement using
a .Writer method for either projects or phases. Prompts to select histograms
and for phase exports, which phase(s).
:param wx.Frame G2frame: the GSAS-II main data tree window
:param dict data: the sequential refinement data object
:param exporter obj: an exporter object
:param str exporttype: indicates the type of export ('project' or 'phase')
'''
if len(data['histNames']) == 0:
G2G.G2MessageBox(G2frame,'There are no sequential histograms','Warning')
obj.InitExport(None)
obj.loadTree()
obj.loadParmDict()
if len(data['histNames']) == 1:
histlist = data['histNames']
else:
dlg = G2G.G2MultiChoiceDialog(G2frame,'Select histograms to export from list',
'Select histograms',data['histNames'])
if dlg.ShowModal() == wx.ID_OK:
histlist = [data['histNames'][l] for l in dlg.GetSelections()]
dlg.Destroy()
else:
dlg.Destroy()
return
if exporttype == 'Phase':
phaselist = list(obj.Phases.keys())
if len(obj.Phases) == 0:
G2G.G2MessageBox(G2frame,'There are no phases in sequential ref.','Warning')
return
elif len(obj.Phases) > 1:
dlg = G2G.G2MultiChoiceDialog(G2frame,'Select phases to export from list',
'Select phases', phaselist)
if dlg.ShowModal() == wx.ID_OK:
phaselist = [phaselist[l] for l in dlg.GetSelections()]
dlg.Destroy()
else:
dlg.Destroy()
return
filename = obj.askSaveFile()
if not filename: return True
obj.dirname,obj.filename = os.path.split(filename)
print('Writing output to file '+str(obj.filename)+"...")
mode = 'w'
for p in phaselist:
for h in histlist:
obj.SetSeqRef(data,h)
#GSASIIpath.IPyBreak()
obj.Writer(h,phasenam=p,mode=mode)
mode = 'a'
print('...done')
elif exporttype == 'Project': # note that the CIF exporter is not yet ready for this
filename = obj.askSaveFile()
if not filename: return True
obj.dirname,obj.filename = os.path.split(filename)
print('Writing output to file '+str(obj.filename)+"...")
mode = 'w'
for h in histlist:
obj.SetSeqRef(data,h)
obj.Writer(h,mode=mode)
print('\t'+str(h)+' written')
mode = 'a'
print('...done')
elif exporttype == 'Powder':
filename = obj.askSaveFile()
if not filename: return True
obj.dirname,obj.filename = os.path.split(filename)
print('Writing output to file '+str(obj.filename)+"...")
mode = 'w'
for h in histlist:
obj.SetSeqRef(data,h)
obj.Writer(h,mode=mode)
print('\t'+str(h)+' written')
mode = 'a'
print('...done')
def ReadDIFFaX(DIFFaXfile):
print ('read '+DIFFaXfile)
Layer = {'Laue':'-1','Cell':[False,1.,1.,1.,90.,90.,90,1.],'Width':[[10.,10.],[False,False]],
'Layers':[],'Stacking':[],'Transitions':[],'Toler':0.01,'AtInfo':{}}
df = open(DIFFaXfile,'r')
lines = df.readlines()
df.close()
struct = False
Struct = []
stack = False
Stack = []
trans = False
Trans = []
for diff in lines:
diff = diff[:-1].lower()
if '!' in diff:
continue
while '}' in diff: #strip comments
iB = diff.index('{')
iF = diff.index('}')+1
if iB:
diff = diff[:iB]
else:
diff = diff[iF:]
if not diff:
continue
if diff.strip() == 'instrumental':
continue
if diff.strip() == 'structural':
struct = True
continue
elif diff.strip() == 'stacking':
struct = False
stack = True
continue
elif diff.strip() == 'transitions':
stack = False
trans = True
continue
diff = diff.strip()
if struct:
if diff:
Struct.append(diff)
elif stack:
if diff:
Stack.append(diff)
elif trans:
if diff:
Trans.append(diff)
#STRUCTURE records
laueRec = Struct[1].split()
Layer['Laue'] = laueRec[0]
if Layer['Laue'] == 'unknown' and len(laueRec) > 1:
Layer['Toler'] = float(laueRec[1]) #tolerance for 'unknown'?
if Layer['Laue'] == '2/m(1)': Layer['Laue'] = '2/m(c)'
if Layer['Laue'] == '2/m(2)': Layer['Laue'] = '2/m(ab)'
cell = Struct[0].split()
Layer['Cell'] = [False,float(cell[0]),float(cell[1]),float(cell[2]),90.,90.,float(cell[3]),1.0]
nLayers = int(Struct[2])
N = 3
if 'layer' not in Struct[3]:
N = 4
if Struct[3] != 'infinite':
width = Struct[3].split()
Layer['Width'][0] = [float(width[0]),float(width[1])]
for nL in range(nLayers):
if '=' in Struct[N]:
name = Struct[N].split('=')
sameas = int(name[1])-1
Layer['Layers'].append({'Name':name[0],'SameAs':Layer['Layers'][sameas]['Name'],'Symm':'None','Atoms':[]})
N += 1
continue
Symm = 'None'
if 'centro' in Struct[N+1]: Symm = '-1'
Layer['Layers'].append({'Name':Struct[N],'SameAs':'','Symm':Symm,'Atoms':[]})
N += 2
while 'layer' not in Struct[N]:
atom = Struct[N][4:].split()
atomType = G2el.FixValence(Struct[N][:4].replace(' ','').strip().capitalize())
if atomType not in Layer['AtInfo']:
Layer['AtInfo'][atomType] = G2el.GetAtomInfo(atomType)
atomName = '%s(%s)'%(atomType,atom[0])
newVals = []
for val in atom[1:6]:
if '/' in val:
newVals.append(eval(val+'.'))
else:
newVals.append(float(val))
atomRec = [atomName,atomType,newVals[0],newVals[1],newVals[2],newVals[4],newVals[3]/78.9568]
Layer['Layers'][-1]['Atoms'].append(atomRec)
N += 1
if N > len(Struct)-1:
break
#TRANSITIONS records
transArray = []
N = 0
for i in range(nLayers):
transArray.append([])
for j in range(nLayers):
vals = Trans[N].split()
newVals = []
for val in vals[:4]:
if '/' in val:
newVals.append(eval(val+'.'))
else:
newVals.append(float(val))
transArray[-1].append(newVals+['',False])
N += 1
Layer['Transitions'] = transArray
#STACKING records
Layer['Stacking'] = [Stack[0],'']
if Stack[0] == 'recursive':
Layer['Stacking'][1] = Stack[1]
elif Stack[0] == 'explicit':
if Stack[1] == 'random':
Layer['Stacking'][1] = Stack[1]
else:
Layer['Stacking'][1] = 'list'
Layer['Stacking'].append('')
for stack in Stack[2:]:
Layer['Stacking'][2] += ' '+stack
return Layer
[docs]
def saveNewPhase(G2frame,phData,newData,phlbl,msgs,orgFilName):
'''create a .gpx file from a structure from the BilbaoSite pseudosym site
saved in newData
'''
def fmtCell(cell):
s = ''
for i in cell[0:3]: s += f"{i:.3f}, "
for i in cell[3:5]: s += f"{i:.2f}, "
s += f"{cell[5]:.2f}"
return s
if newData is None:
print(phlbl,'empty structure')
return
elif type(newData) is str:
msgs[phlbl] = newData
return
# create a new phase
try:
sgnum = int(newData[0].strip())
sgsym = G2spc.spgbyNum[sgnum]
sgname = sgsym.replace(" ","")
except:
print(f'Problem with processing record:\n{newData}')
return
newPhase = copy.deepcopy(phData)
newPhase['ranId'] = ran.randint(0,sys.maxsize),
if 'magPhases' in phData: del newPhase['magPhases']
generalData = newPhase['General']
generalData['SGData'] = SGData = G2spc.SpcGroup(sgsym)[1]
generalData['Cell'][1:7] = [float(i) for i in newData[1].split()]
generalData['Cell'][7] = G2lat.calc_V(G2lat.cell2A(generalData['Cell'][1:7]))
cx,ct,cs,cia = generalData['AtomPtrs']
Atoms = newPhase['Atoms'] = []
for a in newData[3:]:
if not a.strip(): continue
try:
elem,n,wyc,x,y,z = a.split()
atom = []
atom.append(elem+n)
atom.append(elem)
atom.append('')
for i in x,y,z: atom.append(float(i))
atom.append(1.0)
SytSym,Mult = G2spc.SytSym(np.array(atom[3:6]),SGData)[:2]
atom.append(SytSym)
atom.append(Mult)
atom.append('I')
atom += [0.02,0.,0.,0.,0.,0.,0.,]
atom.append(ran.randint(0,sys.maxsize))
Atoms.append(atom)
except:
print(f'error in atom line {a}')
#finally: pass
phData.update(newPhase)
G2elem.SetupGeneral(phData,phData['General']['Mydir']) # fixup composition info
# save new file
G2frame.GSASprojectfile = os.path.splitext(orgFilName
)[0]+'_super_'+sgname.replace('/','$')+'.gpx'
while os.path.exists(G2frame.GSASprojectfile):
s = re.split(r'_([\d]+)\.gpx',G2frame.GSASprojectfile)
if len(s) == 1:
G2frame.GSASprojectfile = os.path.splitext(G2frame.GSASprojectfile)[0] + '_1.gpx'
else:
num = 10
try:
num = int(s[1]) + 1
except:
pass
G2frame.GSASprojectfile = f'{s[0]}_{num}.gpx'
ProjFileSave(G2frame)
# get transformed contents
nacomp,nccomp = G2mth.phaseContents(phData)
msgs[phlbl] = f"With space group {sgsym} and cell={fmtCell(generalData['Cell'][1:7])}"
msgs[phlbl] += f", vol={generalData['Cell'][7]:.2f} A^3"
msgs[phlbl] += f". Project file created as {os.path.split(G2frame.GSASprojectfile)[1]}"
msgs[phlbl] += f". After transform, unit cell {G2mth.fmtPhaseContents(nccomp)}"
msgs[phlbl] += f", density={G2mth.getDensity(generalData)[0]:.2f} g/cm^3"
msgs[phlbl] += f". Asymmetric unit {G2mth.fmtPhaseContents(nacomp)} ({len(phData['Atoms'])} atoms)."
return G2frame.GSASprojectfile
[docs]
def mkParmDictfromTree(G2frame,sigDict=None):
'''Load the GSAS-II refinable parameters from the tree into dict parmDict
Updating refined values to those from the last cycle. Optionally
compute the s.u. values for the parameters and place them in sigDict.
The actions in the routine are used in a number of places around
the GSAS-II code where it would be "cleaner" to use this instead.
Perhaps that will happen as code revisions are made. One example
of this, :meth:`GSASIIfiles.ExportBaseclass.loadParmDict`.
:param wx.Frame G2frame: a reference to the main GSAS-II window
:param dict sigDict: a Python dict with sigma (s.u.) values for
each parameter
:returns: parmDict, a dict with the value for all refined and most
unrefined GSAS-II parameters used in the diffraction computations.
This parmDict version has only values, as opposed to the version
used in some parts of the code that has refinement flags and initial
values as well.
'''
from . import GSASIIstrIO as G2stIO
from . import GSASIIstrMath as G2stMth
from . import GSASIImapvars as G2mv
G2frame.CheckNotebook()
parmDict = {}
rigidbodyDict = {}
covDict = {}
consDict = {}
if G2frame.GPXtree.IsEmpty(): return # nothing to do
Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree()
if not Phases or not Histograms: return # nothing to do
rigidbodyDict = G2frame.GPXtree.GetItemPyData(
G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Rigid bodies'))
covDict = G2frame.GPXtree.GetItemPyData(
G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Covariance'))
consDict = G2frame.GPXtree.GetItemPyData(
G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Constraints'))
rbVary,rbDict = G2stIO.GetRigidBodyModels(rigidbodyDict,Print=False)
parmDict.update(rbDict)
rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})
Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtables,EFtables,ORBtables,BLtables,MFtables,maxSSwave = \
G2stIO.GetPhaseData(Phases,RestraintDict=None,rbIds=rbIds,Print=False)
parmDict.update(phaseDict)
hapVary,hapDict,controlDict = G2stIO.GetHistogramPhaseData(Phases,Histograms,Print=False,resetRefList=False)
parmDict.update(hapDict)
histVary,histDict,histDict1, controlDict = G2stIO.GetHistogramData(Histograms,Print=False)
parmDict.update(histDict)
parmDict.update(zip(
covDict.get('varyList',[]),
covDict.get('variables',[])))
if sigDict is not None:
sigDict.update(dict(zip(
covDict.get('varyList',[]),
covDict.get('sig',[])
)))
# expand to include constraints: first compile a list of constraints
constList = []
for item in consDict:
if item.startswith('_'): continue
constList += consDict[item]
G2mv.InitVars() # process constraints
constrDict,fixedList,ignored = G2mv.ProcessConstraints(constList)
varyList = list(covDict.get('varyListStart',[]))
if varyList is None and len(constrDict) == 0:
# no constraints can use varyList
varyList = covDict.get('varyList')
elif varyList is None:
varyList = []
# # old GPX file from before pre-constraint varyList is saved
print (' *** Old refinement: Please use Calculate/Refine to redo ***')
return None
varyList = list(varyList)
# add constraint generated parameters to parmDict
G2mv.EvaluateMultipliers(constrDict,parmDict)
errmsg,warnmsg,groups,parmlist = G2mv.GenerateConstraints(varyList,constrDict,fixedList,parmDict)
# enforce constraints on values (should have been done; no effect)
G2mv.Map2Dict(parmDict,varyList) # N.B. changes varyList
G2mv.Dict2Map(parmDict)
# add uncertainties for constrained & RB parameters
if sigDict is not None:
sigDict.update(G2mv.ComputeDepESD(
covDict['covMatrix'],covDict['varyList']))
sigDict.update(G2stMth.computeRBsu(parmDict,Phases,rigidbodyDict,
covDict['covMatrix'],covDict['varyList'],covDict['sig']))
return parmDict
[docs]
def LogCellChanges(G2frame):
'''Log varied cell parameters into the data tree notebook'''
Controls = G2frame.GPXtree.GetItemPyData(
G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Controls'))
if Controls['max cyc'] == 0: return # no fit so no change
covData = G2frame.GPXtree.GetItemPyData(
G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Covariance'))
parmDict = mkParmDictfromTree(G2frame)
Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree()
for phase in Phases:
phasedict = Phases[phase]
pId = phasedict['pId']
SGData = phasedict['General']['SGData']
for hist in phasedict['Histograms']:
if not phasedict['Histograms'][hist]['Use']: continue
if 'HKLF' in hist: continue #skip single crystal histograms!
hId = Histograms[hist]['hId']
if any(phasedict['Histograms'][hist]['HStrain'][1]) or phasedict['General']['Cell'][0]:
cellList,cellSig = G2lat.getCellSU(pId,hId,SGData,parmDict,covData)
txt = G2lat.showCellSU(cellList,cellSig,SGData)
G2frame.AddToNotebook(f'Phase {pId} Hist {hId}: {txt}',
'CEL',False)
if __name__ == '__main__':
from . import GSASIIdataGUI
application = GSASIIdataGUI.GSASIImain(0)
G2frame = application.main
#app = wx.PySimpleApp()
#G2frame = wx.Frame(None) # create a frame
#frm.Show(True)
#filename = '/tmp/notzip.zip'
#filename = '/tmp/all.zip'
#filename = '/tmp/11bmb_7652.zip'
#selection=None, confirmoverwrite=True, parent=None
# choicelist=[ ('a','b','c'),
# ('test1','test2'),('no choice',)]
# titles = [ 'a, b or c', 'tests', 'No option here']
# dlg = MultipleChoicesDialog(
# choicelist,titles,
# parent=frm)
# if dlg.ShowModal() == wx.ID_OK:
# print 'Got OK'
#imagefile = '/tmp/NDC5_00237_3.ge3'
#Comments, Data, Npix, Image = G2fil.GetImageData(G2frame,imagefile,imageOnly=False,ImageTag=None)
#print("\n\nResults loaded to Comments, Data, Npix and Image\n\n")
#GSASIIpath.IPyBreak_base()