# -*- coding: utf-8 -*-
#GSASII - phase data display routines
'''
Routines for Phase dataframes follow. Only a few Update routines are here
all others are in GSASIIphsGUI.py
'''
import os
import wx
import wx.grid as wg
import matplotlib as mpl
#import math
import copy
import numpy as np
import numpy.linalg as nl
from . import GSASIIlattice as G2lat
from . import GSASIIspc as G2spc
from . import GSASIIElem as G2elem
from . import GSASIIElemGUI as G2elemGUI
from . import GSASIIplot as G2plt
from . import GSASIIdataGUI as G2gd
from . import GSASIIstrIO as G2stIO
from . import GSASIImath as G2mth
from . import GSASIIpwd as G2pwd
from . import GSASIIctrlGUI as G2G
from . import GSASIIphsGUI as G2phsG
try:
wx.NewIdRef
wx.NewId = wx.NewIdRef
except AttributeError:
pass
try:
VERY_LIGHT_GREY = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
WHITE = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
BLACK = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT)
RED = wx.Colour(255,0,0)
WACV = wx.ALIGN_CENTER_VERTICAL
except:
pass
mapDefault = G2elem.mapDefault
TabSelectionIdDict = {}
# trig functions in degrees
sind = lambda x: np.sin(x*np.pi/180.)
tand = lambda x: np.tan(x*np.pi/180.)
cosd = lambda x: np.cos(x*np.pi/180.)
asind = lambda x: 180.*np.arcsin(x)/np.pi
acosd = lambda x: 180.*np.arccos(x)/np.pi
atan2d = lambda x,y: 180.*np.arctan2(y,x)/np.pi
is_exe = lambda fpath: os.path.isfile(fpath) and os.access(fpath, os.X_OK)
sqt2 = np.sqrt(2.)
sqt3 = np.sqrt(3.)
# previous rigid body selections
prevResId = None
prevVecId = None
prevSpnId = None
GkDelta = chr(0x0394)
Angstr = chr(0x00c5)
RMCmisc = {}
ranDrwDict = {}
ranDrwDict['atomList'] = []
DrawStyleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
#### UpdateDynsomia GUI
[docs]
def UpdateDysnomia(G2frame,data):
''' Present the controls for running Dysnomia
'''
def OnOptMeth(event):
DysData['Optimize'] = OptMeth.GetValue()
wx.CallAfter(UpdateDysnomia,G2frame,data)
def OnZmult(event):
DysData['Lagrange'][0] = Zmult.GetValue()
wx.CallAfter(UpdateDysnomia,G2frame,data)
def OnStart(event):
DysData['DenStart'] = Start.GetValue()
def OnPrior(event):
DysData['prior'] = Prior.GetValue()
if DysData['prior'] == 'last run':
if os.path.isfile(pName+'_prior.pgrid'):
os.remove(pName+'_prior.pgrid')
os.rename(pName+'.pgrid',pName+'_prior.pgrid')
def OnFileCheck(event):
DysData['clear'] = fileCheck.GetValue()
generalData = data['General']
pName = generalData['Name'].replace(' ','_')
Map = generalData['Map']
UseList = Map['RefList']
pId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,UseList[0]) #only use 1st histogram
if not pId:
wx.MessageBox('You must prepare a fourier map before running Dysnomia','Dysnomia Error',
style=wx.ICON_ERROR)
return
treeId = G2gd.GetGPXtreeItemId(G2frame,pId,'Reflection Lists')
if treeId:
reflSets = G2frame.GPXtree.GetItemPyData(treeId)
reflData = reflSets[generalData['Name']]['RefList']
else:
wx.MessageBox('You must have PWDR reflections before running Dysnomia','Dysnomia Error',
style=wx.ICON_ERROR)
return
refDmin = reflData[-1][4]
mulMin = np.argmin(reflData[:][3])
if reflData[mulMin][3] < 0:
refDmin = reflData[mulMin-1][4]
MEMData = G2frame.MEMData
if MEMData.GetSizer():
MEMData.GetSizer().Clear(True)
DysData = data['Dysnomia']
if 'overlap' not in DysData:
DysData['overlap'] = 1.0
if 'MEMdmin' not in DysData:
DysData['MEMdmin'] = refDmin
if 'clear' not in DysData:
DysData['clear'] = True
mainSizer = wx.BoxSizer(wx.VERTICAL)
topSizer = G2frame.dataWindow.topBox
topSizer.Clear(True)
parent = G2frame.dataWindow.topPanel
lbl = f"Maximum Entropy Method (Dysnomia) controls for {data['General']['Name']!r}"
topSizer.Add(wx.StaticText(parent,label=lbl),0,WACV)
topSizer.Add((-1,-1),1,wx.EXPAND)
topSizer.Add(G2G.HelpButton(parent,helpIndex=G2frame.dataWindow.helpKey))
wx.CallAfter(G2frame.dataWindow.SetDataSize)
mainSizer.Add(wx.StaticText(MEMData,label=
' For use of Dysnomia, please cite:\n'+
G2G.GetCite('Dysnomia',wrap=60,indent=5)))
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
lineSizer.Add(wx.StaticText(MEMData,label=' MEM Optimization method: '),0,WACV)
OptMeth = wx.ComboBox(MEMData,-1,value=DysData['Optimize'],choices=['ZSPA','L-BFGS'],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
OptMeth.Bind(wx.EVT_COMBOBOX,OnOptMeth)
lineSizer.Add(OptMeth,0,WACV)
lineSizer.Add(wx.StaticText(MEMData,label=' Peak overlap factor'),0,WACV)
overlap = G2G.ValidatedTxtCtrl(MEMData,DysData,'overlap',nDig=(10,4),xmin=0.1,xmax=1.)
lineSizer.Add(overlap,0,WACV)
mainSizer.Add(lineSizer)
if DysData['Optimize'] == 'ZSPA':
Zsizer = wx.BoxSizer(wx.HORIZONTAL)
Zsizer.Add(wx.StaticText(MEMData,label=' Initial Lagrangian multiplier: from '),0,WACV)
Zmult = wx.ComboBox(MEMData,value=DysData['Lagrange'][0],choices=['user','Dysnomia'],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
Zmult.Bind(wx.EVT_COMBOBOX,OnZmult)
Zsizer.Add(Zmult,0,WACV)
if DysData['Lagrange'][0] == 'user':
Zsizer.Add(wx.StaticText(MEMData,label=' value: '),0,WACV)
lamb = G2G.ValidatedTxtCtrl(MEMData,DysData['Lagrange'],1,nDig=(10,4),xmin=0.0001,xmax=1.)
Zsizer.Add(lamb,0,WACV)
Zsizer.Add(wx.StaticText(MEMData,label=' Adjust by: '),0,WACV)
dlamb = G2G.ValidatedTxtCtrl(MEMData,DysData['Lagrange'],2,nDig=(8,2),xmin=0.05,xmax=0.1)
Zsizer.Add(dlamb,0,WACV)
mainSizer.Add(Zsizer)
Esizer = wx.BoxSizer(wx.HORIZONTAL)
Esizer.Add(wx.StaticText(MEMData,label=' Weight by d-spacing**'),0,WACV)
Efact = G2G.ValidatedTxtCtrl(MEMData,DysData,'wt pwr',xmin=0,xmax=4,size=(50,20))
Esizer.Add(Efact,0,WACV)
Dmin = G2G.ValidatedTxtCtrl(MEMData,DysData,'MEMdmin',xmin=0.5,xmax=refDmin,size=(50,20))
Esizer.Add(wx.StaticText(MEMData,label=' Minimum d-spacing for generated reflections: '),0,WACV)
Esizer.Add(Dmin,0,WACV)
mainSizer.Add(Esizer)
if os.path.isfile(pName+'.pgrid'):
PriorSizer = wx.BoxSizer(wx.HORIZONTAL)
PriorSizer.Add(wx.StaticText(MEMData,label=' Start from densities: '),0,WACV)
Start = wx.ComboBox(MEMData,-1,value=DysData['DenStart'],choices=['uniform','last run'],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
Start.Bind(wx.EVT_COMBOBOX,OnStart)
PriorSizer.Add(Start,0,WACV)
PriorSizer.Add(wx.StaticText(MEMData,label=' Use as prior: '),0,WACV)
Prior = wx.ComboBox(MEMData,-1,value=DysData['prior'],choices=['uniform','last run'],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
Prior.Bind(wx.EVT_COMBOBOX,OnPrior)
PriorSizer.Add(Prior,0,WACV)
mainSizer.Add(PriorSizer)
else:
DysData['DenStart'] = 'uniform'
DysData['prior'] = 'uniform'
Csizer = wx.BoxSizer(wx.HORIZONTAL)
Csizer.Add(wx.StaticText(MEMData,label=' Maximum number of cycles: '),0,WACV)
Cyc = G2G.ValidatedTxtCtrl(MEMData,DysData,'Ncyc',xmin=0,xmax=10000,size=(50,20))
Csizer.Add(Cyc,0,WACV)
fileCheck = wx.CheckBox(MEMData,label='Clear Dynsomia files? ')
fileCheck.SetValue(DysData['clear'])
fileCheck.Bind(wx.EVT_CHECKBOX,OnFileCheck)
Csizer.Add(fileCheck,0,WACV)
mainSizer.Add(Csizer)
G2phsG.SetPhaseWindow(G2frame.MEMData,mainSizer)
#### UpdateDeformation form factor routines ################################################################
def UpdateDeformation(G2frame,data,AtdId):
def OnRadFxn(event):
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
deformationData[-dId]['Radial'] = radFxn.GetStringSelection()
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def OnSSchoice(event):
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
rbSym = deformationData[-dId]['LocSS'] = SSchoice.GetStringSelection()
sytsym = atom[cs].strip()
for harm in data['Deformations'][dId]:
if 'Sl' in harm[0]:
Harm = harm
Hkeys = list(Harm[1].keys())
orders = [int(item[2]) for item in Hkeys if 'D' in item]
if len(orders):
Order = max(orders)
newHarms = {item:Harm[1][item] for item in ['Ne','kappa',"kappa'"]}
for order in np.arange(Order+1):
cofNames,cofSgns = G2lat.GenRBCoeff(sytsym,rbSym,order)
cofNames = [name.replace('C','D') for name in cofNames]
for name in cofNames:
if name in Hkeys:
newHarms[name] = Harm[1][name]
else:
newHarms.update({name:[0.0,False],})
Harm[1] = newHarms
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def MakeUVmat(defData,U,V):
"Cartesian axes: A: X'=U, Y'=(UxV)xU & Z'=UxV,B: X'=U, Y'=UxV & Z'=Ux(UxV)"
" C: X'=UxV, Y'=Ux(UxV) & Z'=U, D: X'=(UxV)xU, Y=(UxV) & Z'=U"
if 'A' in defData['MUV']: #"X'=U, Y'=(UxV)xU & Z'=UxV"
MX = U/nl.norm(U)
MY = V/nl.norm(V)
MZ = np.cross(MX,MY)
MZ /= nl.norm(MZ)
MY = np.cross(MZ,MX)
MY /= nl.norm(MY)
elif 'B' in defData['MUV']: #"X'=U, Y'=UxV & Z'=Ux(UxV)"
MX = U/nl.norm(U)
MZ = V/nl.norm(V)
MY = np.cross(MZ,MX)
MY /= nl.norm(MY)
MZ = np.cross(MX,MY)
MZ /= nl.norm(MZ)
elif 'C' in defData['MUV']: #"X'=UxV, Y'=Ux(UxV) & Z'=U"
MZ = U/nl.norm(U)
MY = V/nl.norm(V)
MX = np.cross(MZ,MY)
MX /= nl.norm(MX)
MY = np.cross(MZ,MX)
MY /= nl.norm(MY)
elif 'D' in defData['MUV']: #"X'=(UxV)xU, Y=(UxV) & Z'=U"
MZ = U/nl.norm(U)
MX = V/nl.norm(V)
MY = np.cross(MZ,MX)
MY /= nl.norm(MY)
MX = np.cross(MY,MZ)
MX /= nl.norm(MX)
return np.vstack((MX,MY,MZ)).T
def OnDeformRef(event):
Obj = event.GetEventObject()
dId,oId,dkey = Indx[Obj.GetId()]
deformationData[dId][oId][1][dkey][1] = not deformationData[dId][oId][1][dkey][1]
def OnPlotAtm(event):
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
atom = atomData[AtLookUp[dId]]
neigh = G2mth.FindAllNeighbors(data,atom[ct-1],AtNames)
deform = deformationData[dId]
UVmat = deformationData[-dId]['UVmat']
radial = deformationData[-dId]['Radial']
G2plt.PlotDeform(G2frame,generalData,atom[ct-1],atom[ct],deform,UVmat,radial,neigh)
def OnDelAtm(event):
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
del deformationData[dId]
wx.CallAfter(UpdateDeformation,G2frame,data,None)
def OnMatSel(event):
"Cartesian axes: A: X'=U, Y'=(UxV)xU & Z'=UxV,B: X'=U, Y'=UxV & Z'=Ux(UxV)"
" C: X'=UxV, Y'=Ux(UxV) & Z'=U, D: X'=(UxV)xU, Y=(UxV) & Z'=U"
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
deformationData[-dId]['MUV'] = Obj.GetValue()
U = UVvec[dId][UVchoice[dId].index(deformationData[-dId]['U'])]
V = UVvec[dId][UVchoice[dId].index(deformationData[-dId]['V'])]
UVmat = MakeUVmat(deformationData[-dId],U,V)
data['Deformations'][-dId]['UVmat'] = UVmat
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def OnUvec(event):
"Cartesian axes: A: X'=U, Y'=(UxV)xU & Z'=UxV,B: X'=U, Y'=UxV & Z'=Ux(UxV)"
" C: X'=UxV, Y'=Ux(UxV) & Z'=U, D: X'=(UxV)xU, Y=(UxV) & Z'=U"
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
if Obj.GetValue() == deformationData[-dId]['V']:
Obj.SetValue(deformationData[-dId]['U'])
else:
U = UVvec[dId][Obj.GetSelection()]
V = UVvec[dId][UVchoice[dId].index(deformationData[-dId]['V'])]
UVmat = MakeUVmat(deformationData[-dId],U,V)
if np.any(np.isnan(UVmat)):
Obj.SetValue(deformationData[-dId]['U'])
G2G.G2MessageBox(G2frame,'ERROR: Z: U-vector zero or parallel to V','Invalid vector choice')
return
if nl.det(UVmat) < 0.: #ensure right hand
UVmat *= -1.
deformationData[-dId]['U'] = Obj.GetValue()
data['Deformations'][-dId]['UVmat'] = UVmat
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def OnVvec(event):
"Cartesian axes: A: X'=U, Y'=(UxV)xU & Z'=UxV,B: X'=U, Y'=UxV & Z'=Ux(UxV)"
" C: X'=UxV, Y'=Ux(UxV) & Z'=U, D: X'=(UxV)xU, Y=(UxV) & Z'=U"
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
if Obj.GetValue() == deformationData[-dId]['U']:
Obj.SetValue(deformationData[-dId]['V'])
else:
U = UVvec[dId][UVchoice[dId].index(deformationData[-dId]['U'])]
V = UVvec[dId][Obj.GetSelection()]
UVmat = MakeUVmat(deformationData[-dId],U,V)
if np.any(np.isnan(UVmat)):
Obj.SetValue(deformationData[-dId]['V'])
G2G.G2MessageBox(G2frame,'ERROR: V-vector zero or parallel to U','Invalid vector choice')
return
if nl.det(UVmat) < 0.: #insure right hand
UVmat *= -1.
deformationData[-dId]['V'] = Obj.GetValue()
data['Deformations'][-dId]['UVmat'] = UVmat
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def OnAtSel(event):
dId = atomList[atSel.GetValue()]
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def Kappa(deformation,orbSizer,dId,orb,kname,Indx):
orbSizer.Add(G2G.ValidatedTxtCtrl(deformation,orb[1][kname],0,nDig=(8,3),xmin=0.5,xmax=3.0))
Tcheck = wx.CheckBox(deformation,-1,'Refine?')
Tcheck.SetValue(orb[1][kname][1])
Tcheck.Bind(wx.EVT_CHECKBOX,OnDeformRef)
Indx[Tcheck.GetId()] = [dId,iorb,kname]
orbSizer.Add(Tcheck)
def NeSizer(deformation,orbSizer,dId,orb,Indx):
orbSizer.Add(G2G.ValidatedTxtCtrl(deformation,orb[1]['Ne'],0,nDig=(8,3),xmin=0.,xmax=10.))
Tcheck = wx.CheckBox(deformation,-1,'Refine?')
Tcheck.SetValue(orb[1]['Ne'][1])
Tcheck.Bind(wx.EVT_CHECKBOX,OnDeformRef)
Indx[Tcheck.GetId()] = [dId,iorb,'Ne']
orbSizer.Add(Tcheck)
def Dsizer(deformation,orbSizer,Names,dId,orb,Indx):
name = Names.get(item,'') #Names only go to order = 3
orbSizer.Add(wx.StaticText(deformation,label=item+name+':'))
orbSizer.Add(G2G.ValidatedTxtCtrl(deformation,orb[1][item],0,nDig=(8,5),xmin=-1.5,xmax=1.5))
Tcheck = wx.CheckBox(deformation,-1,'Refine?')
Tcheck.SetValue(orb[1][item][1])
Tcheck.Bind(wx.EVT_CHECKBOX,OnDeformRef)
Indx[Tcheck.GetId()] = [dId,iorb,item]
orbSizer.Add(Tcheck)
def OnNewHarm(event):
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
atom = atomData[AtLookUp[dId]]
sytsym = atom[cs].strip()
rbSym = deformationData[-dId]['LocSS']
for harm in data['Deformations'][dId]:
if 'Sl' in harm[0]:
Harm = harm
Order = 1
Hkeys = list(Harm[1].keys())
orders = [int(item[2]) for item in Hkeys if 'D' in item]
if len(orders):
Order = max(orders)+1
cofNames = []
notFound = True
while notFound and Order < 6:
cofNames,cofSgns = G2lat.GenRBCoeff(sytsym,rbSym,Order)
cofNames = [name.replace('C','D') for name in cofNames]
for name in cofNames:
if name not in Hkeys: #new names found
notFound = False
Harm[1].update({name:[0.0,False]})
# if '0' not in name:
# negname = name.replace(',',',-')
# Harm[1].update({negname:[0.0,False]})
Order += 1
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def OnDelHarm(event):
Obj = event.GetEventObject()
dId = Indx[Obj.GetId()]
minL = 1 #always an "Ne"
for harm in data['Deformations'][dId]:
if 'Sl' in harm[0]:
Harm = harm
minL = 2 # & 'kappa'
Hkeys = list(Harm[1].keys())
if len(Hkeys) > minL:
maxord = max([int(item[2]) for item in Hkeys if 'D' in item])
for item in Hkeys:
if 'D' in item and int(item[2]) == maxord:
del Harm[1][item]
if len(Harm[1]) == 3:
del Harm[1]["kappa'"]
wx.CallAfter(UpdateDeformation,G2frame,data,dId)
def OnShowDef(event):
dId = Indx[event.GetEventObject().GetId()]
deformationData[-dId]['showDef'] = not deformationData[-dId]['showDef']
G2plt.PlotStructure(G2frame,data)
def OnAtCol(event):
dId = Indx[event.GetEventObject().GetId()]
deformationData[-dId]['atColor'] = not deformationData[-dId]['atColor']
G2plt.PlotStructure(G2frame,data)
# UpdateDeformation executable code starts here
deformation = G2frame.deformation
alpha = ['A','B','C','D','E','F','G','H',]
generalData = data['General']
cx,ct,cs,cia = generalData['AtomPtrs']
Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
atomData = data['Atoms']
AtLookUp = G2mth.FillAtomLookUp(atomData,cia+8)
AtNames = [atom[ct-1] for atom in atomData]
deformationData = data['Deformations']
dId = AtdId
if deformation.GetSizer():
deformation.GetSizer().Clear(True)
atomList = {}
for item in deformationData:
if item in AtLookUp:
atom = atomData[AtLookUp[item]]
atomList.update({atom[ct-1]:item})
AtChoice = ' '
if dId is not None:
AtChoice = atomData[AtLookUp[dId]][ct-1]
elif len(atomList):
AtChoice = list(atomList.keys())[0]
dId = atomList[AtChoice]
topSizer = G2frame.dataWindow.topBox
topSizer.Clear(True)
parent = G2frame.dataWindow.topPanel
lbl= f"Atomic deformation data for {data['General']['Name']!r}"[:60]
topSizer.Add(wx.StaticText(parent,label=lbl),0,WACV)
topSizer.Add((-1,-1),1,wx.EXPAND)
topSizer.Add(G2G.HelpButton(parent,helpIndex=G2frame.dataWindow.helpKey))
wx.CallAfter(G2frame.dataWindow.SetDataSize)
mainSizer = wx.BoxSizer(wx.VERTICAL)
topSizer = wx.BoxSizer(wx.HORIZONTAL)
if dId is None:
topSizer.Add(wx.StaticText(deformation,
label='No atoms in deformation list. Do add atom first (neutral atoms only)'),0,WACV)
else:
topSizer.Add(wx.StaticText(deformation,label=' Select an atom '),0,WACV)
atSel = wx.ComboBox(deformation,value=AtChoice,choices=list(atomList.keys()),style=wx.CB_READONLY|wx.CB_DROPDOWN)
atSel.Bind(wx.EVT_COMBOBOX,OnAtSel)
topSizer.Add(atSel,0,WACV)
mainSizer.Add(topSizer,0,wx.EXPAND)
if dId is not None:
Indx = {}
UVchoice = {}
UVvec = {}
#patch
if 'UVmat' not in deformationData[-dId] or 'MUV' not in deformationData[-dId]:
deformationData[-dId] = {'U':'X','V':'Y','UVmat':np.eye(3),'MUV':"A: X'=U, Y'=(UxV)xU & Z'=UxV"}
#end patch
atom = atomData[AtLookUp[dId]]
neigh = G2mth.FindAllNeighbors(data,atom[ct-1],AtNames)[0]
neigh = G2mth.sortArray(neigh,2) #sort by dist
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
lineSizer.Add(wx.StaticText(deformation,label=' For atom %s, site sym %s:'%(atom[ct-1],atom[cs])),0,WACV)
plotAtm = wx.Button(deformation,label='Plot')
plotAtm.Bind(wx.EVT_BUTTON,OnPlotAtm)
Indx[plotAtm.GetId()] = dId
lineSizer.Add(plotAtm,0,WACV)
deformationData[-dId]['showDef'] = deformationData[-dId].get('showDef',False)
deformationData[-dId]['atColor'] = deformationData[-dId].get('atColor',True)
showDef = wx.CheckBox(deformation,label='show def.?')
showDef.SetValue(deformationData[-dId]['showDef'])
Indx[showDef.GetId()] = dId
showDef.Bind(wx.EVT_CHECKBOX,OnShowDef)
lineSizer.Add(showDef,0,WACV)
atCol = wx.CheckBox(deformation,label='use atom colors?')
atCol.SetValue(deformationData[-dId]['atColor'])
Indx[atCol.GetId()] = dId
atCol.Bind(wx.EVT_CHECKBOX,OnAtCol)
lineSizer.Add(atCol,0,WACV)
delAtm = wx.Button(deformation,label='Delete')
delAtm.Bind(wx.EVT_BUTTON,OnDelAtm)
Indx[delAtm.GetId()] = dId
lineSizer.Add(delAtm,0,WACV)
mainSizer.Add(lineSizer)
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
names = []
if not len(neigh):
lineSizer.Add(wx.StaticText(deformation,label=' No neighbors found; Do Set bond parms to expand search'),0,WACV)
elif len(neigh) < 9:
names = ['%s=%s'%(alpha[i],item[0].replace(' ','')) for i,item in enumerate(neigh)]
lineSizer.Add(wx.StaticText(deformation,label=' Neighbors: '+str(names)),0,WACV)
else:
names = 'Too many neighbors - change atom radii to fix'
UVchoice[dId] = ['X','Y','Z','X+Y','X+Y+Z',]
UVvec[dId] = [[1.,0.,0.],[0.,1.,0.],[0.,0.,1.],[1.,1.,0.]/sqt2,[1.,1.,1.]/sqt3,]
NUVvec,NUVchoice = G2lat.SetUVvec(neigh)
UVchoice[dId] += NUVchoice
UVvec[dId] += NUVvec
lineSizer.Add(wx.StaticText(deformation,label=' Local site sym:'),0,WACV)
SSchoices = G2spc.GetSytSymChoice(atom[cs])
deformationData[-dId]['LocSS'] = deformationData[-dId].get('LocSS',atom[cs][:])
SSchoice = wx.ComboBox(deformation,value=deformationData[-dId]['LocSS'],
choices=SSchoices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
Indx[SSchoice.GetId()] = dId
SSchoice.Bind(wx.EVT_COMBOBOX,OnSSchoice)
lineSizer.Add(SSchoice,0,WACV)
mainSizer.Add(lineSizer)
mainSizer.Add(wx.StaticText(deformation,
label=" NB: Local site sym always has unique axis || Z' and second axis || X'; choose U && V carefully"))
matSizer = wx.BoxSizer(wx.HORIZONTAL)
Mchoice = ["A: X'=U, Y'=(UxV)xU & Z'=UxV","B: X'=U, Y'=UxV & Z'=Ux(UxV)",
"C: X'=UxV, Y'=Ux(UxV) & Z'=U","D: X'=(UxV)xU, Y=(UxV) & Z'=U"]
matSizer.Add(wx.StaticText(deformation,label=' Orbital Cartesian axes:'),0,WACV)
matSel = wx.ComboBox(deformation,choices=Mchoice,value=deformationData[-dId]['MUV'],style=wx.CB_READONLY|wx.CB_DROPDOWN)
matSel.Bind(wx.EVT_COMBOBOX,OnMatSel)
Indx[matSel.GetId()] = dId
matSizer.Add(matSel,0,WACV)
deformationData[-dId]['Radial'] = deformationData[-dId].get('Radial','Slater')
topSizer.Add(wx.StaticText(deformation,label=' Select radial fxn: '),0,WACV)
fxchoice = deformationData[-dId].get('fxchoice',['Slater',])
radFxn = wx.ComboBox(deformation,value=deformationData[-dId]['Radial'],
choices=fxchoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
Indx[radFxn.GetId()] = dId
radFxn.Bind(wx.EVT_COMBOBOX,OnRadFxn)
topSizer.Add(radFxn,0,WACV)
mainSizer.Add(matSizer)
oriSizer = wx.BoxSizer(wx.HORIZONTAL)
oriSizer.Add(wx.StaticText(deformation,label=' Select orbital U vector: '),0,WACV)
Uvec = wx.ComboBox(deformation,value=deformationData[-dId]['U'],choices=UVchoice[dId],style=wx.CB_READONLY|wx.CB_DROPDOWN)
Uvec.Bind(wx.EVT_COMBOBOX,OnUvec)
Indx[Uvec.GetId()] = dId
oriSizer.Add(Uvec,0,WACV)
oriSizer.Add(wx.StaticText(deformation,label=' Select orbital V vector: '),0,WACV)
Vvec = wx.ComboBox(deformation,value=deformationData[-dId]['V'],choices=UVchoice[dId],style=wx.CB_READONLY|wx.CB_DROPDOWN)
Vvec.Bind(wx.EVT_COMBOBOX,OnVvec)
Indx[Vvec.GetId()] = dId
oriSizer.Add(Vvec,0,WACV)
if 'Slater' in data['Deformations'][-dId]['Radial']:
newHarm = wx.Button(deformation,label='Add harmonic')
newHarm.Bind(wx.EVT_BUTTON,OnNewHarm)
Indx[newHarm.GetId()] = dId
oriSizer.Add(newHarm,0,WACV)
delHarm = wx.Button(deformation,label='Delete highest harmonic')
delHarm.Bind(wx.EVT_BUTTON,OnDelHarm)
Indx[delHarm.GetId()] = dId
oriSizer.Add(delHarm,0,WACV)
mainSizer.Add(oriSizer)
G2G.HorizontalLine(mainSizer,deformation)
Names = {'D(1,-1)':'py','D(1,0)':'pz','D(1,1)':'px',
'D(2,-2)':'dxy','D(2,-1)':'dyz','D(2,0)':'dz2','D(2,1)':'dxz','D(2,2)':'dx2-y2',
'D(3,-3)':'fy(3x2-y2)','D(3,-2)':'fxyz','D(3,-1)':'fyz2','D(3,0)':'fz3',
'D(3,1)':'fxz2','D(3,2)':'fz(x2-y2)','D(3,3)':'fx(x2-3y2)',}
mainSizer.Add(wx.StaticText(deformation,label=' Deformation parameters:'))
orbSizer = wx.FlexGridSizer(0,9,2,2)
for iorb,orb in enumerate(deformationData[dId]):
# if deformationData[-dId]['Radial'] == 'Bessel' and 'Sl ' not in orb[0]:
# if '<j0>' in orb[0]:
# orbSizer.Add(wx.StaticText(deformation,label=orb[0]+' Ne:'))
# NeSizer(deformation,orbSizer,dId,orb,Indx)
# if 'kappa' in orb[1]:
# orbSizer.Add(wx.StaticText(deformation,label=' kappa:'))
# Kappa(deformation,orbSizer,dId,orb,'kappa',Indx)
# for i in range(3): orbSizer.Add((5,5),0)
# continue
# if 'kappa' in orb[1]:
# for i in range(3): orbSizer.Add((5,5),0)
# orbSizer.Add(wx.StaticText(deformation,label=orb[0]+" kappa':"))
# Kappa(deformation,orbSizer,dId,orb,"kappa'",Indx)
# if 'kappa' not in orb[1]:
# orbSizer.Add(wx.StaticText(deformation,label=orb[0]+':'))
# for i in range(2): orbSizer.Add((5,5),0)
# nItem = 0
# for item in orb[1]:
# if 'D' in item:
# nItem += 1
# Dsizer(deformation,orbSizer,Names,dId,orb,Indx)
# if nItem in [2,4,6,8,10]:
# for i in range(3): orbSizer.Add((5,5),0)
# for i in range(3): orbSizer.Add((5,5),0)
# elif deformationData[-dId]['Radial'] == 'Slater' and 'Sl ' in orb[0]:
orbSizer.Add(wx.StaticText(deformation,label=orb[0]+' Ne:'))
NeSizer(deformation,orbSizer,dId,orb,Indx)
orbSizer.Add(wx.StaticText(deformation,label=' kappa:'))
Kappa(deformation,orbSizer,dId,orb,'kappa',Indx)
if len(orb[1]) > 2:
orb[1]["kappa'"] = orb[1].get("kappa'",[1.0,False])
orbSizer.Add(wx.StaticText(deformation,label=" kappa':"))
Kappa(deformation,orbSizer,dId,orb,"kappa'",Indx)
iD = 1
for item in orb[1]:
if 'D' in item:
if iD < int(item[2]):
iD = int(item[2])
nItems = orbSizer.GetItemCount()%9
if nItems:
nB = 9-nItems
for i in range(nB): orbSizer.Add((5,5),0)
Dsizer(deformation,orbSizer,Names,dId,orb,Indx)
mainSizer.Add(orbSizer)
G2frame.GetStatusBar().SetStatusText('On plot: RGB = XYZ',1)
G2phsG.SetPhaseWindow(deformation,mainSizer)
#### UpdateISODISTORT ###############################################################################
[docs]
def UpdateISODISTORT(G2frame,data,Scroll=0):
''' Setup ISODISTORT and present the results. Allow selection of a distortion model for PDFfit or
GSAS-II structure refinement as a cif file produced by ISODISTORT. Allows manipulation of distortion
mode displacements selection their refinement for this new phase.
'''
def displaySetup():
def OnParentCif(event):
dlg = wx.FileDialog(G2frame.ISODIST, 'Select parent cif file',G2frame.LastGPXdir,
style=wx.FD_OPEN ,wildcard='cif file(*.cif)|*.cif')
if dlg.ShowModal() == wx.ID_OK:
fName = dlg.GetFilename()
fDir = dlg.GetDirectory()
ISOdata['ParentCIF'] = os.path.join(fDir,fName)
dlg.Destroy()
else:
dlg.Destroy()
UpdateISODISTORT(G2frame,data)
def OnUsePhase(event):
ISOdata['ParentCIF'] = 'Use this phase'
UpdateISODISTORT(G2frame,data)
def OnMethodSel(event):
method = methodSel.GetSelection()+1
if method in [1,4]:
ISOdata['ISOmethod'] = method
UpdateISODISTORT(G2frame,data)
def OnChildCif(event):
dlg = wx.FileDialog(G2frame.ISODIST, 'Select child cif file',G2frame.LastGPXdir,
style=wx.FD_OPEN ,wildcard='cif file(*.cif)|*.cif')
if dlg.ShowModal() == wx.ID_OK:
fName = dlg.GetFilename()
fDir = dlg.GetDirectory()
ISOdata['ChildCIF'] = os.path.join(fDir,fName)
dlg.Destroy()
else:
dlg.Destroy()
UpdateISODISTORT(G2frame,data)
def OnUsePhase2(event):
ISOdata['ChildCIF'] = 'Use this phase'
UpdateISODISTORT(G2frame,data)
topSizer = wx.BoxSizer(wx.VERTICAL)
topSizer.Add(wx.StaticText(G2frame.ISODIST,label=' ISODISTORT setup controls:'))
parentSizer = wx.BoxSizer(wx.HORIZONTAL)
parentSizer.Add(wx.StaticText(G2frame.ISODIST,label=' Parent cif file:'),0,WACV)
parentCif = wx.Button(G2frame.ISODIST,label=ISOdata['ParentCIF'],size=(300,24))
parentCif.Bind(wx.EVT_BUTTON,OnParentCif)
parentSizer.Add(parentCif,0,WACV)
if 'Use this phase' not in ISOdata['ChildCIF'] and 'Use this phase' not in ISOdata['ParentCIF']:
usePhase = wx.Button(G2frame.ISODIST,label=' Use this phase? ')
usePhase.Bind(wx.EVT_BUTTON,OnUsePhase)
parentSizer.Add(usePhase,0,WACV)
topSizer.Add(parentSizer)
#patch
if 'ISOmethod' not in ISOdata:
ISOdata['ISOmethod'] = 1
#end patch
choice = ['Method 1: Search over all special k points - yields only single Irrep models',
'Method 2: not implemented in GSAS-II',
'Method 3: not implemented in GSAS-II',
'Method 4: Mode decomposition of known child structure']
methodSel = wx.RadioBox(G2frame.ISODIST,label='Select ISODISTORT method:',choices=choice,
majorDimension=1,style=wx.RA_SPECIFY_COLS)
methodSel.SetSelection(ISOdata['ISOmethod']-1)
methodSel.Bind(wx.EVT_RADIOBOX,OnMethodSel)
topSizer.Add(methodSel)
if ISOdata['ISOmethod'] == 4:
childSizer = wx.BoxSizer(wx.HORIZONTAL)
childSizer.Add(wx.StaticText(G2frame.ISODIST,label=' Child cif file:'),0,WACV)
childCif = wx.Button(G2frame.ISODIST,label=ISOdata['ChildCIF'],size=(300,24))
childCif.Bind(wx.EVT_BUTTON,OnChildCif)
childSizer.Add(childCif,0,WACV)
if 'Use this phase' not in ISOdata['ChildCIF'] and 'Use this phase' not in ISOdata['ParentCIF']:
usePhase2 = wx.Button(G2frame.ISODIST,label=' Use this phase? ')
usePhase2.Bind(wx.EVT_BUTTON,OnUsePhase2)
childSizer.Add(usePhase2,0,WACV)
topSizer.Add(childSizer)
return topSizer
def displaySubset():
def OnLaue(event):
Obj = event.GetEventObject()
name = Indx[Obj.GetId()]
ISOdata['SGselect'][name[:4]] = not ISOdata['SGselect'][name[:4]]
ISOdata['selection'] = None
UpdateISODISTORT(G2frame,data)
def OnAllBtn(event):
for item in ISOdata['SGselect']:
ISOdata['SGselect'][item] = not ISOdata['SGselect'][item]
ISOdata['selection'] = None
UpdateISODISTORT(G2frame,data)
topSizer = wx.BoxSizer(wx.VERTICAL)
G2G.HorizontalLine(topSizer,G2frame.ISODIST)
topSizer.Add(wx.StaticText(G2frame.ISODIST,label='ISODISTORT Method 1 distortion search results:'))
topSizer.Add(wx.StaticText(G2frame.ISODIST,label=' Subset selection if desired:'))
laueName = ['Cubic','Hexagonal','Trigonal','Tetragonal','Orthorhombic','Monoclinic','Triclinic']
littleSizer = wx.FlexGridSizer(0,8,5,5)
Indx = {}
for name in laueName:
laueCk = wx.CheckBox(G2frame.ISODIST,label=name)
Indx[laueCk.GetId()] = name
laueCk.SetValue(ISOdata['SGselect'][name[:4]])
laueCk.Bind(wx.EVT_CHECKBOX,OnLaue)
littleSizer.Add(laueCk,0,WACV)
allBtn = wx.Button(G2frame.ISODIST,label='Toggle all')
allBtn.Bind(wx.EVT_BUTTON,OnAllBtn)
littleSizer.Add(allBtn)
topSizer.Add(littleSizer)
return topSizer
def displayRadio():
def CheckItem(item):
SGnum = int(item.split()[1].split('*')[0])
for SGtype in ISOdata['SGselect']:
if ISOdata['SGselect'][SGtype] and SGnum in SGrange[SGtype]:
return True
return False
def OnSelect(event):
r,c = event.GetRow(),event.GetCol()
if c == 0:
ISOdata['selection'] = [r,isoTable.GetValue(r,1)]
for row in range(isoGrid.GetNumberRows()):
isoTable.SetValue(row,c,False)
isoTable.SetValue(r,c,True)
isoGrid.ForceRefresh()
SGrange = {'Cubi':np.arange(195,231),'Hexa':np.arange(168,195),'Trig':np.arange(143,168),'Tetr':np.arange(75,143),
'Orth':np.arange(16,75),'Mono':np.arange(3,16),'Tric':np.arange(1,3)}
bottomSizer = wx.BoxSizer(wx.VERTICAL)
colLabels = ['select',' ISODISTORT order parameter direction description']
colTypes = [wg.GRID_VALUE_BOOL,wg.GRID_VALUE_STRING,]
Radio = ISOdata['radio']
rowLabels = []
table = []
for i,item in enumerate(Radio):
if CheckItem(Radio[item]):
if ISOdata['selection'] and ISOdata['selection'][0] == i:
table.append([True,Radio[item]])
else:
table.append([False,Radio[item]])
rowLabels.append(str(i))
isoTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=colTypes)
isoGrid = G2G.GSGrid(G2frame.ISODIST)
isoGrid.SetTable(isoTable,True,useFracEdit=False)
isoGrid.AutoSizeColumns(True)
isoGrid.SetColLabelAlignment(wx.ALIGN_LEFT,wx.ALIGN_CENTRE)
bottomSizer.Add(isoGrid)
attr = wg.GridCellAttr()
attr.SetReadOnly(True)
attr.SetBackgroundColour(VERY_LIGHT_GREY)
isoGrid.SetColAttr(1,attr)
isoGrid.Bind(wg.EVT_GRID_CELL_LEFT_CLICK, OnSelect)
return bottomSizer
def displayModes():
def OnDispl(event):
'''Respond to movement of distortion mode slider'''
Obj = event.GetEventObject()
idsp,dispVal = Indx[Obj.GetId()]
modeDisp[idsp] = Obj.GetValue()/1000.
dispVal.SetValue(modeDisp[idsp])
err = G2mth.ApplyModeDisp(data)
if err:
G2G.G2MessageBox(G2frame,'Do Draw atoms first')
G2phsG.FindBondsDraw(data)
G2plt.PlotStructure(G2frame,data)
def OnDispVal(invalid,value,tc):
'''Respond to entry of a value into a distortion mode entry widget'''
idsp,displ = Indx[tc.GetId()]
displ.SetValue(int(value*1000))
err = G2mth.ApplyModeDisp(data)
if err:
G2G.G2MessageBox(G2frame,'Do Draw atoms first')
G2phsG.FindBondsDraw(data)
G2plt.PlotStructure(G2frame,data)
def OnRefDispl(event):
Obj = event.GetEventObject()
idsp,item = Indx[Obj.GetId()]
item[-2] = not item[-2]
def OnReset(event):
'''Reset all distortion mode values to initial values'''
ISOdata['modeDispl'] = copy.deepcopy(ISOdata['ISOmodeDispl'])
err = G2mth.ApplyModeDisp(data)
if err:
G2G.G2MessageBox(G2frame,'Do Draw atoms first')
G2phsG.FindBondsDraw(data)
G2plt.PlotStructure(G2frame,data)
UpdateISODISTORT(G2frame,data)
def OnSetZero(event):
'''Reset all distortion mode values to 0'''
ISOdata['modeDispl'] = [0.0 for i in ISOdata['ISOmodeDispl']]
err = G2mth.ApplyModeDisp(data)
if err:
G2G.G2MessageBox(G2frame,'Do Draw atoms first')
G2phsG.FindBondsDraw(data)
G2plt.PlotStructure(G2frame,data)
UpdateISODISTORT(G2frame,data)
def OnSaveModes(event):
'''Set saved distortion mode values to displayed values'''
dlg = wx.MessageDialog(G2frame,'Are you sure you want to replace the saved mode values?',
'Confirm replace',wx.YES|wx.NO)
try:
dlg.CenterOnParent()
result = dlg.ShowModal()
finally:
dlg.Destroy()
if result != wx.ID_YES: return
ISOdata['ISOmodeDispl'] = copy.deepcopy(ISOdata['modeDispl'])
G2plt.PlotStructure(G2frame,data)
UpdateISODISTORT(G2frame,data)
#### displayModes code starts here
ConstrData = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Constraints'))
pId = data['ranId']
mainSizer = wx.BoxSizer(wx.VERTICAL)
if SGLaue not in ['mmm','2/m','-1']:
mainSizer.Add(wx.StaticText(G2frame.ISODIST,label=' NB: ISODISTORT distortion mode symmetry is too high to be used in PDFfit'))
txt = wx.StaticText(G2frame.ISODIST,label=
' For use of ISODISTORT, please cite: '+
G2G.GetCite('ISOTROPY, ISODISTORT, ISOCIF...'))
txt.Wrap(500)
mainSizer.Add(txt)
mainSizer.Add(wx.StaticText(G2frame.ISODIST,label=
''' The 2nd column below shows the last saved mode values. The 3rd && 4th columns will set the
display mode values. The positions in the Atoms and Draw Atoms tabs, as well as the atom
positions shown in the Plot Window are changed to reflect the display mode values. The
range of the slider corresponds to making a maximum atomic displacement between -2 && +2 \u212B.'''))
mainSizer.Add((-1,10))
slideSizer = wx.FlexGridSizer(0,5,0,0)
modeDisp = ISOdata['modeDispl']
idsp = 0
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label='Name'),0,wx.ALIGN_CENTER)
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label='Save value'))
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label='Value'),0,wx.ALIGN_CENTER)
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label='Refine?'),0,wx.ALIGN_CENTER)
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label='Atom displacements'),0,wx.EXPAND|wx.LEFT,15)
isoDict = {i.name:j for (i,j) in zip(data['ISODISTORT']['G2ModeList'],data['ISODISTORT']['IsoModeList'])}
for item in ConstrData['Phase']:
if item[-1] != 'f': continue # only want new vars
if item[-3] is None: continue # unnamed new var is not ISO
try:
if pId != item[-3].phase: continue # at present only ISO modes are associated with a phase
except AttributeError:
continue
if item[-3].name not in isoDict: continue
isoName = item[-3].varname().split('::')[1]
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label=isoName),0,WACV)
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label=' %.5g '%ISOdata['ISOmodeDispl'][idsp],
style=wx.ALIGN_CENTER_HORIZONTAL),0,WACV|wx.EXPAND)
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
dispVal = G2G.ValidatedTxtCtrl(G2frame.ISODIST,modeDisp,idsp,xmin=-2.,xmax=2.,size=(75,20),OnLeave=OnDispVal)
lineSizer.Add(dispVal,0,WACV)
displ = G2G.G2Slider(G2frame.ISODIST,style=wx.SL_HORIZONTAL,minValue=-2000,maxValue=2000,
value=int(modeDisp[idsp]*1000),size=(250,20))
displ.Bind(wx.EVT_SLIDER, OnDispl)
Indx[displ.GetId()] = [idsp,dispVal]
Indx[dispVal.GetId()] = [idsp,displ]
lineSizer.Add(displ)
slideSizer.Add(lineSizer)
refDispl = wx.CheckBox(G2frame.ISODIST)
refDispl.SetValue(item[-2])
refDispl.Bind(wx.EVT_CHECKBOX,OnRefDispl)
Indx[refDispl.GetId()] = [idsp,item]
slideSizer.Add(refDispl,0,WACV|wx.EXPAND|wx.LEFT,15)
slideSizer.Add(wx.StaticText(G2frame.ISODIST,label=', '.join(ModeDispList[idsp])),0,wx.EXPAND|wx.LEFT,15)
idsp += 1
slideSizer.SetMinSize(wx.Size(650,10))
mainSizer.Add(slideSizer)
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
reset = wx.Button(G2frame.ISODIST,label='Reset modes to save values')
reset.Bind(wx.EVT_BUTTON,OnReset)
lineSizer.Add(reset,0,WACV)
reset = wx.Button(G2frame.ISODIST,label='Set all modes to zero')
reset.Bind(wx.EVT_BUTTON,OnSetZero)
lineSizer.Add(reset,0,wx.ALL,10)
reset = wx.Button(G2frame.ISODIST,label='Save mode values')
reset.Bind(wx.EVT_BUTTON,OnSaveModes)
lineSizer.Add(reset,0,WACV)
mainSizer.Add(lineSizer,0,wx.TOP,5)
mainSizer.Layout()
G2phsG.SetPhaseWindow(G2frame.ISODIST,mainSizer,Scroll=Scroll)
#### UpdateISODISTORT code starts here
topSizer = G2frame.dataWindow.topBox
topSizer.Clear(True)
parent = G2frame.dataWindow.topPanel
lbl= f"ISODISTORT distortion modes for {data['General']['Name']!r}"[:60]
topSizer.Add(wx.StaticText(parent,label=lbl),0,WACV)
topSizer.Add((-1,-1),1,wx.EXPAND)
topSizer.Add(G2G.HelpButton(parent,helpIndex=G2frame.dataWindow.helpKey))
wx.CallAfter(G2frame.dataWindow.SetDataSize)
Indx = {}
ISOdata = data['ISODISTORT']
SGLaue = data['General']['SGData']['SGLaue']
G2frame.dataWindow.ISODDataEdit.Enable(G2G.wxID_ISODNEWPHASE,'rundata' in ISOdata)
G2frame.dataWindow.ISODDataEdit.Enable(G2G.wxID_ISOPDFFIT,(('G2VarList' in ISOdata) and (SGLaue in ['mmm','2/m','-1'])))
G2frame.dataWindow.ISODDataEdit.Enable(G2G.wxID_SHOWISO1,('G2VarList' in ISOdata)
or ('G2OccVarList' in ISOdata))
G2frame.dataWindow.ISODDataEdit.Enable(G2G.wxID_SHOWISOMODES,('G2VarList' in ISOdata))
if G2frame.ISODIST.GetSizer():
G2frame.ISODIST.GetSizer().Clear(True)
if 'G2ModeList' in ISOdata: #invoked only if phase is from a ISODISTORT cif file & thus contains distortion mode constraints
# #patch
# if 'modeDispl' not in ISOdata:
# ISOdata['modeDispl'] = np.zeros(len(ISOdata['G2ModeList']))
# #end patch
ModeDispList = G2pwd.GetAtmDispList(ISOdata)
displayModes()
return
#initialization
if 'ParentCIF' not in ISOdata:
ISOdata.update({'ParentCIF':'Select','ChildCIF':'Select','ISOmethod':4,
'ChildMatrix':np.eye(3),'ChildSprGp':'P 1','ChildCell':'abc',}) #these last 3 currently unused
#end initialization
mainSizer = wx.BoxSizer(wx.VERTICAL)
txt = wx.StaticText(G2frame.ISODIST,label=
' For use of ISODISTORT, please cite: '+
G2G.GetCite('ISOTROPY, ISODISTORT, ISOCIF...'))
txt.Wrap(500)
mainSizer.Add(txt)
mainSizer.Add((-1,5))
G2G.HorizontalLine(mainSizer,G2frame.ISODIST)
mainSizer.Add((-1,5))
mainSizer.Add(displaySetup())
if 'radio' in ISOdata:
mainSizer.Add(displaySubset())
mainSizer.Add(displayRadio())
G2phsG.SetPhaseWindow(G2frame.ISODIST,mainSizer,Scroll=Scroll)
#### UpdateLayerData GUI for DIFFax Layer Data ################################################################################
[docs]
def UpdateLayerData(G2frame,data,Scroll=0):
'''Present the contents of the Phase/Layers tab for stacking fault simulation
'''
laueChoice = ['-1','2/m(ab)','2/m(c)','mmm','-3','-3m','4/m','4/mmm',
'6/m','6/mmm','unknown']
colLabels = ['Name','Type','x','y','z','frac','Uiso']
transLabels = ['Prob','Dx','Dy','Dz','refine','plot']
colTypes = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]+ \
3*[wg.GRID_VALUE_FLOAT+':10,5',]+2*[wg.GRID_VALUE_FLOAT+':10,4',] #x,y,z,frac,Uiso
transTypes = [wg.GRID_VALUE_FLOAT+':10,3',]+3*[wg.GRID_VALUE_FLOAT+':10,5',]+ \
[wg.GRID_VALUE_CHOICE+": ,P,Dx,Dy,Dz,Dxy,Dxz,Dyz,Dxyz",wg.GRID_VALUE_BOOL,]
plotDefaults = {'oldxy':[0.,0.],'Quaternion':[0.,0.,0.,1.],'cameraPos':30.,'viewDir':[0,0,1],
'viewPoint':[[0.,0.,0.],[]],}
Indx = {}
def OnLaue(event):
Obj = event.GetEventObject()
data['Layers']['Laue'] = Obj.GetValue()
wx.CallAfter(UpdateLayerData,G2frame,data)
def OnSadpPlot(event):
sadpPlot.SetValue(False)
labels = Layers['Sadp']['Plane']
lmax = float(Layers['Sadp']['Lmax'])
XY = 2*lmax*np.mgrid[0:256:256j,0:256:256j]/256.-lmax
G2frame.Cmax = 1.0
G2plt.PlotXYZ(G2frame,XY,Layers['Sadp']['Img'].T,labelX=labels[:-1],
labelY=labels[-1],newPlot=False,Title=Layers['Sadp']['Plane'])
def OnSeqPlot(event):
seqPlot.SetValue(False)
resultXY,resultXY2,seqNames = Layers['seqResults']
pName = Layers['seqCodes'][0]
G2plt.PlotXY(G2frame,resultXY,XY2=resultXY2,labelX=r'$\mathsf{2\theta}$',
labelY='Intensity',newPlot=True,Title='Sequential simulations on '+pName,
lines=True,names=seqNames)
def CellSizer():
cellGUIlist = [
[['-3','-3m','6/m','6/mmm','4/m','4/mmm'],6,zip([" a = "," c = "],["%.5f","%.5f",],[True,True],[0,2])],
[['mmm'],8,zip([" a = "," b = "," c = "],["%.5f","%.5f","%.5f"],[True,True,True],[0,1,2,])],
[['2/m(ab)','2/m(c)','-1','axial','unknown'],10,zip([" a = "," b = "," c = "," gamma = "],
["%.5f","%.5f","%.5f","%.3f"],[True,True,True,True],[0,1,2,5])]]
def OnCellRef(event):
data['Layers']['Cell'][0] = cellRef.GetValue()
def OnCellChange(event):
event.Skip()
laue = data['Layers']['Laue']
cell = data['Layers']['Cell']
Obj = event.GetEventObject()
ObjId = cellList.index(Obj.GetId())
try:
value = max(1.0,float(Obj.GetValue()))
except ValueError:
if ObjId < 3: #bad cell edge - reset
value = cell[ObjId+1]
else: #bad angle
value = 90.
if laue in ['-3','-3m','6/m','6/mmm','4/m','4/mmm']:
cell[4] = cell[5] = 90.
cell[6] = 120.
if laue in ['4/m','4/mmm']:
cell[6] = 90.
if ObjId == 0:
cell[1] = cell[2] = value
Obj.SetValue("%.5f"%(cell[1]))
else:
cell[3] = value
Obj.SetValue("%.5f"%(cell[3]))
elif laue in ['mmm']:
cell[ObjId+1] = value
cell[4] = cell[5] = cell[6] = 90.
Obj.SetValue("%.5f"%(cell[ObjId+1]))
elif laue in ['2/m','-1']:
cell[4] = cell[5] = 90.
if ObjId != 3:
cell[ObjId+1] = value
Obj.SetValue("%.5f"%(cell[ObjId+1]))
else:
cell[6] = value
Obj.SetValue("%.3f"%(cell[6]))
cell[7] = G2lat.calc_V(G2lat.cell2A(cell[1:7]))
volVal.SetLabel(' Vol = %.3f'%(cell[7]))
cell = data['Layers']['Cell']
laue = data['Layers']['Laue']
for cellGUI in cellGUIlist:
if laue in cellGUI[0]:
useGUI = cellGUI
cellSizer = wx.FlexGridSizer(0,useGUI[1]+1,5,5)
cellRef = wx.CheckBox(layerData,-1,label='Refine unit cell:')
cellSizer.Add(cellRef,0,WACV)
cellRef.Bind(wx.EVT_CHECKBOX, OnCellRef)
cellRef.SetValue(cell[0])
cellList = []
for txt,fmt,ifEdit,Id in useGUI[2]:
cellSizer.Add(wx.StaticText(layerData,label=txt),0,WACV)
# Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0)
cellVal = wx.TextCtrl(layerData,value=(fmt%(cell[Id+1])),
style=wx.TE_PROCESS_ENTER)
cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)
cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
cellSizer.Add(cellVal,0,WACV)
cellList.append(cellVal.GetId())
volVal = wx.StaticText(layerData,label=' Vol = %.3f'%(cell[7]))
cellSizer.Add(volVal,0,WACV)
return cellSizer
def WidthSizer():
def OnRefWidth(event):
Id = Indx[event.GetEventObject()]
Layers['Width'][1][Id] = not Layers['Width'][1][Id]
Labels = ['a','b']
flags = Layers['Width'][1]
widthSizer = wx.BoxSizer(wx.HORIZONTAL)
for i in range(2):
widthSizer.Add(wx.StaticText(layerData,label=' layer width(%s) (<= 1\xb5m): '%(Labels[i])),0,WACV)
widthVal = G2G.ValidatedTxtCtrl(layerData,Layers['Width'][0],i,nDig=(10,3),xmin=0.005,xmax=1.0)
widthSizer.Add(widthVal,0,WACV)
widthRef = wx.CheckBox(layerData,label='Refine?')
widthRef.SetValue(flags[i])
Indx[widthRef] = i
widthRef.Bind(wx.EVT_CHECKBOX, OnRefWidth)
widthSizer.Add(widthRef,0,WACV)
return widthSizer
def OnNewLayer(event):
data['Layers']['Layers'].append({'Name':'Unk','SameAs':'','Symm':'None','Atoms':[]})
Trans = data['Layers']['Transitions']
if len(Trans):
Trans.append([[0.,0.,0.,0.,'',False] for trans in Trans])
for trans in Trans:
trans.append([0.,0.,0.,0.,'',False])
else:
Trans = [[[1.,0.,0.,0.,'',False],],]
data['Layers']['Transitions'] = Trans
wx.CallLater(100,UpdateLayerData,G2frame,data)
def OnDeleteLast(event):
del(data['Layers']['Layers'][-1])
del(data['Layers']['Transitions'][-1])
for trans in data['Layers']['Transitions']:
del trans[-1]
wx.CallAfter(UpdateLayerData,G2frame,data)
def OnImportLayer(event):
dlg = wx.FileDialog(G2frame, 'Choose GSAS-II project file', G2G.GetImportPath(G2frame),
wildcard='GSAS-II project file (*.gpx)|*.gpx',style=wx.FD_OPEN| wx.FD_CHANGE_DIR)
try:
if dlg.ShowModal() == wx.ID_OK:
GPXFile = dlg.GetPath()
phaseNames = G2stIO.GetPhaseNames(GPXFile)
else:
return
finally:
dlg.Destroy()
dlg = wx.SingleChoiceDialog(G2frame,'Phase to use for layer','Select',phaseNames)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
PhaseName = phaseNames[sel]
else:
return
Phase = G2stIO.GetAllPhaseData(GPXFile,PhaseName)
#need cell compatibility check here
Layer = {'Name':Phase['General']['Name'],'SameAs':'','Symm':'None'}
cx,ct,cs,cia = Phase['General']['AtomPtrs']
atoms = Phase['Atoms']
Atoms = []
for atom in atoms:
x,y,z,f = atom[cx:cx+4]
u = atom[cia+1]
if not u: u = 0.01
Atoms.append([atom[ct-1],atom[ct],x,y,z,f,u])
if atom[ct] not in data['Layers']['AtInfo']:
data['Layers']['AtInfo'][atom[ct]] = G2elem.GetAtomInfo(atom[ct])
Layer['Atoms'] = Atoms
data['Layers']['Layers'].append(Layer)
Trans = data['Layers']['Transitions']
if len(Trans):
Trans.append([[0.,0.,0.,0.,'',False] for trans in Trans])
for trans in Trans:
trans.append([0.,0.,0.,0.,'',False])
else:
Trans = [[[1.,0.,0.,0.,'',False],],]
data['Layers']['Transitions'] = Trans
wx.CallAfter(UpdateLayerData,G2frame,data)
def LayerSizer(il,Layer):
# def OnNameChange(event):
# event.Skip()
# Layer['Name'] = layerName.GetValue()
# wx.CallLater(100,UpdateLayerData,G2frame,data)
def OnAddAtom(event):
Layer['Atoms'].append(['Unk','Unk',0.,0.,0.,1.,0.01])
wx.CallAfter(UpdateLayerData,G2frame,data)
def OnSymm(event):
Layer['Symm'] = symm.GetValue()
def AtomTypeSelect(event):
r,c = event.GetRow(),event.GetCol()
if atomGrid.GetColLabelValue(c) == 'Type':
PE = G2elemGUI.PickElement(G2frame)
if PE.ShowModal() == wx.ID_OK:
if PE.Elem != 'None':
atType = PE.Elem.strip()
Layer['Atoms'][r][c] = atType
name = Layer['Atoms'][r][c]
if len(name) in [2,4]:
Layer['Atoms'][r][c-1] = name[:2]+'%d'%(r+1)
else:
Layer['Atoms'][r][c-1] = name[:1]+'%d'%(r+1)
if atType not in data['Layers']['AtInfo']:
data['Layers']['AtInfo'][atType] = G2elem.GetAtomInfo(atType)
PE.Destroy()
wx.CallAfter(UpdateLayerData,G2frame,data)
else:
event.Skip()
def OnDrawLayer(event):
drawLayer.SetValue(False)
G2plt.PlotLayers(G2frame,Layers,[il,],plotDefaults,firstCall=True)
def OnSameAs(event):
Layer['SameAs'] = sameas.GetValue()
wx.CallLater(100,UpdateLayerData,G2frame,data)
layerSizer = wx.BoxSizer(wx.VERTICAL)
nameSizer = wx.BoxSizer(wx.HORIZONTAL)
nameSizer.Add(wx.StaticText(layerData,label=' Layer name: '),0,WACV)
layerName = G2G.ValidatedTxtCtrl(layerData,Layer,'Name')
# layerName = wx.TextCtrl(layerData,value=Layer['Name'],style=wx.TE_PROCESS_ENTER)
# layerName.Bind(wx.EVT_TEXT_ENTER,OnNameChange)
# layerName.Bind(wx.EVT_KILL_FOCUS,OnNameChange)
# layerName.Bind(wx.EVT_LEAVE_WINDOW,OnNameChange)
nameSizer.Add(layerName,0,WACV)
if il:
nameSizer.Add(wx.StaticText(layerData,label=' Same as: '),0,WACV)
sameas = wx.ComboBox(layerData,value=Layer['SameAs'],choices=['',]+layerNames[:-1],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
sameas.Bind(wx.EVT_COMBOBOX, OnSameAs)
nameSizer.Add(sameas,0,WACV)
if Layer['SameAs']:
indx = layerNames.index(Layer['SameAs'])
if indx < il: #previously used : same layer
layerSizer.Add(nameSizer)
return layerSizer
nameSizer.Add(wx.StaticText(layerData,label=' Layer symmetry: '),0,WACV)
symmChoice = ['-1','None']
symm = wx.ComboBox(layerData,value=Layer['Symm'],choices=symmChoice,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
symm.Bind(wx.EVT_COMBOBOX,OnSymm)
nameSizer.Add(symm,0,WACV)
addAtom = wx.CheckBox(layerData,label=' Add atom? ')
addAtom.Bind(wx.EVT_CHECKBOX, OnAddAtom)
nameSizer.Add(addAtom,0,WACV)
drawLayer = wx.CheckBox(layerData,label=' Draw layer? ')
drawLayer.Bind(wx.EVT_CHECKBOX, OnDrawLayer)
nameSizer.Add(drawLayer,0,WACV)
layerSizer.Add(nameSizer)
table = []
rowLabels = []
for i,atom in enumerate(Layer['Atoms']):
table.append(atom)
rowLabels.append(str(i))
atomTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=colTypes)
atomGrid = G2G.GSGrid(layerData)
atomGrid.SetTable(atomTable,True,useFracEdit=False)
# atomGrid.SetScrollRate(0,0) #get rid of automatic scroll bars
# loop over all cols in table, set cell editor for numerical items
for c,t in enumerate(colTypes):
if not t.startswith(wg.GRID_VALUE_FLOAT): continue
attr = wx.grid.GridCellAttr()
attr.IncRef() #fix from Jim Hester
attr.SetEditor(G2G.GridFractionEditor(atomGrid))
atomGrid.SetColAttr(c, attr)
for row,atom in enumerate(Layer['Atoms']):
atomGrid.SetReadOnly(row,1,True)
atomGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, AtomTypeSelect)
atomGrid.AutoSizeColumns(True)
layerSizer.Add(atomGrid)
return layerSizer
def TransSizer():
def PlotSelect(event):
Obj = event.GetEventObject()
Yi = Indx[Obj.GetId()]
Xi,c = event.GetRow(),event.GetCol()
if Xi >= 0 and c == 5: #plot column
G2plt.PlotLayers(G2frame,Layers,[Yi,Xi,],plotDefaults,firstCall=True)
else:
Psum = 0.
for Xi in range(len(transArray)):
Psum += transArray[Xi][Xi][0]
Psum /= len(transArray)
totalFault.SetLabel(' Total fault density = %.3f'%(1.-Psum))
event.Skip()
def OnNormProb(event):
for Yi,Yname in enumerate(Names):
Psum = 0.
for Xi,Xname in enumerate(Names):
Psum += transArray[Yi][Xi][0]
if not Psum:
transArray[Yi][0][0] = 1.0
Psum = 1.0
for Xi,Xname in enumerate(Names):
transArray[Yi][Xi][0] /= Psum
wx.CallAfter(UpdateLayerData,G2frame,data)
def OnSymProb(event):
if symprob.GetValue():
Nx = len(Names)-1
Layers['SymTrans'] = True
for Yi,Yname in enumerate(Names):
for Xi,Xname in enumerate(Names):
if transArray[Nx-Yi][Nx-Xi][0] != transArray[Yi][Xi][0]:
Layers['SymTrans'] = False
symprob.SetValue(False)
wx.MessageBox('%s-%s not equal %s-%s'%(Yname,Xname,Xname,Yname),
caption='Probability symmetry error',style=wx.ICON_EXCLAMATION)
break
else:
Layers['SymTrans'] = False
transSizer = wx.BoxSizer(wx.VERTICAL)
transSizer.Add(wx.StaticText(layerData,label=' Layer-Layer transition probabilities: '),0)
topSizer = wx.BoxSizer(wx.HORIZONTAL)
normprob = wx.CheckBox(layerData,label=' Normalize probabilities?')
normprob.Bind(wx.EVT_CHECKBOX,OnNormProb)
topSizer.Add(normprob,0,WACV)
symprob = wx.CheckBox(layerData,label=' Symmetric probabilities?')
symprob.SetValue(Layers.get('SymTrans',False))
symprob.Bind(wx.EVT_CHECKBOX,OnSymProb)
topSizer.Add(symprob,0,WACV)
transSizer.Add(topSizer,0)
Names = [layer['Name'] for layer in Layers['Layers']]
transArray = Layers['Transitions']
layerData.transGrids = []
if not Names or not transArray:
return transSizer
diagSum = 0.
for Yi,Yname in enumerate(Names):
transSizer.Add(wx.StaticText(layerData,label=' From %s to:'%(Yname)),0)
table = []
rowLabels = []
diagSum += transArray[Yi][Yi][0]
for Xi,Xname in enumerate(Names):
table.append(transArray[Yi][Xi])
rowLabels.append(Xname)
if transArray[Yi][Xi][0] > 0.:
Layers['allowedTrans'].append([str(Yi+1),str(Xi+1)])
transTable = G2G.Table(table,rowLabels=rowLabels,colLabels=transLabels,types=transTypes)
transGrid = G2G.GSGrid(layerData)
transGrid.SetTable(transTable,True,useFracEdit=False)
# transGrid.SetScrollRate(0,0) #get rid of automatic scroll bars
Indx[transGrid.GetId()] = Yi
for c,t in enumerate(transTypes):
if not t.startswith(wg.GRID_VALUE_FLOAT): continue
attr = wx.grid.GridCellAttr()
attr.IncRef() #fix from Jim Hester
attr.SetEditor(G2G.GridFractionEditor(transGrid))
transGrid.SetColAttr(c, attr)
transGrid.Bind(wg.EVT_GRID_CELL_LEFT_CLICK, PlotSelect)
transGrid.AutoSizeColumns(True)
transSizer.Add(transGrid)
layerData.transGrids.append(transGrid)
if len(transArray):
diagSum /= len(transArray)
totalFault = wx.StaticText(layerData,
label=' Total fault density = %.3f'%(1.-diagSum))
transSizer.Add(totalFault,0)
return transSizer
def PlotSizer():
def OnPlotSeq(event):
event.Skip()
vals = plotSeq.GetValue().split()
try:
vals = [int(val)-1 for val in vals]
if not all([0 <= val < len(Names) for val in vals]):
raise ValueError
except ValueError:
plotSeq.SetValue('Error in string '+plotSeq.GetValue())
return
G2plt.PlotLayers(G2frame,Layers,vals,plotDefaults,firstCall=True)
Names = [' %s: %d,'%(layer['Name'],iL+1) for iL,layer in enumerate(Layers['Layers'])]
plotSizer = wx.BoxSizer(wx.VERTICAL)
Str = ' Using sequence nos. from:'
for name in Names:
Str += name
plotSizer.Add(wx.StaticText(layerData,label=Str[:-1]),0)
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
lineSizer.Add(wx.StaticText(layerData,label=' Enter sequence of layers to plot:'),0,WACV)
# Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0)
plotSeq = wx.TextCtrl(layerData,value = '',style=wx.TE_PROCESS_ENTER)
plotSeq.Bind(wx.EVT_TEXT_ENTER,OnPlotSeq)
plotSeq.Bind(wx.EVT_KILL_FOCUS,OnPlotSeq)
lineSizer.Add(plotSeq,0,WACV)
plotSizer.Add(lineSizer,0)
return plotSizer
def StackSizer():
stackChoice = ['recursive','explicit',]
seqChoice = ['random','list',]
def OnStackType(event):
newType = stackType.GetValue()
if newType == data['Layers']['Stacking'][0]:
return
data['Layers']['Stacking'][0] = newType
if newType == 'recursive':
data['Layers']['Stacking'][1] = 'infinite'
else: #explicit
data['Layers']['Stacking'][1] = 'random'
data['Layers']['Stacking'][2] = '250'
wx.CallAfter(UpdateLayerData,G2frame,data)
def OnSeqType(event):
newType = seqType.GetValue()
if newType == data['Layers']['Stacking'][1]:
return
data['Layers']['Stacking'][1] = newType
if newType == 'random':
data['Layers']['Stacking'][2] = '250'
else: #List
data['Layers']['Stacking'][2] = ''
wx.CallAfter(UpdateLayerData,G2frame,data)
def OnNumLayers(event):
event.Skip()
val = numLayers.GetValue()
if val == 'infinite':
data['Layers']['Stacking'][1] = val
else:
try:
if 0 < int(val) < 1023:
data['Layers']['Stacking'][1] = val
else:
data['Layers']['Stacking'][1] = 'infinite'
except ValueError:
pass
numLayers.SetValue(data['Layers']['Stacking'][1])
def OnNumRan(event):
event.Skip()
val = numRan.GetValue()
try:
if 0 > int(val) > 1022:
raise ValueError
else:
data['Layers']['Stacking'][2] = val
except ValueError:
val = data['Layers']['Stacking'][2]
numRan.SetValue(val)
def OnStackList(event):
event.Skip()
stack = stackList.GetValue()
stack = stack.replace('\n',' ').strip().strip('\n')
nstar = stack.count('*')
if nstar:
try:
newstack = ''
Istar = 0
for star in range(nstar):
Istar = stack.index('*',Istar+1)
iB = stack[:Istar].rfind(' ')
if iB == -1:
mult = int(stack[:Istar])
else:
mult = int(stack[iB:Istar])
pattern = stack[Istar+2:stack.index(')',Istar)]+' '
newstack += mult*pattern
stack = newstack
except ValueError:
stack += ' Error in string'
Slist = stack.split()
if len(Slist) < 2:
stack = 'Error in sequence - too short!'
OKlist = [Slist[i:i+2] in Layers['allowedTrans'] for i in range(len(Slist[:-1]))]
if all(OKlist):
data['Layers']['Stacking'][2] = stack
else:
stack = 'Improbable sequence or bad string'
stackList.SetValue(stack)
stackSizer = wx.BoxSizer(wx.VERTICAL)
stackSizer.Add(wx.StaticText(layerData,label=' Layer stacking parameters:'),0)
if not Layers['Stacking']:
Layers['Stacking'] = ['recursive','infinite','']
topLine = wx.BoxSizer(wx.HORIZONTAL)
topLine.Add(wx.StaticText(layerData,label=' Stacking type: '),0,WACV)
stackType = wx.ComboBox(layerData,value=Layers['Stacking'][0],choices=stackChoice,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
stackType.Bind(wx.EVT_COMBOBOX,OnStackType)
topLine.Add(stackType,0,WACV)
if Layers['Stacking'][0] == 'recursive':
topLine.Add(wx.StaticText(layerData,label=' number of layers (<1022 or "infinite"): '),0,WACV)
# Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0)
numLayers = wx.TextCtrl(layerData,value=data['Layers']['Stacking'][1],style=wx.TE_PROCESS_ENTER)
numLayers.Bind(wx.EVT_TEXT_ENTER,OnNumLayers)
numLayers.Bind(wx.EVT_KILL_FOCUS,OnNumLayers)
topLine.Add(numLayers,0,WACV)
stackSizer.Add(topLine)
elif Layers['Stacking'][0] == 'explicit':
topLine.Add(wx.StaticText(layerData,label=' layer sequence: '),0,WACV)
seqType = wx.ComboBox(layerData,value=data['Layers']['Stacking'][1],choices=seqChoice,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
seqType.Bind(wx.EVT_COMBOBOX,OnSeqType)
topLine.Add(seqType,0,WACV)
if Layers['Stacking'][1] == 'list':
stackSizer.Add(topLine,0)
Names = [' %s: %d,'%(layer['Name'],iL+1) for iL,layer in enumerate(Layers['Layers'])]
stackSizer.Add(wx.StaticText(layerData,label=' Explicit layer sequence; enter space delimited list of numbers:'),0)
Str = ' Use sequence nos. from:'
for name in Names:
Str += name
stackSizer.Add(wx.StaticText(layerData,label=Str[:-1]+' Repeat sequences can be used: e.g. 6*(1 2) '),0)
stackSizer.Add(wx.StaticText(layerData,label=' Zero probability sequences not allowed'),0)
stackList = wx.TextCtrl(layerData,value=Layers['Stacking'][2],size=(600,-1),
style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER)
stackList.Bind(wx.EVT_TEXT_ENTER,OnStackList)
stackList.Bind(wx.EVT_KILL_FOCUS,OnStackList)
stackSizer.Add(stackList,0,wx.ALL|wx.EXPAND,8)
else: #random
topLine.Add(wx.StaticText(layerData,label=' Length of random sequence: '),0,WACV)
# Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0)
numRan = wx.TextCtrl(layerData,value=Layers['Stacking'][2],style=wx.TE_PROCESS_ENTER)
numRan.Bind(wx.EVT_TEXT_ENTER,OnNumRan)
numRan.Bind(wx.EVT_KILL_FOCUS,OnNumRan)
topLine.Add(numRan,0,WACV)
stackSizer.Add(topLine,0)
return stackSizer
Layers = data['Layers']
layerNames = []
Layers['allowedTrans'] = []
if len(Layers['Layers']):
layerNames = [layer['Name'] for layer in Layers['Layers']]
G2frame.GetStatusBar().SetStatusText('',1)
layerData = G2frame.layerData
try:
if layerData.GetSizer():
layerData.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
topSizer = wx.BoxSizer(wx.VERTICAL)
bottomSizer = wx.BoxSizer(wx.VERTICAL)
headSizer = wx.BoxSizer(wx.HORIZONTAL)
headSizer.Add(wx.StaticText(layerData,label=' Global layer description: '),0,WACV)
if 'Sadp' in Layers:
sadpPlot = wx.CheckBox(layerData,label=' Plot selected area diffraction?')
sadpPlot.Bind(wx.EVT_CHECKBOX,OnSadpPlot)
headSizer.Add(sadpPlot,0,WACV)
if 'seqResults' in Layers:
seqPlot = wx.CheckBox(layerData,label=' Plot sequential result?')
seqPlot.Bind(wx.EVT_CHECKBOX,OnSeqPlot)
headSizer.Add(seqPlot,0,WACV)
topSizer.Add(headSizer)
laueSizer = wx.BoxSizer(wx.HORIZONTAL)
laueSizer.Add(wx.StaticText(layerData,label=' Diffraction Laue symmetry:'),0,WACV)
laue = wx.ComboBox(layerData,value=Layers['Laue'],choices=laueChoice,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
laue.Bind(wx.EVT_COMBOBOX,OnLaue)
laueSizer.Add(laue,0,WACV)
if Layers['Laue'] == 'unknown':
laueSizer.Add(wx.StaticText(layerData,label=' Diffraction symmetry tolerance: '),0,WACV)
toler = G2G.ValidatedTxtCtrl(layerData,Layers,'Toler',nDig=(10,3))
laueSizer.Add(toler,0,WACV)
topSizer.Add(laueSizer,0)
topSizer.Add(wx.StaticText(layerData,label=' Reference unit cell for all layers:'),0)
topSizer.Add(CellSizer(),0)
topSizer.Add(WidthSizer())
topSizer.Add(wx.StaticText(layerData,label=' NB: stacking fault refinement currently not available'),0)
G2G.HorizontalLine(topSizer,layerData)
titleSizer = wx.BoxSizer(wx.HORIZONTAL)
titleSizer.Add(wx.StaticText(layerData,label=' Layer descriptions: '),0,WACV)
newLayer = wx.Button(layerData,label='Add new layer')
newLayer.Bind(wx.EVT_BUTTON, OnNewLayer)
titleSizer.Add(newLayer,0,WACV)
importLayer = wx.Button(layerData,label=' Import new layer')
importLayer.Bind(wx.EVT_BUTTON, OnImportLayer)
titleSizer.Add(importLayer,0,WACV)
deleteLast = wx.Button(layerData,label='Delete last layer')
deleteLast.Bind(wx.EVT_BUTTON, OnDeleteLast)
titleSizer.Add(deleteLast,0,WACV)
topSizer.Add(titleSizer,0)
for il,layer in enumerate(Layers['Layers']):
topSizer.Add(LayerSizer(il,layer))
G2G.HorizontalLine(topSizer,layerData)
mainSizer.Add(topSizer)
bottomSizer.Add(TransSizer())
G2G.HorizontalLine(bottomSizer,layerData)
bottomSizer.Add(PlotSizer(),0)
G2G.HorizontalLine(bottomSizer,layerData)
bottomSizer.Add(StackSizer())
mainSizer.Add(bottomSizer)
G2phsG.SetPhaseWindow(G2frame.layerData,mainSizer,Scroll=Scroll)
#### UpdateTexture GUI
def UpdateTexture(G2frame,data):
def SetSHCoef():
cofNames = G2lat.GenSHCoeffT(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
SHCoeff = textureData['SH Coeff'][1]
for cofName in SHCoeff:
if cofName in cofNames:
newSHCoef[cofName] = SHCoeff[cofName]
return newSHCoef
def OnShOrder(event):
Obj = event.GetEventObject()
# the Kaduk test: is Texture appropriate? Look for a 2nd histogram
# of any type with differing setting angles from the 1st.
instArray = {}
if int(Obj.GetValue()) > 0:
for h in data['Histograms']:
PatternId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,h)
if not PatternId: #skip bogus histograms
continue
Inst = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,PatternId,'Instrument Parameters'))[0]
Sample = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,PatternId,'Sample Parameters'))
if Inst['Type'][1] in instArray:
if instArray[Inst['Type'][1]] != [Sample['Chi'],Sample['Phi'],Sample['Omega']]:
textureData['Order'] = int(Obj.GetValue())
break
else:
instArray[Inst['Type'][1]] = [Sample['Chi'],Sample['Phi'],Sample['Omega']]
else:
if textureData['Model'] != 'cylindrical':
textureData['Order'] = 0
wx.MessageBox('Incorrect use of Texture. Use preferred orientation (on data tab) unless you have multiple histograms taken with different orientations',
caption='Texture Error',style=wx.ICON_EXCLAMATION)
else:
textureData['Order'] = int(Obj.GetValue())
else:
textureData['Order'] = 0
textureData['SH Coeff'][1] = SetSHCoef()
G2frame.GPXtree.UpdateSelection()
# wx.CallLater(100,UpdateTexture)
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnShModel(event):
Obj = event.GetEventObject()
textureData['Model'] = Obj.GetValue()
textureData['SH Coeff'][1] = SetSHCoef()
G2frame.GPXtree.UpdateSelection()
# wx.CallLater(100,UpdateTexture)
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnSHRefine(event):
Obj = event.GetEventObject()
textureData['SH Coeff'][0] = Obj.GetValue()
def OnSHShow(event):
Obj = event.GetEventObject()
textureData['SHShow'] = Obj.GetValue()
G2frame.GPXtree.UpdateSelection()
# wx.CallLater(100,UpdateTexture)
def OnProjSel(event):
Obj = event.GetEventObject()
G2frame.Projection = Obj.GetValue()
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnShoDet(event):
Obj = event.GetEventObject()
textureData['ShoDet'] = Obj.GetValue()
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnColorSel(event):
Obj = event.GetEventObject()
G2frame.ContourColor = Obj.GetValue()
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnAngRef(event):
Obj = event.GetEventObject()
textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
def OnODFValue(invalid,value,tc):
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnPfType(event):
Obj = event.GetEventObject()
textureData['PlotType'] = Obj.GetValue()
G2frame.GPXtree.UpdateSelection()
# wx.CallLater(100,UpdateTexture)
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnPFValue(event):
event.Skip()
Obj = event.GetEventObject()
Saxis = Obj.GetValue().split()
if textureData['PlotType'] in ['Pole figure','Axial pole distribution','3D pole distribution']:
try:
hkl = [int(Saxis[i]) for i in range(3)]
except (ValueError,IndexError):
hkl = textureData['PFhkl']
if not np.any(np.array(hkl)): #can't be all zeros!
hkl = textureData['PFhkl']
Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
textureData['PFhkl'] = hkl
else:
try:
xyz = [float(Saxis[i]) for i in range(3)]
except (ValueError,IndexError):
xyz = textureData['PFxyz']
if not np.any(np.array(xyz)): #can't be all zeros!
xyz = textureData['PFxyz']
Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
textureData['PFxyz'] = xyz
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
def OnpopLA(event):
pfName = PhaseName
cell = generalData['Cell'][1:7]
PH = np.array(textureData['PFhkl'])
phi,beta = G2lat.CrsAng(PH,cell,SGData)
SHCoef = textureData['SH Coeff'][1]
ODFln = G2lat.Flnh(SHCoef,phi,beta,SGData)
pfName = PhaseName+'%d%d%d.gpf'%(PH[0],PH[1],PH[2])
pth = G2G.GetExportPath(G2frame)
dlg = wx.FileDialog(G2frame, 'Choose popLA pole figure file name', pth, pfName,
'popLA file (*.gpf)|*.gpf',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
try:
if dlg.ShowModal() == wx.ID_OK:
pfFile = dlg.GetPath()
finally:
dlg.Destroy()
print ('popLA save '+pfFile)
if pfFile:
pf = open(pfFile,'w')
pf.write(PhaseName+'\n')
str = ' %d%d%d 5.0 90.0 5.0360.0 1 1 2 1 3 100 1'%(PH[0],PH[1],PH[2])
pf.write(str+'\n')
Psi,Gam = np.mgrid[0:19,0:72]
Psi = Psi.flatten()*5.
Gam = Gam.flatten()*5.
Z = np.array(G2lat.polfcal(ODFln,SamSym[textureData['Model']],Psi,Gam)*100.,dtype='int')
Z = np.where(Z>0,Z,0)
Z = np.where(Z<9999,Z,9999)
for i in range(76):
iBeg = i*18
iFin = iBeg+18
np.savetxt(pf,Z[iBeg:iFin],fmt='%4d',newline='')
pf.write('\n')
pf.close()
print (' popLA %d %d %d pole figure saved to %s'%(PH[0],PH[1],PH[2],pfFile))
def OnCSV(event):
pfName = PhaseName
pfFile = ''
cell = generalData['Cell'][1:7]
if 'Inverse' in textureData['PlotType']:
SHCoef = textureData['SH Coeff'][1]
PX = np.array(textureData['PFxyz'])
gam = atan2d(PX[0],PX[1])
xy = np.sqrt(PX[0]**2+PX[1]**2)
xyz = np.sqrt(PX[0]**2+PX[1]**2+PX[2]**2)
psi = asind(xy/xyz)
IODFln = G2lat.Glnh(SHCoef,psi,gam,SamSym[textureData['Model']])
pfName = PhaseName+'%d%d%dIPF.csv'%(int(PX[0]),int(PX[1]),int(PX[2]))
pth = G2G.GetExportPath(G2frame)
dlg = wx.FileDialog(G2frame, 'Choose CSV inverse pole figure file name', pth, pfName,
'CSV file (*.csv)|*.csv',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
else:
PH = np.array(textureData['PFhkl'])
phi,beta = G2lat.CrsAng(PH,cell,SGData)
SHCoef = textureData['SH Coeff'][1]
ODFln = G2lat.Flnh(SHCoef,phi,beta,SGData)
pfName = PhaseName+'%d%d%dPF.csv'%(PH[0],PH[1],PH[2])
pth = G2G.GetExportPath(G2frame)
dlg = wx.FileDialog(G2frame, 'Choose CSV pole figure file name', pth, pfName,
'CSV file (*.csv)|*.csv',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
try:
if dlg.ShowModal() == wx.ID_OK:
pfFile = dlg.GetPath()
print ('CSV save '+pfFile)
finally:
dlg.Destroy()
if pfFile:
pf = open(pfFile,'w')
pf.write('"%s"\n'%(PhaseName))
if 'Inverse' in textureData['PlotType']:
pf.write('" %s %d %d %d inverse pole figure"\n'%(PhaseName,int(PX[0]),int(PX[1]),int(PX[2])))
P,R = np.mgrid[0:19,0:72]
pf.write('"phi/beta",')
np.savetxt(pf,np.linspace(0.,90.,19,True),fmt='%10.4f,',newline='')
pf.write('\n')
P = P.flatten()*5.
R = R.flatten()*5.
Z = G2lat.invpolfcal(IODFln,SGData,P,R)
Z = np.reshape(Z,(19,72)).T
for i,row in enumerate(Z):
pf.write('%8d, '%(i*5))
np.savetxt(pf,row,fmt='%10.4f,',newline='')
pf.write('\n')
pf.close()
print (' %s %d %d %d inverse pole figure saved to %s'%(PhaseName,int(PX[0]),int(PX[1]),int(PX[2]),pfFile))
else:
pf.write('" %s %d %d %d pole figure"\n'%(PhaseName,PH[0],PH[1],PH[2]))
Psi,Gam = np.mgrid[0:19,0:72]
pf.write('"psi/gam",')
np.savetxt(pf,np.linspace(0.,90.,19,True),fmt='%10.4f,',newline='')
pf.write('\n')
Psi = Psi.flatten()*5.
Gam = Gam.flatten()*5.
Z = np.array(G2lat.polfcal(ODFln,SamSym[textureData['Model']],Psi,Gam))
Z = np.reshape(Z,(19,72)).T
for i,row in enumerate(Z):
pf.write('%8d, '%(i*5))
np.savetxt(pf,row,fmt='%10.4f,',newline='')
pf.write('\n')
pf.close()
print (' %s %d %d %d pole figure saved to %s'%(PhaseName,PH[0],PH[1],PH[2],pfFile))
def SHPenalty(Penalty):
def OnHKLList(event):
event.Skip()
dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select penalty hkls',
'Penalty hkls',hkls,filterBox=False)
try:
if dlg.ShowModal() == wx.ID_OK:
Penalty[0] = [hkls[i] for i in dlg.GetSelections()]
if not Penalty[0]:
Penalty[0] = ['',]
else:
return
finally:
dlg.Destroy()
G2frame.GPXtree.UpdateSelection()
# wx.CallLater(100,UpdateTexture)
A = G2lat.cell2A(generalData['Cell'][1:7])
hkls = G2lat.GenPfHKLs(10,SGData,A)
shPenalty = wx.BoxSizer(wx.HORIZONTAL)
shPenalty.Add(wx.StaticText(Texture,wx.ID_ANY,' Negative MRD penalty list: '),0,WACV)
shPenalty.Add(wx.ComboBox(Texture,value=Penalty[0][0],choices=Penalty[0],
style=wx.CB_DROPDOWN|wx.CB_READONLY),0,WACV)
hklList = wx.Button(Texture,label='Select penalty hkls')
hklList.Bind(wx.EVT_BUTTON,OnHKLList)
shPenalty.Add(hklList,0,WACV)
shPenalty.Add(wx.StaticText(Texture,wx.ID_ANY,' Zero MRD tolerance: '),0,WACV)
shToler = G2G.ValidatedTxtCtrl(Texture,Penalty,1,nDig=(10,2),xmin=0.001)
shPenalty.Add(shToler,0,WACV)
return shPenalty
def OnProj(event):
Obj = event.GetEventObject()
generalData['3Dproj'] = Obj.GetValue()
wx.CallAfter(G2plt.PlotTexture,G2frame,data)
# UpdateTexture executable starts here
Texture = G2frame.Texture
generalData = data['General']
PhaseName = generalData['Name']
SGData = generalData['SGData']
try:
textureData = generalData['SH Texture']
except KeyError: #fix old files!
textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],'ShoDet':False,
'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
if 'SHShow' not in textureData:
textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
if 'PlotType' not in textureData:
textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
if 'Penalty' not in textureData:
textureData['Penalty'] = [['',],0.1,False,1.0]
if 'ShoDet' not in textureData:
textureData['ShoDet'] = False
shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
keyList = G2frame.GetHistogramNames(['PWDR',])
UseList = data['Histograms']
HistsInPhase = [name for name in keyList if name in UseList]
textureData['det Angles'] = []
for hist in HistsInPhase:
pId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,hist) #only use 1st histogram
Sample = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,pId,'Sample Parameters'))
Inst = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,pId,'Instrument Parameters'))[0]
if 'NT' in Inst['Type'][0]:
Tth = Inst['2-theta'][1]/2.
Gangls = [Sample['Phi'],Sample['Chi'],Sample['Omega'],Sample['Azimuth']]
Sangls = [textureData['Sample omega'][1],textureData['Sample chi'][1],textureData['Sample phi'][1]]
phi,gam,x,x = G2lat.SamAng(Tth,Gangls,Sangls,False)
if phi > 90.:
phi = 180.-phi
gam += 180.
gam %= 360.
textureData['det Angles'].append([hist,phi,gam])
G2frame.GetStatusBar().SetStatusText('',1)
if Texture.GetSizer():
Texture.GetSizer().Clear(True)
mainSizer = wx.BoxSizer(wx.VERTICAL)
# sanity check: should this project be fitting texture?
mainSizer.Add(wx.StaticText(Texture,label=
' NB: Normally texture model fitting generally requires multiple datasets with differing sample orientations/detector values'))
if G2frame.testSeqRefineMode() and G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Sequential results'):
mainSizer.Add(wx.StaticText(Texture,label=
" Sequential result found. Use Texture/Refine texture above. See Method B in texture tutorial."))
h,pd = G2frame.GetUsedHistogramsAndPhasesfromTree()
if len(h) < 3:
mainSizer.Add(wx.StaticText(Texture,label=' Insufficient number of patterns for usual texture analysis'))
mainSizer.Add(wx.StaticText(Texture,label=
' For structural fits that need preferred orientation corrections, use terms in the Data tab instead.'))
else:
unique = []
for i in h:
setting = [h[i]['Sample Parameters'][key] for key in ('Omega', 'Chi', 'Phi', 'Azimuth')]
if setting not in unique: unique.append(setting)
if len(unique) == 1:
mainSizer.Add(wx.StaticText(Texture,label=
" All your histograms have the same values for Omega, Chi, Phi and Azimuth.\n Texture fitting requires differing values."))
elif len(unique) == 2:
mainSizer.Add(wx.StaticText(Texture,label=
" You have only two unique settings for Omega, Chi, Phi and Azimuth.\n Texture fitting requires more differing values."))
if textureData['Order'] or textureData['SH Coeff'][0]:
mainSizer.Add(wx.StaticText(Texture,wx.ID_ANY,
'\n *** To remove this texture: Turn off refinement and set Harmonic order to zero below.\n'))
G2G.HorizontalLine(mainSizer,Texture)
topSizer = G2frame.dataWindow.topBox
topSizer.Clear(True)
parent = G2frame.dataWindow.topPanel
lbl= f"Spherical harmonics texture data for {data['General']['Name']!r}"[:60]
topSizer.Add(wx.StaticText(parent,label=lbl),0,WACV)
topSizer.Add((-1,-1),1,wx.EXPAND)
topSizer.Add(G2G.HelpButton(parent,helpIndex=G2frame.dataWindow.helpKey))
wx.CallAfter(G2frame.dataWindow.SetDataSize)
mainSizer.Add(wx.StaticText(Texture,label=' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))))
mainSizer.Add((0,5),0)
shSizer = wx.FlexGridSizer(0,6,5,5)
shSizer.Add(wx.StaticText(Texture,-1,' Texture model: '),0,WACV)
shModel = wx.ComboBox(Texture,value=textureData['Model'],choices=shModels,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
shSizer.Add(shModel,0,WACV)
shSizer.Add(wx.StaticText(Texture,-1,' Harmonic order: '),0,WACV)
shOrder = wx.ComboBox(Texture,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
shSizer.Add(shOrder,0,WACV)
shRef = wx.CheckBox(Texture,label=' Refine texture?')
shRef.SetValue(textureData['SH Coeff'][0])
shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
shSizer.Add(shRef,0,WACV)
shShow = wx.CheckBox(Texture,label=' Show coeff.?')
shShow.SetValue(textureData['SHShow'])
shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
shSizer.Add(shShow,0,WACV)
mainSizer.Add(shSizer,0,0)
mainSizer.Add((0,5),0)
PTSizer = wx.FlexGridSizer(0,5,5,5)
PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,WACV)
choices = ['Axial pole distribution','Pole figure','Inverse pole figure','3D pole distribution']
pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
PTSizer.Add(pfType,0,WACV)
if 'Axial' not in textureData['PlotType'] and '3D' not in textureData['PlotType']:
PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,WACV)
projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic'],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
PTSizer.Add(projSel,0,WACV)
if textureData['PlotType'] == 'Pole figure' and len(textureData['det Angles']):
shoDet = wx.CheckBox(Texture,-1,label=' Show detectors?')
shoDet.SetValue(textureData['ShoDet'])
shoDet.Bind(wx.EVT_CHECKBOX, OnShoDet)
PTSizer.Add(shoDet,0,WACV)
else:
PTSizer.Add((0,5),0)
elif '3D' in textureData['PlotType']:
PTSizer.Add(wx.StaticText(Texture,-1,' Show projections for: '),0,WACV)
proj = ['','x','y','z','xy','xz','yz','xyz']
projType = wx.ComboBox(Texture,wx.ID_ANY,value=generalData['3Dproj'],choices=proj,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
projType.Bind(wx.EVT_COMBOBOX, OnProj)
PTSizer.Add(projType,0,WACV)
PTSizer.Add((0,5),0)
if textureData['PlotType'] in ['Pole figure','Axial pole distribution','3D pole distribution']:
PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,WACV)
PH = textureData['PFhkl']
# Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0)
pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
else:
PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,WACV)
PX = textureData['PFxyz']
# Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0)
pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
PTSizer.Add(pfVal,0,WACV)
if 'Axial' not in textureData['PlotType'] and '3D' not in textureData['PlotType']:
PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,WACV)
choice = [m for m in mpl.cm.datad.keys()]+['GSPaired','GSPaired_r',] #if not m.endswith("_r")
choice.sort()
colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
PTSizer.Add(colorSel,0,WACV)
if 'figure' in textureData['PlotType']:
popLA = wx.Button(Texture,-1,"Make CSV file")
popLA.Bind(wx.EVT_BUTTON, OnCSV)
PTSizer.Add(popLA,0,WACV)
mainSizer.Add(PTSizer,0)
mainSizer.Add((0,5),0)
if textureData['SHShow']:
mainSizer.Add(wx.StaticText(Texture,-1,' Spherical harmonic coefficients: '))
mainSizer.Add((0,5),0)
ODFSizer = wx.FlexGridSizer(0,8,2,2)
ODFkeys = list(textureData['SH Coeff'][1].keys())
ODFkeys.sort()
for item in ODFkeys:
ODFSizer.Add(wx.StaticText(Texture,-1,item),0,WACV)
ODFval = G2G.ValidatedTxtCtrl(Texture,textureData['SH Coeff'][1],item,nDig=(8,3),OnLeave=OnODFValue)
ODFSizer.Add(ODFval,0,WACV)
mainSizer.Add(ODFSizer,0)
mainSizer.Add((0,5),0)
mainSizer.Add((0,5),0)
mainSizer.Add(wx.StaticText(Texture,-1,' Sample orientation angle zeros: '),0)
mainSizer.Add((0,5),0)
angSizer = wx.BoxSizer(wx.HORIZONTAL)
angIndx = {}
for item in ['Sample omega','Sample chi','Sample phi']:
angRef = wx.CheckBox(Texture,-1,label=item+': ')
angRef.SetValue(textureData[item][0])
angIndx[angRef.GetId()] = item
angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
angSizer.Add(angRef,0,WACV)
angVal = G2G.ValidatedTxtCtrl(Texture,textureData[item],1,nDig=(8,2))
angSizer.Add(angVal,0,WACV|wx.LEFT,5)
mainSizer.Add(angSizer,0,wx.LEFT,5)
# mainSizer.Add(SHPenalty(textureData['Penalty']),0,wx.LEFT,5) for future
G2phsG.SetPhaseWindow(Texture,mainSizer)
#### UpdateWavesData GUI
[docs]
def UpdateWavesData(G2frame,data,Scroll=0):
'''Create the Wave Data tab for modulated structures
'''
def OnAtmSel(event):
Obj = event.GetEventObject()
G2frame.atmSel = Obj.GetValue()
RepaintAtomInfo()
def RepaintAtomInfo(Scroll=0):
G2frame.bottomSizer.Clear(True)
G2frame.bottomSizer = ShowAtomInfo()
mainSizer.Add(G2frame.bottomSizer)
mainSizer.Layout()
G2frame.dataWindow.Refresh()
waveData.SetVirtualSize(mainSizer.GetMinSize())
waveData.Scroll(0,Scroll)
G2frame.dataWindow.SendSizeEvent()
def ShowAtomInfo():
global mapSel #so it can be seen below in OnWavePlot
def AtomSizer(atom):
global mapSel
def OnShowWave(event):
Obj = event.GetEventObject()
atom = Indx[Obj.GetId()]
Ax = Obj.GetValue()
G2plt.ModulationPlot(G2frame,data,atom,Ax)
atomSizer = wx.BoxSizer(wx.HORIZONTAL)
atomSizer.Add(wx.StaticText(waveData,label=
' Modulation data for atom: %s Site sym: %s'%(atom[0],atom[cs].strip())),0,WACV)
axchoice = ['x','y','z']
if len(D4Map['rho']):
atomSizer.Add(wx.StaticText(waveData,label=' Show contour map for axis: '),0,WACV)
mapSel = wx.ComboBox(waveData,value=' ',choices=axchoice,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
mapSel.Bind(wx.EVT_COMBOBOX,OnShowWave)
Indx[mapSel.GetId()] = atom
atomSizer.Add(mapSel,0,WACV)
return atomSizer
def WaveSizer(iatm,wavedata,Stype,typeName,Names):
def OnWaveType(event):
Obj = event.GetEventObject()
item = Indx[Obj.GetId()]
G2elem.AddWave2atm(atm)
if len(atm[-1]['SS1'][item]) <= 1:
atm[-1]['SS1'][item] = [0,]
atm[-1]['SS1'][item][0] = waveType.GetValue()
wx.CallAfter(RepaintAtomInfo,G2frame.waveData.GetScrollPos(wx.VERTICAL))
else:
if len(waveTypes[Stype]) > 1:
waveType.SetValue(atm[-1]['SS1'][Stype][0])
G2G.G2MessageBox(G2frame,'Warning: can only change wave type if no waves','Not changed')
def OnAddWave(event):
if not SSGData: # empty means
G2G.G2MessageBox(None,'Select a modulation group first','Superspace Group Error')
return
Obj = event.GetEventObject()
item = Indx[Obj.GetId()]
nt = numVals[Stype]
G2elem.AddWave2atm(atm)
if not len(atm[-1]['SS1'][item]):
if waveTyp in ['ZigZag','Block','Crenel']:
nt = numVals[waveTyp]
atm[-1]['SS1'][item] = [0,]
atm[-1]['SS1'][item][0] = waveType.GetValue()
atm[-1]['SS1'][item].append([[0.0 for i in range(nt)],False])
wx.CallAfter(RepaintAtomInfo,G2frame.waveData.GetScrollPos(wx.VERTICAL))
def OnRefWave(event):
Obj = event.GetEventObject()
item,iwave = Indx[Obj.GetId()]
G2elem.AddWave2atm(atm)
atm[-1]['SS1'][item][iwave+1][1] = not atm[-1]['SS1'][item][iwave+1][1]
def OnDelWave(event):
Obj = event.GetEventObject()
item,iwave = Indx[Obj.GetId()]
del atm[-1]['SS1'][item][iwave+1]
if len(atm[-1]['SS1'][item]) == 1:
atm[-1]['SS1'][item][0] = 'Fourier'
wx.CallAfter(RepaintAtomInfo,G2frame.waveData.GetScrollPos(wx.VERTICAL))
def OnWavePlot(invalid,value,tc):
if len(D4Map['rho']):
Ax = mapSel.GetValue()
if Ax:
G2plt.ModulationPlot(G2frame,data,atm,Ax)
waveTyp,waveBlk = 'Fourier',[]
if len(wavedata):
waveTyp = wavedata[0]
waveBlk = wavedata[1:]
waveSizer = wx.BoxSizer(wx.VERTICAL)
waveHead = wx.BoxSizer(wx.HORIZONTAL)
waveHead.Add(wx.StaticText(waveData,label=typeName+' modulation parameters: '),0,WACV)
if Stype == 'Smag' and len(waveBlk): #only allow one magnetic wave - keeps it simple for now
pass
else:
waveAdd = wx.Button(waveData,label='Add wave?')
waveAdd.Bind(wx.EVT_BUTTON, OnAddWave)
Indx[waveAdd.GetId()] = Stype
waveHead.Add(waveAdd,0,WACV)
waveHead.Add(wx.StaticText(waveData,label=' WaveType: '),0,WACV)
waveType = wx.ComboBox(waveData,value=waveTyp,choices=waveTypes[Stype],
style=wx.CB_READONLY|wx.CB_DROPDOWN)
Indx[waveType.GetId()] = Stype
waveType.Bind(wx.EVT_COMBOBOX,OnWaveType)
waveHead.Add(waveType,0,WACV)
waveSizer.Add(waveHead)
if len(waveBlk):
nx = 0
for iwave,wave in enumerate(waveBlk):
if not iwave:
if waveTyp in ['ZigZag','Block','Crenel']:
nx = 1
CSI = G2spc.GetSSfxuinel(waveTyp,Stype,1,xyz,SGData,SSGData)[0]
else:
CSI = G2spc.GetSSfxuinel('Fourier',Stype,iwave+1-nx,xyz,SGData,SSGData)[0]
waveName = 'Fourier'
if Stype == 'Sfrac':
nterm = 2
if 'Crenel' in waveTyp and not iwave:
waveName = 'Crenel'
names = Names[2:]
else:
names = Names[:2]
Waves = wx.FlexGridSizer(0,4,5,5)
elif Stype == 'Spos':
nterm = 6
if waveTyp in ['ZigZag','Block'] and not iwave:
nterm = 5
names = Names[6:]
Waves = wx.FlexGridSizer(0,7,5,5)
waveName = waveTyp
else:
names = Names[:6]
Waves = wx.FlexGridSizer(0,8,5,5)
elif Stype == 'Sadp':
nterm = 12
names = Names
Waves = wx.FlexGridSizer(0,8,5,5)
elif Stype == 'Smag':
nterm = 6
names = Names
Waves = wx.FlexGridSizer(0,8,5,5)
waveSizer.Add(wx.StaticText(waveData,label=' %s parameters: %s'%(waveName,str(names).rstrip(']').lstrip('[').replace("'",''))),0)
for ival in range(nterm):
val = wave[0][ival]
if np.any(CSI[0][ival]):
minmax = [-0.2,0.2]
if Stype == 'Smag':
minmax = [-20.,20.]
if waveTyp in ['ZigZag','Block','Crenel'] and not iwave and ival < 2:
if not ival:
minmax = [0.,2.]
else:
minmax = [wave[0][0],1.0+wave[0][0]]
waveVal = G2G.ValidatedTxtCtrl(waveData,wave[0],ival,nDig=(10,5),xmin=minmax[0],xmax=minmax[1],OnLeave=OnWavePlot)
else:
waveVal = G2G.ReadOnlyTextCtrl(waveData,value='%.5f'%(val))
Waves.Add(waveVal,0,WACV)
if len(wave[0]) > 6 and ival == 5:
Waves.Add((5,5),0)
Waves.Add((5,5),0)
waveRef = wx.CheckBox(waveData,label='Refine?')
waveRef.SetValue(wave[1])
Indx[waveRef.GetId()] = [Stype,iwave]
waveRef.Bind(wx.EVT_CHECKBOX, OnRefWave)
Waves.Add(waveRef,0,WACV)
if iwave < len(waveBlk)-1:
Waves.Add((5,5),0)
else:
waveDel = wx.Button(waveData,wx.ID_ANY,'Delete',style=wx.BU_EXACTFIT)
Indx[waveDel.GetId()] = [Stype,iwave]
waveDel.Bind(wx.EVT_BUTTON,OnDelWave)
Waves.Add(waveDel,0,WACV)
waveSizer.Add(Waves)
return waveSizer
iatm = atNames.index(G2frame.atmSel)
atm = atomData[iatm]
G2elem.AddWave2atm(atm)
xyz = atm[cx:cx+3]
atomSizer = wx.BoxSizer(wx.VERTICAL)
G2G.HorizontalLine(atomSizer,waveData)
atomSizer.Add(AtomSizer(atm))
for Stype in ['Sfrac','Spos','Sadp','Smag']:
if atm[cia] != 'A' and Stype == 'Sadp': #Uiso can't have modulations! (why not?)
continue
if generalData['Type'] != 'magnetic' and Stype == 'Smag':
break
try:
atomSizer.Add(WaveSizer(iatm,atm[-1]['SS1'][Stype],Stype,typeNames[Stype],Labels[Stype]))
except TypeError: # not expected anymore
atomSizer.Add(wx.StaticText(waveData,label=' Error: could not process SS info for this atom'))
break
return atomSizer
generalData = data['General']
cx,ct,cs,cia = generalData['AtomPtrs']
typeNames = {'Sfrac':' Site fraction','Spos':' Position','Sadp':' Thermal motion','Smag':' Magnetic moment'}
numVals = {'Sfrac':2,'Spos':6,'Sadp':12,'Smag':6,'ZigZag':5,'Block':5,'Crenel':2}
posNames = ['Xsin','Ysin','Zsin','Xcos','Ycos','Zcos','Tmin','Tmax','Xmax','Ymax','Zmax']
adpNames = ['U11sin','U22sin','U33sin','U12sin','U13sin','U23sin',
'U11cos','U22cos','U33cos','U12cos','U13cos','U23cos']
magNames = ['MXsin','MYsin','MZsin','MXcos','MYcos','MZcos']
fracNames = ['Fsin','Fcos','Fzero','Fwid']
waveTypes = {'Sfrac':['Fourier','Crenel'],'Spos':['Fourier','ZigZag','Block',],'Sadp':['Fourier',],'Smag':['Fourier',]}
Labels = {'Spos':posNames,'Sfrac':fracNames,'Sadp':adpNames,'Smag':magNames}
Indx = {}
waveData = G2frame.waveData
G2frame.GetStatusBar().SetStatusText('',1)
generalData = data['General']
SGData = generalData['SGData']
SSGData = generalData['SSGData']
cx,ct,cs,cia = generalData['AtomPtrs']
atomData = data['Atoms']
D4Map = generalData.get('4DmapData',{'rho':[]})
if waveData.GetSizer():
waveData.GetSizer().Clear(True)
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(wx.StaticText(waveData,label=' Incommensurate propagation wave data'))
atNames = []
for atm in atomData:
atNames.append(atm[ct-1])
if not atNames:
mainSizer.Add(wx.StaticText(waveData,label=' (no atoms in phase)'))
G2phsG.SetPhaseWindow(G2frame.waveData,mainSizer,Scroll=Scroll)
return
if G2frame.atmSel not in atNames:
G2frame.atmSel = atNames[0]
topSizer = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(topSizer,0)
topSizer.Add(wx.StaticText(waveData,label=' Select atom to edit: '),0,WACV)
atms = wx.ComboBox(waveData,value=G2frame.atmSel,choices=atNames,
style=wx.CB_READONLY|wx.CB_DROPDOWN)
atms.Bind(wx.EVT_COMBOBOX,OnAtmSel)
topSizer.Add(atms,0)
G2frame.bottomSizer = ShowAtomInfo()
mainSizer.Add(G2frame.bottomSizer)
G2phsG.SetPhaseWindow(G2frame.waveData,mainSizer,Scroll=Scroll)