# -*- coding: utf-8 -*-
#GSASIIrestr - restraint GUI routines
########### SVN repository information ###################
# $Date: 2024-03-17 12:50:24 -0500 (Sun, 17 Mar 2024) $
# $Author: toby $
# $Revision: 5767 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/GSASIIrestrGUI.py $
# $Id: GSASIIrestrGUI.py 5767 2024-03-17 17:50:24Z toby $
########### SVN repository information ###################
'''Restraint GUI routines follow.
'''
from __future__ import division, print_function
import wx
import wx.grid as wg
import numpy as np
import numpy.ma as ma
import os.path
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 5767 $")
import GSASIImath as G2mth
import GSASIIlattice as G2lat
import GSASIIspc as G2spc
import GSASIIdataGUI as G2gd
import GSASIIplot as G2plt
import GSASIIdata as G2data
import GSASIIctrlGUI as G2G
import GSASIIphsGUI as G2phsGUI
import GSASIIobj as G2obj
import GSASIIconstrGUI as G2cnstG
import GSASIIexprGUI as G2exG
try:
wx.NewIdRef
wx.NewId = wx.NewIdRef
except AttributeError:
pass
try:
VERY_LIGHT_GREY = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
VERY_YELLOW = wx.Colour(255,255,0)
WACV = wx.ALIGN_CENTER_VERTICAL
except:
pass
TabSelectionIdDict = {}
################################################################################
##### Restraints
################################################################################
[docs]
def GetSelectedRows(widget,lbl='edit',G2frame=None):
'''Returns a list of selected rows. Rows can be selected, blocks of cells
or individual cells can be selected. The column for selected cells is ignored.
'''
try:
rows = widget.GetSelectedRows()
if rows: return rows
top = widget.GetSelectionBlockTopLeft()
bot = widget.GetSelectionBlockBottomRight()
if top and bot:
rows = range(top[0][0],bot[0][0]+1)
if rows: return rows
rows = sorted(list(set([cell[0] for cell in widget.GetSelectedCells()])))
if rows: return rows
choices = ["{}: {}".format(widget.GetRowLabelValue(i),widget.GetCellValue(i,0))
for i in range(widget.GetNumberRows())]
try:
dlg = G2G.G2MultiChoiceDialog(G2frame,'Restraints to '+lbl,
'Select restraints',choices)
if dlg.ShowModal() != wx.ID_OK: return
return dlg.GetSelections()
finally:
dlg.Destroy()
except:
return
[docs]
def UpdateRestraints(G2frame,data,phaseName):
'''Respond to selection of the Restraints item on the
data tree
'''
# global Pages
def getMacroFile(macName):
defDir = os.path.join(GSASIIpath.path2GSAS2,'inputs','GSASIImacros')
if not os.path.exists(defDir): # patch 3/2024 for svn dir organization
defDir = os.path.join(GSASIIpath.path2GSAS2,'GSASIImacros')
if not os.path.exists(defDir):
print('Warning: GSASIImacros directory not found')
return
dlg = wx.FileDialog(G2frame,message='Choose '+macName+' restraint macro file',
defaultDir=defDir,defaultFile="",wildcard="GSAS-II macro file (*.mac)|*.mac",
style=wx.FD_OPEN | wx.FD_CHANGE_DIR)
try:
macro = ''
if dlg.ShowModal() == wx.ID_OK:
macfile = dlg.GetPath()
macro = open(macfile,'r')
head = macro.readline()
if macName not in head:
print (head)
print ('**** ERROR - wrong restraint macro file selected, try again ****')
macro = []
finally:
dlg.Destroy()
return macro #advanced past 1st line
def getMOGULFile():
colNums = [0,2,3,5,6,7] # location for these fields:
# Type, Fragment, No. of hits, Query value, Mean, Std. dev.
dlg = wx.FileDialog(G2frame,message='Choose MOGUL csv file',
defaultDir='.',defaultFile="",wildcard="MOGUL csv file (*.csv)|*.csv",
style=wx.FD_OPEN | wx.FD_CHANGE_DIR)
try:
mogul = ''
if dlg.ShowModal() == wx.ID_OK:
csvfile = dlg.GetPath()
mogul = open(csvfile,'r')
head = mogul.readline()
if 'Type' not in head:
print ('Note: header line is\n',head)
print ('**** ERROR - file selected is not a MOGUL csv file, try again ****')
mogul = []
else:
for i,k in enumerate(('Type','Fragment',
'No. of hits','Query value','Mean','Std. dev.')):
try:
colNums[i] = head.split(',').index(k)
except ValueError:
pass
finally:
dlg.Destroy()
return mogul,colNums #file pointer advanced past 1st line & col pointers
def OnPlotAARestraint(event):
page = G2frame.restrBook.GetSelection()
if 'Torsion' in G2frame.restrBook.GetPageText(page):
torNames = []
torNames += list(restrData['Torsion']['Coeff'].keys())
dlg = wx.SingleChoiceDialog(G2frame,'Select','Torsion data',torNames)
try:
if dlg.ShowModal() == wx.ID_OK:
torName = torNames[dlg.GetSelection()]
torsion = G2data.torsionDist[torName]
torCoeff = restrData['Torsion']['Coeff'][torName]
torList = restrData['Torsion']['Torsions']
Names = []
Angles = []
for i,[indx,ops,cofName,esd] in enumerate(torList):
if cofName == torName:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = '('+atoms[2][1]+atoms[2][0].strip()+atoms[2][2]+')'
for atom in atoms:
name += ' '+atom[3]
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
angle = G2mth.getRestTorsion(XYZ,Amat)
Angles.append(angle)
Names.append(name)
G2plt.PlotTorsion(G2frame,phaseName,torsion,torName,Names,np.array(Angles),torCoeff)
finally:
dlg.Destroy()
elif 'Rama' in G2frame.restrBook.GetPageText(page):
ramaNames = ['All',]
ramaNames += list(restrData['Rama']['Coeff'].keys())
dlg = wx.SingleChoiceDialog(G2frame,'Select','Ramachandran data',ramaNames)
try:
if dlg.ShowModal() == wx.ID_OK:
ramaName = ramaNames[dlg.GetSelection()]
rama = G2data.ramachandranDist[ramaName]
ramaCoeff = []
if ramaName != 'All':
ramaCoeff = restrData['Rama']['Coeff'][ramaName]
ramaList = restrData['Rama']['Ramas']
Names = []
PhiPsi = []
for i,[indx,ops,cofName,esd] in enumerate(ramaList):
if cofName == ramaName or (ramaName == 'All' and '-1' in cofName):
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = '('+atoms[3][1]+atoms[3][0].strip()+atoms[3][2]+')'
for atom in atoms:
name += ' '+atom[3]
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
phi,psi = G2mth.getRestRama(XYZ,Amat)
PhiPsi.append([phi,psi])
Names.append(name)
G2plt.PlotRama(G2frame,phaseName,rama,ramaName,Names,np.array(PhiPsi),ramaCoeff)
finally:
dlg.Destroy()
def SetupParmDict(G2frame):
'''Creates a parameter dict with variable names as keys and
numerical values (only)
'''
G2cnstG.CheckAllScalePhaseFractions(G2frame,refine=False)
try:
parmDict,varyList = G2frame.MakeLSParmDict()
except:
print('Error retrieving parameters')
return {}
return {i:parmDict[i][0] for i in parmDict}
def OnAddRestraint(event):
'''Adds a restraint depending on which tab is currently displayed'''
page = G2frame.restrBook.GetSelection()
if 'Bond' in G2frame.restrBook.GetPageText(page):
AddBondRestraint(restrData['Bond'])
elif 'Angle' in G2frame.restrBook.GetPageText(page):
AddAngleRestraint(restrData['Angle'])
elif 'Plane' in G2frame.restrBook.GetPageText(page):
AddPlaneRestraint(restrData['Plane'])
elif 'Chem' in G2frame.restrBook.GetPageText(page):
AddChemCompRestraint(restrData['ChemComp'])
elif 'Texture' in G2frame.restrBook.GetPageText(page):
AddTextureRestraint(restrData['Texture'])
elif 'Moments' in G2frame.restrBook.GetPageText(page):
AddMomentRestraint(restrData['Moments'])
elif 'General' in G2frame.restrBook.GetPageText(page):
parmDict = SetupParmDict(G2frame)
dlg = G2exG.ExpressionDialog(G2frame,parmDict,
header="Create a restraint expression",
fit=False,wildCard=G2frame.testSeqRefineMode())
restobj = dlg.Show(True)
if restobj:
restrData['General']['General'].append([restobj,0.0,1.0])
wx.CallAfter(UpdateGeneralRestr,restrData['General'])
def OnAddAARestraint(event):
page = G2frame.restrBook.GetSelection()
if 'Bond' in G2frame.restrBook.GetPageText(page):
AddAABondRestraint(restrData['Bond'])
elif 'Angle' in G2frame.restrBook.GetPageText(page):
AddAAAngleRestraint(restrData['Angle'])
elif 'Plane' in G2frame.restrBook.GetPageText(page):
AddAAPlaneRestraint(restrData['Plane'])
elif 'Chiral' in G2frame.restrBook.GetPageText(page):
AddAAChiralRestraint(restrData['Chiral'])
elif 'Torsion' in G2frame.restrBook.GetPageText(page):
AddAATorsionRestraint(restrData['Torsion'])
elif 'Rama' in G2frame.restrBook.GetPageText(page):
AddAARamaRestraint(restrData['Rama'])
def OnUseMogul(event):
page = G2frame.restrBook.GetSelection()
if 'Bond' in G2frame.restrBook.GetPageText(page):
AddMogulBondRestraint(restrData['Bond'])
elif 'Angle' in G2frame.restrBook.GetPageText(page):
AddMogulAngleRestraint(restrData['Angle'])
def makeChains(Names,Ids):
Chains = {}
atoms = zip(Names,Ids)
for name,Id in atoms:
items = name.split(' ',2)
rnum,res = items[0].split(':')
rnum = int(rnum)
if items[1] not in Chains:
Residues = {}
Chains[items[1]] = Residues
if rnum not in Residues:
Residues[rnum] = [[],[]]
if items[2][3] in [' ','A']:
Residues[rnum][0].append([res,items[2],Id])
if items[2][3] in [' ','B']:
Residues[rnum][1].append([res,items[2],Id])
return Chains
def AddBondRestraint(bondRestData):
Lists = {'origin':[],'target':[]}
for listName in ['origin','target']:
dlg = G2G.G2MultiChoiceDialog(G2frame,'Bond restraint '+listName+' for '+General['Name'],
'Select bond restraint '+listName+' atoms',Names)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelections()
for x in sel:
if 'all' in Names[x]:
allType = Types[x]
for name,Type,coords,Id in zip(Names,Types,Coords,Ids):
if Type == allType and 'all' not in name:
Lists[listName].append([Id,Type,coords])
else:
Lists[listName].append([Ids[x],Types[x],Coords[x],])
else:
return
if len(Lists['origin']) and len(Lists['target']):
bond = 1.54
dlg = G2G.SingleFloatDialog(G2frame,'Distance','Enter restraint distance for bond',bond,[0.01,4.],'%.4f')
if dlg.ShowModal() == wx.ID_OK:
bond = dlg.GetValue()
dlg.Destroy()
Factor = bondRestData['Range']
dlg = wx.ProgressDialog("Generating bond restraints","Processed origin atoms",len(Lists['origin']),
style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME)
try:
bondlst = G2mth.searchBondRestr(Lists['origin'],Lists['target'],
bond,Factor,General['Type'],SGData,Amat,0.01,dlg)
for newBond in bondlst:
if newBond not in bondRestData['Bonds']:
bondRestData['Bonds'].append(newBond)
finally:
dlg.Destroy()
UpdateBondRestr(bondRestData)
def AddAABondRestraint(bondRestData):
macro = getMacroFile('bond')
if not macro:
return
macStr = macro.readline()
atoms = zip(Names,Coords,Ids)
Factor = bondRestData['Range']
while macStr:
items = macStr.split()
if 'F' in items[0]:
restrData['Bond']['wtFactor'] = float(items[1])
elif 'S' in items[0]:
oIds = []
oCoords = []
oDis = []
tIds = []
tCoords = []
tDis = []
res = items[1]
dist = float(items[2])
esd = float(items[3])
oAtm,tAtm = items[4:6]
for Name,coords,Id in atoms:
names = Name.split(' ',2)
if res == '*' or res in names[0]:
if oAtm.ljust(3) == names[2][:3]:
oIds.append(Id)
oCoords.append(np.array(coords))
oDis.append(names[2][3])
if tAtm.ljust(3) == names[2][:3]:
tIds.append(Id)
tCoords.append(np.array(coords))
tDis.append(names[2][3])
for i,[oId,oCoord,odis] in enumerate(zip(oIds,oCoords,oDis)):
for tId,tCoord,tdis in list(zip(tIds,tCoords,tDis))[i:]:
if odis+tdis in ['AB','BA']:
continue
obsd = np.sqrt(np.sum(np.inner(Amat,tCoord-oCoord)**2))
if dist/Factor < obsd < dist*Factor:
newBond = [[oId,tId],['1','1'],dist,esd]
if newBond not in bondRestData['Bonds']:
bondRestData['Bonds'].append(newBond)
macStr = macro.readline()
macro.close()
print(' Found %d bond restraints'%len(bondRestData['Bonds']))
UpdateBondRestr(bondRestData)
def AddMogulBondRestraint(bondRestData):
mogul,colNums = getMOGULFile()
for line in mogul:
items = line.split(',')
if 'bond' == items[colNums[0]]:
oName,tName = items[colNums[1]].split()
oInd = Names.index(oName)
tInd = Names.index(tName)
if items[colNums[2]] != 'No hits':
dist = float(items[colNums[4]])
esd = float(items[colNums[5]])
else:
dist = float(items[colNums[3]])
esd = 0.02
newBond = [[Ids[oInd],Ids[tInd]],['1','1'],dist,esd]
if newBond not in bondRestData['Bonds']:
bondRestData['Bonds'].append(newBond)
UpdateBondRestr(bondRestData)
def AddAngleRestraint(angleRestData):
Radii = dict(zip(General['AtomTypes'],zip(General['BondRadii'],General['AngleRadii'])))
Lists = {'A-atom':[],'B-atom':[],'C-atom':[]}
for listName in ['A-atom','B-atom']:
dlg = G2G.G2MultiChoiceDialog(G2frame,'Select '+listName+' for angle A-B-C for '+General['Name'] ,
'Select angle restraint '+listName,Names)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelections()
for x in sel:
if 'all' in Names[x]:
allType = Types[x]
for name,Type,coords,Id in zip(Names,Types,Coords,Ids):
if Type == allType and 'all' not in name:
if 'A' in listName:
Lists[listName].append(Type)
else:
Lists[listName].append([Id,Type,coords])
else:
if 'A' in listName:
Lists[listName].append(Types[x])
else:
Lists[listName].append([Ids[x],Types[x],Coords[x],])
else:
return
targAtoms = [[Ids[x+iBeg],Types[x+iBeg],Coords[x+iBeg]] for x in range(len(Names[iBeg:]))]
if len(Lists['B-atom']):
value = 109.54
dlg = G2G.SingleFloatDialog(G2frame,'Angle','Enter restraint angle ',value,[30.,180.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
value = dlg.GetValue()
dlg.Destroy()
Factor = angleRestData['Range']
indices = (-2,-1,0,1,2)
Units = np.array([[h,k,l] for h in indices for k in indices for l in indices])
VectA = []
for Oid,Otype,Ocoord in Lists['B-atom']:
IndBlist = []
VectB = []
for Tid,Ttype,Tcoord in targAtoms:
result = G2spc.GenAtom(Tcoord,SGData,All=False,Move=False)
BsumR = (Radii[Otype][0]+Radii[Ttype][0])*Factor
AsumR = (Radii[Otype][1]+Radii[Ttype][1])*Factor
for Txyz,Top,Tunit,Spn in result:
Dx = (Txyz-Ocoord)+Units
dx = np.inner(Amat,Dx)
dist = ma.masked_less(np.sqrt(np.sum(dx**2,axis=0)),0.5)
IndB = ma.nonzero(ma.masked_greater(dist,BsumR))
if np.any(IndB):
for indb in IndB:
for i in range(len(indb)):
if str(dx.T[indb][i]) not in IndBlist:
IndBlist.append(str(dx.T[indb][i]))
unit = Units[indb][i]+Tunit
if np.any(unit):
Topstr = '%d+%d,%d,%d'%(Top,unit[0],unit[1],unit[2])
else:
Topstr = str(Top)
Dist = ma.getdata(dist[indb])[i]
if (Dist-AsumR) <= 0.:
VectB.append([Oid,'1',Ocoord,Ttype,Tid,Topstr,Tcoord,Dist])
VectA.append(VectB)
for Vects in VectA:
for i,vecta in enumerate(Vects):
for vectb in Vects[:i]:
if vecta[3] in Lists['A-atom']:
ids = [vecta[4],vecta[0],vectb[4]]
ops = [vecta[5],vecta[1],vectb[5]]
angle = [ids,ops,value,1.0]
if angle not in angleRestData['Angles']:
angleRestData['Angles'].append(angle)
UpdateAngleRestr(angleRestData)
def AddAAAngleRestraint(angleRestData):
macro = getMacroFile('angle')
if not macro:
return
Chains = makeChains(Names,Ids)
macStr = macro.readline()
while macStr:
items = macStr.split()
if 'F' in items[0]:
restrData['Angle']['wtFactor'] = float(items[1])
elif 'S' in items[0]:
Res = items[1]
Value = float(items[2])
Esd = float(items[3])
Atms = items[4:7]
pAtms = ['','','']
for i,atm in enumerate(Atms):
if '+' in atm:
pAtms[i] = atm.strip('+')
ids = [0,0,0]
chains = list(Chains.keys())
chains.sort()
for chain in chains:
residues = list(Chains[chain].keys())
residues.sort()
for residue in residues:
for ires in [0,1]:
if Res != '*': #works with disordered res
for res,name,Id in Chains[chain][residue][ires]:
if Res == res:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
else:
try:
for res,name,Id in Chains[chain][residue][ires]:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
for res,name,Id in Chains[chain][residue+1][ires]:
try:
ipos = pAtms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
except KeyError:
continue
if all(ids):
angle = [list(ids),['1','1','1'],Value,Esd]
if angle not in angleRestData['Angles']:
angleRestData['Angles'].append(angle)
ids = [0,0,0]
macStr = macro.readline()
macro.close()
print(' Found %d angle restraints'%len(angleRestData['Angles']))
UpdateAngleRestr(angleRestData)
def AddMogulAngleRestraint(angleRestData):
mogul,colNums = getMOGULFile()
for line in mogul:
items = line.split(',')
if 'angle' == items[colNums[0]]:
aName,bName,cName = items[colNums[1]].split()
aInd = Names.index(aName)
bInd = Names.index(bName)
cInd = Names.index(cName)
if items[colNums[2]] != 'No hits':
angle = float(items[colNums[4]])
esd = float(items[colNums[5]])
else:
angle = float(items[colNums[3]])
esd = 2.00
newAngle = [[Ids[aInd],Ids[bInd],Ids[cInd]],['1','1','1'],angle,esd]
if newAngle not in angleRestData['Angles']:
angleRestData['Angles'].append(newAngle)
UpdateAngleRestr(angleRestData)
def AddPlaneRestraint(restrData):
ids = []
dlg = G2G.G2MultiChoiceDialog(G2frame,'Select 4 or more atoms for plane in '+General['Name'],
'Select 4+ atoms',Names[iBeg:])
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelections()
if len(sel) > 3:
for x in sel:
ids.append(Ids[x+iBeg])
ops = ['1' for i in range(len(sel))]
plane = [ids,ops,0.0,0.01]
if plane not in restrData['Planes']:
restrData['Planes'].append(plane)
else:
print ('**** ERROR - not enough atoms for a plane restraint - try again ****')
UpdatePlaneRestr(restrData)
def AddAAPlaneRestraint(planeRestData):
macro = getMacroFile('plane')
if not macro:
return
Chains = makeChains(Names,Ids)
macStr = macro.readline()
while macStr:
items = macStr.split()
if 'F' in items[0]:
restrData['Plane']['wtFactor'] = float(items[1])
elif 'S' in items[0]:
Res = items[1]
Esd = float(items[2])
Atms = items[3:]
pAtms = ['' for i in Atms]
for i,atm in enumerate(Atms):
if '+' in atm:
pAtms[i] = atm.strip('+')
ids = [0,]*len(Atms)
ops = ['1' for i in range(len(Atms))]
chains = list(Chains.keys())
chains.sort()
for chain in chains:
residues = list(Chains[chain].keys())
residues.sort()
for residue in residues:
for ires in [0,1]:
if residue == residues[-1] and Res == '*':
continue
if Res != '*': #works with disordered res
for res,name,Id in Chains[chain][residue][ires]:
if Res == res:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
else:
try:
for res,name,Id in Chains[chain][residue][ires]:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
for res,name,Id in Chains[chain][residue+1][ires]:
try:
ipos = pAtms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
except KeyError:
continue
if all(ids):
plane = [list(ids),ops,0.0,Esd]
if plane not in planeRestData['Planes']:
planeRestData['Planes'].append(plane)
ids = [0,]*len(Atms)
macStr = macro.readline()
macro.close()
print(' Found %d plane restraints'%len(planeRestData['Planes']))
UpdatePlaneRestr(planeRestData)
def AddAAChiralRestraint(chiralRestData):
macro = getMacroFile('chiral')
if not macro:
return
Chains = makeChains(Names,Ids)
macStr = macro.readline()
while macStr:
items = macStr.split()
if 'F' in items[0]:
restrData['Chiral']['wtFactor'] = float(items[1])
elif 'S' in items[0]:
Res = items[1]
Value = float(items[2])
Esd = float(items[3])
Atms = items[4:8]
ids = [0,0,0,0]
chains = list(Chains.keys())
chains.sort()
for chain in chains:
residues = list(Chains[chain].keys())
residues.sort()
for residue in residues:
for ires in [0,1]:
if residue == residues[-1] and Res == '*':
continue
if Res != '*': #works with disordered res
for res,name,Id in Chains[chain][residue][ires]:
if Res == res:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
else:
try:
for res,name,Id in Chains[chain][residue][ires]:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
except KeyError:
continue
if all(ids):
chiral = [list(ids),['1','1','1','1'],Value,Esd]
if chiral not in chiralRestData['Volumes']:
chiralRestData['Volumes'].append(chiral)
ids = [0,0,0,0]
macStr = macro.readline()
macro.close()
print(' Found %d chiral volumes restraints'%len(chiralRestData['Volumes']))
UpdateChiralRestr(chiralRestData)
def AddAATorsionRestraint(torsionRestData):
macro = getMacroFile('torsion')
if not macro:
return
Chains = makeChains(Names,Ids)
macStr = macro.readline()[:-1]
while macStr:
items = macStr.split()
if 'F' in items[0]:
restrData['Torsion']['wtFactor'] = float(items[1])
elif 'A' in items[0]:
name = items[10]
coeff = np.zeros(9)
for i,item in enumerate(items[1:10]):
coeff[i] = float(item)
torsionRestData['Coeff'][name] = coeff
elif 'S' in items[0]:
Name = items[1]
Res = items[2]
Esd = float(items[3])
Atms = items[4:8]
pAtms = ['','','','']
for i,atm in enumerate(Atms):
if '+' in atm:
pAtms[i] = atm.strip('+')
ids = [0,0,0,0]
chains = list(Chains.keys())
chains.sort()
for chain in chains:
residues = list(Chains[chain].keys())
residues.sort()
for residue in residues:
for ires in [0,1]:
if residue == residues[-1] and Res == '*':
continue
if Res != '*': #works with disordered res
for res,name,Id in Chains[chain][residue][ires]:
if Res == res:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
else:
try:
for res,name,Id in Chains[chain][residue][ires]:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
for res,name,Id in Chains[chain][residue+1][ires]:
try:
ipos = pAtms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
except KeyError:
continue
if all(ids):
torsion = [list(ids),['1','1','1','1'],Name,Esd]
if torsion not in torsionRestData['Torsions']:
torsionRestData['Torsions'].append(torsion)
ids = [0,0,0,0]
macStr = macro.readline()
macro.close()
print(' Found %d torsion restraints'%len(torsionRestData['Torsions']))
UpdateTorsionRestr(torsionRestData)
def AddAARamaRestraint(ramaRestData):
macro = getMacroFile('Ramachandran')
if not macro:
return
Chains = makeChains(Names,Ids)
macStr = macro.readline()
while macStr:
items = macStr.split()
if 'F' in items[0]:
restrData['Rama']['wtFactor'] = float(items[1])
elif 'A' in items[0]:
nTerms = int(items[1])
name = items[2]
coeff = np.zeros((nTerms,6))
for i in range(nTerms):
macStr = macro.readline()
items = macStr.split()
for j,val in enumerate(items):
coeff[i][j] = float(val)
ramaRestData['Coeff'][name] = coeff
elif 'S' in items[0]:
Name = items[1]
Res = items[2]
Esd = float(items[3])
Atms = items[4:9]
mAtms = ['','','','','']
pAtms = ['','','','','']
for i,atm in enumerate(Atms):
if '+' in atm:
pAtms[i] = atm.strip('+')
elif '-' in atm:
mAtms[i] = atm.strip('-')
ids = [0,0,0,0,0]
chains = list(Chains.keys())
chains.sort()
for chain in chains:
residues = list(Chains[chain].keys())
residues.sort()
if not (any(mAtms) or any(pAtms)):
for residue in residues:
for ires in [0,1]:
for res,name,Id in Chains[chain][residue][ires]:
if Res == res:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
if all(ids):
rama = [list(ids),['1','1','1','1','1'],Name,Esd]
if rama not in ramaRestData['Ramas']:
ramaRestData['Ramas'].append(rama)
ids = [0,0,0,0,0]
else:
for ires,residue in enumerate(residues[1:-1]):
for jres in [0,1]:
try:
for res,name,Id in Chains[chain][residue-1][jres]:
try:
ipos = mAtms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
for res,name,Id in Chains[chain][residue+1][jres]:
try:
ipos = pAtms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
for res,name,Id in Chains[chain][residue][jres]:
if Res == res:
try:
ipos = Atms.index(name[:3].strip())
ids[ipos] = Id
except ValueError:
continue
if all(ids):
rama = [list(ids),['1','1','1','1','1'],Name,Esd]
if rama not in ramaRestData['Ramas']:
ramaRestData['Ramas'].append(rama)
ids = [0,0,0,0,0]
except KeyError:
continue
macStr = macro.readline()
macro.close()
print(' Found %d Ramachandran restraints'%len(ramaRestData['Ramas']))
UpdateRamaRestr(ramaRestData)
def AddChemCompRestraint(chemcompRestData):
ids = []
factors = []
dlg = G2G.G2MultiChoiceDialog(G2frame,'Select atoms for chemical restraint in '+General['Name'],
'Select atoms',Names)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelections()
for x in sel:
if 'all' in Names[x]:
allType = Types[x]
for name,Type,Id in zip(Names,Types,Ids):
if Type == allType and 'all' not in name:
ids.append(Id)
factors.append(1.0)
else:
ids.append(Ids[x])
factors.append(1.0)
dlg.Destroy()
if len(ids) > 0:
value = 1.0
dlg = G2G.SingleFloatDialog(G2frame,'Cell sum','Enter unit cell sum ',value,[-1.e6,1.e6],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
value = dlg.GetValue()
comp = [ids,factors,value,0.01]
if comp not in chemcompRestData['Sites']:
chemcompRestData['Sites'].append(comp)
UpdateChemcompRestr(chemcompRestData)
else:
print ('**** ERROR - not enough atoms for a composition restraint - try again ****')
def AddMomentRestraint(momentRestData):
ids = []
dlg = G2G.G2MultiChoiceDialog(G2frame,'Select 2 or more atoms for average moment restraint in '+General['Name'],
'Select 2+ atoms',Names[iBeg:])
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelections()
if len(sel) > 1:
for x in sel:
ids.append(Ids[x+iBeg])
moment = [ids,0.0,0.01]
if moment not in momentRestData['Moments']:
momentRestData['Moments'].append(moment)
else:
print ('**** ERROR - not enough atoms for a average moment restraint - try again ****')
UpdateMomentRestr(momentRestData)
def AddTextureRestraint(textureRestData):
dlg = wx.TextEntryDialog(G2frame,'Enter h k l for pole figure restraint','Enter HKL','')
if dlg.ShowModal() == wx.ID_OK:
text = dlg.GetValue()
vals = text.split()
try:
hkl = [int(vals[i]) for i in range(3)]
texture = [hkl,24,0.01,False,1.0]
if texture not in textureRestData['HKLs']:
textureRestData['HKLs'].append(texture)
UpdateTextureRestr(textureRestData)
except (ValueError,IndexError):
print ('**** ERROR - bad input of h k l - try again ****')
dlg.Destroy()
def WtBox(wind,restData):
if 'Range' not in restData: restData['Range'] = 1.1 #patch
def OnUseData(event):
Obj = event.GetEventObject()
restData['Use'] = Obj.GetValue()
wtBox = wx.BoxSizer(wx.HORIZONTAL)
wtBox.Add(wx.StaticText(wind,-1,'Phase '+phaseName+' Restraint weight factor: '),0,WACV)
wtfactor = G2G.ValidatedTxtCtrl(wind,restData,'wtFactor',nDig=(10,2),typeHint=float)
wtBox.Add(wtfactor,0,WACV)
useData = wx.CheckBox(wind,-1,label=' Use?')
useData.Bind(wx.EVT_CHECKBOX, OnUseData)
useData.SetValue(restData['Use'])
wtBox.Add(useData,0,WACV)
if 'Bonds' in restData or 'Angles' in restData:
wtBox.Add(wx.StaticText(wind,-1,' Search range: '),0,WACV)
sRange = G2G.ValidatedTxtCtrl(wind,restData,'Range',nDig=(10,2),typeHint=float)
wtBox.Add(sRange,0,WACV)
wtBox.Add(wx.StaticText(wind,-1,' x sum(atom radii)'),0,WACV)
return wtBox
def OnRowSelect(event):
r,c = event.GetRow(),event.GetCol()
Obj = event.GetEventObject()
if r < 0 and c < 0:
if Obj.IsSelection():
Obj.ClearSelection()
else:
for row in range(Obj.GetNumberRows()):
Obj.SelectRow(row,True)
elif c < 0: #only row clicks
if event.ControlDown():
if r in Obj.GetSelectedRows():
Obj.DeselectRow(r)
else:
Obj.SelectRow(r,True)
elif event.ShiftDown():
indxs = Obj.GetSelectedRows()
Obj.ClearSelection()
ibeg = 0
if indxs:
ibeg = indxs[-1]
for row in range(ibeg,r+1):
Obj.SelectRow(row,True)
else:
Obj.ClearSelection()
Obj.SelectRow(r,True)
def UpdateBondRestr(bondRestData):
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
new = float(bondTable.GetValue(r,c))
if new <= 0.:
raise ValueError
bondRestData['Bonds'][r][c] = new
except ValueError:
pass
wx.CallAfter(UpdateBondRestr,bondRestData)
def OnChangeValue(event):
rows = GetSelectedRows(Bonds)
if not rows:
return
Bonds.ClearSelection()
val = bondList[rows[0]][2]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new value for bond',val,[0.,5.],'%.4f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
bondRestData['Bonds'][r][2] = parm
dlg.Destroy()
UpdateBondRestr(bondRestData)
def OnChangeEsd(event):
rows = GetSelectedRows(Bonds)
if not rows:
return
Bonds.ClearSelection()
val = bondList[rows[0]][3]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for bond',val,[0.,1.],'%.4f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
bondRestData['Bonds'][r][3] = parm
dlg.Destroy()
UpdateBondRestr(bondRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(Bonds,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
Bonds.ClearSelection()
rows.sort()
rows.reverse()
for row in rows:
bondList.remove(bondList[row])
UpdateBondRestr(bondRestData)
try:
if BondRestr.GetSizer(): BondRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(BondRestr,bondRestData),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
bondList = bondRestData['Bonds']
if len(bondList) and len(bondList[0]) == 6: #patch
bondList = bondRestData['Bonds'] = []
if len(bondList):
table = []
rowLabels = []
bad = []
chisq = 0.
Types = [wg.GRID_VALUE_STRING,]+4*[wg.GRID_VALUE_FLOAT+':10,3',]
if 'macro' in General['Type']:
colLabels = ['(res) A - (res) B','calc','target','esd','delt/sig']
for i,[indx,ops,obs,esd] in enumerate(bondList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = ''
for atom in atoms:
name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
calc = G2mth.getRestDist(XYZ,Amat)
chisq += bondRestData['wtFactor']*((obs-calc)/esd)**2
table.append([name[:-3],calc,obs,esd,(obs-calc)/esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
else:
colLabels = ['A+SymOp - B+SymOp','calc','target','esd','delt/sig']
for i,[indx,ops,obs,esd] in enumerate(bondList):
try:
names = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
calc = G2mth.getRestDist(XYZ,Amat)
chisq += bondRestData['wtFactor']*((obs-calc)/esd)**2
table.append([names[0]+'+('+ops[0]+') - '+names[1]+'+('+ops[1]+')',calc,obs,esd,(obs-calc)/esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del bondList[ibad]
if len(bondList):
bondTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Bonds = G2G.GSGrid(BondRestr)
Bonds.SetTable(bondTable, True)
Bonds.AutoSizeColumns(False)
for c in [0,1,4]: # format read-only rows
attr = wx.grid.GridCellAttr()
attr.IncRef()
attr.SetBackgroundColour(VERY_LIGHT_GREY)
attr.SetReadOnly(True)
Bonds.SetColAttr(c, attr)
Bonds.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
Bonds.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
Bonds.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
G2frame.Bind(wx.EVT_MENU, OnChangeValue, id=G2G.wxID_RESRCHANGEVAL)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(BondRestr,wx.ID_ANY,
f'Bond restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(bondList):.2f}'
),0)
Bonds.SetScrollRate(10,10)
Bonds.SetMinSize((-1,300))
mainSizer.Add(Bonds,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(BondRestr,-1,'No bond distance restraints for this phase'),0,)
else:
mainSizer.Add(wx.StaticText(BondRestr,-1,'No bond distance restraints for this phase'),0,)
wx.CallAfter(G2phsGUI.SetPhaseWindow,BondRestr,mainSizer,Scroll=0)
def UpdateAngleRestr(angleRestData):
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
new = float(angleTable.GetValue(r,c))
if new <= 0. or new > 180.:
raise ValueError
angleRestData['Angles'][r][c] = new
except ValueError:
pass
wx.CallAfter(UpdateAngleRestr,angleRestData)
def OnChangeValue(event):
rows = GetSelectedRows(Angles)
if not rows:
return
Angles.ClearSelection()
val = angleList[rows[0]][2]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new value for angle',val,[0.,360.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
angleRestData['Angles'][r][2] = parm
dlg.Destroy()
UpdateAngleRestr(angleRestData)
def OnChangeEsd(event):
rows = GetSelectedRows(Angles)
if not rows:
return
Angles.ClearSelection()
val = angleList[rows[0]][3]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for angle',val,[0.,5.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
angleRestData['Angles'][r][3] = parm
dlg.Destroy()
UpdateAngleRestr(angleRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(Angles,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
angleList.remove(angleList[row])
UpdateAngleRestr(angleRestData)
try:
if AngleRestr.GetSizer():
AngleRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(AngleRestr,angleRestData),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
angleList = angleRestData['Angles']
if len(angleList):
table = []
rowLabels = []
bad = []
chisq = 0.
Types = [wg.GRID_VALUE_STRING,]+4*[wg.GRID_VALUE_FLOAT+':10,2',]
if 'macro' in General['Type']:
colLabels = ['(res) A - (res) B - (res) C','calc','target','esd','delt/sig']
for i,[indx,ops,obs,esd] in enumerate(angleList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = ''
for atom in atoms:
name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
calc = G2mth.getRestAngle(XYZ,Amat)
chisq += angleRestData['wtFactor']*((obs-calc)/esd)**2
table.append([name[:-3],calc,obs,esd,(obs-calc)/esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
else:
colLabels = ['A+SymOp - B+SymOp - C+SymOp','calc','target','esd','delt/sig']
for i,[indx,ops,obs,esd] in enumerate(angleList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
name = atoms[0]+'+('+ops[0]+') - '+atoms[1]+'+('+ops[1]+') - '+atoms[2]+ \
'+('+ops[2]+')'
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
calc = G2mth.getRestAngle(XYZ,Amat)
chisq += angleRestData['wtFactor']*((obs-calc)/esd)**2
table.append([name,calc,obs,esd,(obs-calc)/esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del angleList[ibad]
if len(angleList):
angleTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Angles = G2G.GSGrid(AngleRestr)
Angles.SetTable(angleTable, True)
Angles.AutoSizeColumns(False)
for c in [0,1,4]: # format readonly columns
attr = wx.grid.GridCellAttr()
attr.IncRef()
attr.SetBackgroundColour(VERY_LIGHT_GREY)
attr.SetReadOnly(True)
Angles.SetColAttr(c, attr)
Angles.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
Angles.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
Angles.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
G2frame.Bind(wx.EVT_MENU, OnChangeValue, id=G2G.wxID_RESRCHANGEVAL)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(AngleRestr,wx.ID_ANY,
f'Angle restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(angleList):.2f}'
),0)
Angles.SetScrollRate(10,10)
Angles.SetMinSize((-1,300))
mainSizer.Add(Angles,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(AngleRestr,-1,'No bond angle restraints for this phase'),0,)
else:
mainSizer.Add(wx.StaticText(AngleRestr,-1,'No bond angle restraints for this phase'),0,)
wx.CallAfter(G2phsGUI.SetPhaseWindow,AngleRestr,mainSizer,Scroll=0)
def UpdatePlaneRestr(planeRestData):
items = G2frame.dataWindow.RestraintEdit.GetMenuItems()
for item in items:
if item.GetItemLabelText() in ['Change value']:
item.Enable(False)
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
new = float(planeTable.GetValue(r,c))
if new <= 0.:
raise ValueError
planeRestData['Planes'][r][c] = new
except ValueError:
pass
wx.CallAfter(UpdatePlaneRestr,planeRestData)
def OnChangeEsd(event):
rows = GetSelectedRows(Planes)
if not rows:
return
Planes.ClearSelection()
val = planeList[rows[0]][3]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for plane',val,[0.,5.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
planeRestData['Planes'][r][3] = parm
dlg.Destroy()
UpdatePlaneRestr(planeRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(Planes,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
planeList.remove(planeList[row])
UpdatePlaneRestr(planeRestData)
try:
if PlaneRestr.GetSizer():
PlaneRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(PlaneRestr,planeRestData),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
planeList = planeRestData['Planes']
if len(planeList):
table = []
rowLabels = []
bad = []
chisq = 0.
Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
if 'macro' in General['Type']:
colLabels = ['(res) atom','calc','target','esd']
for i,[indx,ops,obs,esd] in enumerate(planeList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = ''
for a,atom in enumerate(atoms):
name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
if (a+1)%3 == 0:
name += '\n'
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
calc = G2mth.getRestPlane(XYZ,Amat)
chisq += planeRestData['wtFactor']*((calc)/esd)**2
table.append([name[:-3],calc,obs,esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
else:
colLabels = ['atom+SymOp','calc','target','esd']
for i,[indx,ops,obs,esd] in enumerate(planeList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
calc = G2mth.getRestPlane(XYZ,Amat)
chisq += planeRestData['wtFactor']*((calc)/esd)**2
name = ''
for a,atom in enumerate(atoms):
name += atom+'+ ('+ops[a]+'),'
if (a+1)%3 == 0:
name += '\n'
table.append([name[:-1],calc,obs,esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del planeList[ibad]
if len(planeList):
planeTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Planes = G2G.GSGrid(PlaneRestr)
Planes.SetTable(planeTable, True)
Planes.AutoSizeColumns(False)
Planes.AutoSizeRows(False)
for r in range(len(planeList)):
for c in range(3):
Planes.SetReadOnly(r,c,True)
Planes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
Planes.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
Planes.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
Planes.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(PlaneRestr,-1,
f'Plane restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(planeList):.2f}'
),0)
Planes.SetScrollRate(10,10)
Planes.SetMinSize((-1,300))
mainSizer.Add(Planes,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(PlaneRestr,-1,'No plane restraints for this phase'),0,)
else:
mainSizer.Add(wx.StaticText(PlaneRestr,-1,'No plane restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(PlaneRestr,mainSizer,Scroll=0)
def UpdateChiralRestr(chiralRestData):
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
new = float(volumeTable.GetValue(r,c))
if new <= 0.:
raise ValueError
chiralRestData['Volumes'][r][c] = new
except ValueError:
pass
wx.CallAfter(UpdateChiralRestr,chiralRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(Volumes,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
volumeList.remove(volumeList[row])
UpdateChiralRestr(chiralRestData)
def OnChangeValue(event):
rows = GetSelectedRows(Volumes)
if not rows:
return
Volumes.ClearSelection()
val = volumeList[rows[0]][2]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new value for chiral volume',val,[0.,360.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
chiralRestData['Volumes'][r][2] = parm
dlg.Destroy()
UpdateChiralRestr(chiralRestData)
def OnChangeEsd(event):
rows = GetSelectedRows(Volumes)
if not rows:
return
Volumes.ClearSelection()
val = volumeList[rows[0]][3]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for chiral volume',val,[0.,5.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
chiralRestData['Volumes'][r][3] = parm
dlg.Destroy()
UpdateChiralRestr(chiralRestData)
try:
if ChiralRestr.GetSizer(): ChiralRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(ChiralRestr,chiralRestData),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
volumeList = chiralRestData['Volumes']
if len(volumeList):
table = []
rowLabels = []
bad = []
chisq = 0.
Types = [wg.GRID_VALUE_STRING,]+4*[wg.GRID_VALUE_FLOAT+':10,2',]
if 'macro' in General['Type']:
colLabels = ['(res) O (res) A (res) B (res) C','calc','target','esd','delt/sig']
for i,[indx,ops,obs,esd] in enumerate(volumeList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = ''
for atom in atoms:
name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
calc = G2mth.getRestChiral(XYZ,Amat)
chisq += chiralRestData['wtFactor']*((obs-calc)/esd)**2
table.append([name,calc,obs,esd,(obs-calc)/esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
else:
colLabels = ['O+SymOp A+SymOp B+SymOp C+SymOp)','calc','target','esd','delt/sig']
for i,[indx,ops,obs,esd] in enumerate(volumeList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
name = atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
'+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')'
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
calc = G2mth.getRestChiral(XYZ,Amat)
chisq += chiralRestData['wtFactor']*((obs-calc)/esd)**2
table.append([name,calc,obs,esd,(obs-calc)/esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del volumeList[ibad]
if len(volumeList):
volumeTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Volumes = G2G.GSGrid(ChiralRestr)
Volumes.SetTable(volumeTable, True)
Volumes.AutoSizeColumns(False)
for r in range(len(volumeList)):
for c in [0,1,4]:
Volumes.SetReadOnly(r,c,True)
Volumes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
Volumes.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
Volumes.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
Volumes.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnChangeValue, id=G2G.wxID_RESRCHANGEVAL)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(ChiralRestr,-1,
f'Chiral volume restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(volumeList):.2f}'
),0)
Volumes.SetScrollRate(10,10)
Volumes.SetMinSize((-1,300))
mainSizer.Add(Volumes,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(ChiralRestr,-1,'No chiral volume restraints for this phase'),0,)
else:
mainSizer.Add(wx.StaticText(ChiralRestr,-1,'No chiral volume restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(ChiralRestr,mainSizer,Scroll=0)
def UpdateTorsionRestr(torsionRestData):
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
new = float(torsionTable.GetValue(r,c))
if new <= 0. or new > 5.:
raise ValueError
torsionRestData['Torsions'][r][3] = new #only esd is editable
except ValueError:
pass
wx.CallAfter(UpdateTorsionRestr,torsionRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(TorsionRestr.Torsions,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
torsionList.remove(torsionList[row])
wx.CallAfter(UpdateTorsionRestr,torsionRestData)
def OnChangeEsd(event):
rows = GetSelectedRows(TorsionRestr.Torsions)
if not rows:
return
TorsionRestr.Torsions.ClearSelection()
val = torsionList[rows[0]][4]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for torsion restraints',val,[0.,5.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
torsionRestData['Torsions'][r][4] = parm
dlg.Destroy()
wx.CallAfter(UpdateTorsionRestr,torsionRestData)
def coeffSizer():
table = []
rowLabels = []
Types = 9*[wg.GRID_VALUE_FLOAT+':10,4',]
colLabels = ['Mag A','Pos A','Width A','Mag B','Pos B','Width B','Mag C','Pos C','Width C']
for item in coeffDict:
rowLabels.append(item)
table.append(coeffDict[item])
coeffTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Coeff = G2G.GSGrid(TorsionRestr)
Coeff.SetScrollRate(0,10)
Coeff.SetTable(coeffTable, True)
Coeff.AutoSizeColumns(False)
for r in range(len(coeffDict)):
for c in range(9):
Coeff.SetReadOnly(r,c,True)
Coeff.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
Coeff.SetMaxSize((-1,200))
return Coeff
try:
if TorsionRestr.GetSizer(): TorsionRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(TorsionRestr,torsionRestData),0)
coeffDict = torsionRestData['Coeff']
torsionList = torsionRestData['Torsions']
if len(coeffDict):
mainSizer.Add((5,5))
mainSizer.Add(wx.StaticText(TorsionRestr,-1,'Torsion function coefficients:'),0)
mainSizer.Add(coeffSizer(),1,wx.EXPAND,1)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
if len(torsionList):
mainSizer.Add(wx.StaticText(TorsionRestr,-1,'Torsion restraints:'),0)
table = []
rowLabels = []
bad = []
chisq = 0.
Types = 2*[wg.GRID_VALUE_STRING,]+4*[wg.GRID_VALUE_FLOAT+':10,2',]
if 'macro' in General['Type']:
colLabels = ['(res) A B C D','coef name','torsion','obs E','restr','esd']
for i,[indx,ops,cofName,esd] in enumerate(torsionList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = '('+atoms[2][1]+atoms[2][0].strip()+atoms[2][2]+')'
for atom in atoms:
name += ' '+atom[3]
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
tor = G2mth.getRestTorsion(XYZ,Amat)
restr,calc = G2mth.calcTorsionEnergy(tor,coeffDict[cofName])
chisq += torsionRestData['wtFactor']*(restr/esd)**2
table.append([name,cofName,tor,calc,restr,esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del torsionList[ibad]
torsionTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
TorsionRestr.Torsions = G2G.GSGrid(TorsionRestr)
TorsionRestr.Torsions.SetTable(torsionTable, True)
TorsionRestr.Torsions.AutoSizeColumns(False)
for r in range(len(torsionList)):
for c in range(5):
TorsionRestr.Torsions.SetReadOnly(r,c,True)
TorsionRestr.Torsions.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
TorsionRestr.Torsions.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
TorsionRestr.Torsions.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
TorsionRestr.Torsions.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(TorsionRestr,-1,
f'Torsion restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(torsionList):.2f}'
),0)
TorsionRestr.Torsions.SetScrollRate(10,10)
TorsionRestr.Torsions.SetMinSize((-1,300))
mainSizer.Add(TorsionRestr.Torsions,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(TorsionRestr,-1,'No torsion restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(TorsionRestr,mainSizer,Scroll=0)
def UpdateRamaRestr(ramaRestData):
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
new = float(ramaTable.GetValue(r,c))
if new <= 0. or new > 5.:
raise ValueError
ramaRestData['Ramas'][r][4] = new #only esd is editable
except ValueError:
pass
wx.CallAfter(UpdateRamaRestr,ramaRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(RamaRestr.Ramas,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
ramaList.remove(ramaList[row])
UpdateRamaRestr(ramaRestData)
def OnChangeEsd(event):
rows = GetSelectedRows(RamaRestr.Ramas)
if not rows:
return
RamaRestr.Ramas.ClearSelection()
val = ramaList[rows[0]][4]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for energy',val,[0.,5.],'%.2f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
ramaRestData['Ramas'][r][4] = parm
dlg.Destroy()
UpdateRamaRestr(ramaRestData)
def coeffSizer():
table = []
rowLabels = []
Types = 6*[wg.GRID_VALUE_FLOAT+':10,4',]
colLabels = ['Mag','Pos phi','Pos psi','sig(phi)','sig(psi)','sig(cov)']
for item in coeffDict:
for i,term in enumerate(coeffDict[item]):
rowLabels.append(item+' term:'+str(i))
table.append(term)
coeffTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Coeff = G2G.GSGrid(RamaRestr)
Coeff.SetScrollRate(0,10)
Coeff.SetTable(coeffTable, True)
Coeff.AutoSizeColumns(False)
for r in range(Coeff.GetNumberRows()):
for c in range(6):
Coeff.SetReadOnly(r,c,True)
Coeff.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
Coeff.SetMaxSize((-1,200))
return Coeff
try:
if RamaRestr.GetSizer(): RamaRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(RamaRestr,ramaRestData),0)
ramaList = ramaRestData['Ramas']
coeffDict = ramaRestData['Coeff']
if len(coeffDict):
mainSizer.Add(wx.StaticText(RamaRestr,-1,'Ramachandran function coefficients:'),0)
mainSizer.Add(coeffSizer(),1,wx.EXPAND,1)
if len(ramaList):
mainSizer.Add(wx.StaticText(RamaRestr,-1,'Ramachandran restraints:'),0)
table = []
rowLabels = []
bad = []
chisq = 0.
Types = 2*[wg.GRID_VALUE_STRING,]+5*[wg.GRID_VALUE_FLOAT+':10,2',]
if 'macro' in General['Type']:
colLabels = ['(res) A B C D E','coef name','phi','psi','obs E','restr','esd']
for i,[indx,ops,cofName,esd] in enumerate(ramaList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
name = '('+atoms[3][1]+atoms[3][0].strip()+atoms[3][2]+')'
for atom in atoms:
name += ' '+atom[3]
XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
phi,psi = G2mth.getRestRama(XYZ,Amat)
restr,calc = G2mth.calcRamaEnergy(phi,psi,coeffDict[cofName])
chisq += ramaRestData['wtFactor']*(restr/esd)**2
table.append([name,cofName,phi,psi,calc,restr,esd])
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del ramaList[ibad]
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
if len(ramaList):
ramaTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
RamaRestr.Ramas = G2G.GSGrid(RamaRestr)
RamaRestr.Ramas.SetTable(ramaTable, True)
RamaRestr.Ramas.AutoSizeColumns(False)
for r in range(len(ramaList)):
for c in range(6):
RamaRestr.Ramas.SetReadOnly(r,c,True)
RamaRestr.Ramas.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
RamaRestr.Ramas.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
RamaRestr.Ramas.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
RamaRestr.Ramas.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(RamaRestr,-1,
f'Ramachandran restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(ramaList):.2f}'
),0)
RamaRestr.Ramas.SetScrollRate(10,10)
RamaRestr.Ramas.SetMinSize((-1,300))
mainSizer.Add(RamaRestr.Ramas,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(RamaRestr,-1,'No Ramachandran restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(RamaRestr,mainSizer,Scroll=0)
def UpdateChemcompRestr(chemcompRestData):
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
rowLabl = ChemComps.GetRowLabelValue(r)
row = int(rowLabl.split(':')[1])
if 'Restr' in rowLabl:
try:
new = float(chemcompTable.GetValue(r,c))
chemcompRestData['Sites'][row][c-2] = new #obsd or esd
except ValueError:
pass
else:
try:
new = float(chemcompTable.GetValue(r,c))
id = int(rowLabl.split(':')[2])
chemcompRestData['Sites'][row][1][id] = new #only factor
except ValueError:
pass
wx.CallAfter(UpdateChemcompRestr,chemcompRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(ChemComps,'delete',G2frame)
#rows = ChemComps.GetSelectedRows()
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
terms = []
restrs = []
for r in sorted(rows,reverse=True):
rowLabl = ChemComps.GetRowLabelValue(r)
if 'Restr' in rowLabl:
restrs.append(int(rowLabl.split(':')[1]))
else:
terms.append([int(i) for i in rowLabl.split(':')[1:]])
# delete terms first in case someone deletes a term in a restraint to be deleted
for row,term in terms:
del chemcompList[row][0][term]
del chemcompList[row][1][term]
for row in restrs:
del chemcompList[row]
UpdateChemcompRestr(chemcompRestData)
# def OnChangeValue(event):
# rows = GetSelectedRows(ChemComps)
# if not rows:
# return
# ChemComps.ClearSelection()
# dlg = G2G.SingleFloatDialog(G2frame,'New value',
# 'Enter new value for restraint multiplier',1.0,[-1.e6,1.e6],'%.2f')
# if dlg.ShowModal() == wx.ID_OK:
# parm = dlg.GetValue()
# for r in rows:
# rowLabl = ChemComps.GetRowLabelValue(r)
# if 'term' in rowLabl:
# items = rowLabl.split(':')
# chemcompRestData['Sites'][int(items[1])][1][int(items[2])] = parm
# dlg.Destroy()
# UpdateChemcompRestr(chemcompRestData)
try:
if ChemCompRestr.GetSizer(): ChemCompRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(ChemCompRestr,chemcompRestData),0)
mainSizer.Add(wx.StaticText(ChemCompRestr,-1,
'NB: The chemical restraint sum is over the unit cell contents'),0)
mainSizer.Add((5,5),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
chemcompList = chemcompRestData['Sites']
if len(chemcompList):
table = []
rowLabels = []
bad = []
chisq = 0.
Types = [wg.GRID_VALUE_STRING,]+5*[wg.GRID_VALUE_FLOAT+':10,2',]
colLabels = ['Atoms','mul*frac','factor','calc','target','esd']
for i,[indx,factors,obs,esd] in enumerate(chemcompList):
try:
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
frac = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs-1))
mulfrac = mul*frac
calcs = mul*frac*factors
chisq += chemcompRestData['wtFactor']*((obs-np.sum(calcs))/esd)**2
for iatm,[atom,mf,fr,clc] in enumerate(zip(atoms,mulfrac,factors,calcs)):
table.append([atom,mf,fr,clc,'',''])
rowLabels.append('term:'+str(i)+':'+str(iatm))
table.append(['(Sum)','','',np.sum(calcs),obs,esd])
rowLabels.append('Restr:'+str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
if len(bad):
bad.reverse()
for ibad in bad:
del chemcompList[ibad]
if len(chemcompList):
chemcompTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
ChemComps = G2G.GSGrid(ChemCompRestr)
ChemComps.SetTable(chemcompTable, True)
ChemComps.AutoSizeColumns(False)
for r in range(chemcompTable.GetNumberRows()):
for c in range(2):
ChemComps.SetReadOnly(r,c,True)
ChemComps.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
if 'Restr' in ChemComps.GetRowLabelValue(r):
for c in range(4):
ChemComps.SetReadOnly(r,c,True)
ChemComps.SetCellStyle(r,c,VERY_YELLOW,True)
ChemComps.SetCellTextColour(r,1,VERY_YELLOW) # make spurious #'s disappear
ChemComps.SetCellTextColour(r,2,VERY_YELLOW)
else:
for c in [3,4,5]:
ChemComps.SetReadOnly(r,c,True)
ChemComps.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
for c in [4,5]:
ChemComps.SetCellTextColour(r,c,VERY_LIGHT_GREY)
ChemComps.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
ChemComps.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
ChemComps.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
G2frame.dataWindow.RestraintEdit.Enable(id=G2G.wxID_RESTDELETE,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
#G2frame.Bind(wx.EVT_MENU, OnChangeValue, id=G2G.wxID_RESRCHANGEVAL)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(ChemCompRestr,-1,
f'Chemical composition restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(chemcompList):.2f}'
),0)
mainSizer.Add(ChemComps)
else:
mainSizer.Add(wx.StaticText(ChemCompRestr,-1,'No chemical composition restraints for this phase'),0,)
else:
mainSizer.Add(wx.StaticText(ChemCompRestr,-1,'No chemical composition restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(ChemCompRestr,mainSizer,Scroll=0)
def UpdateMomentRestr(momentRestData):
def OnChangeEsd(event):
rows = GetSelectedRows(Moments)
if not rows:
return
Moments.ClearSelection()
val = momentList[rows[0]][-1]
dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new esd for moments',val,[0.,5.],'%.3f')
if dlg.ShowModal() == wx.ID_OK:
parm = dlg.GetValue()
for r in rows:
momentRestData['Moments'][r][-1] = parm
dlg.Destroy()
UpdateMomentRestr(momentRestData)
def OnDeleteRestraint(event):
rows = GetSelectedRows(Moments,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
momentList.remove(momentList[row])
UpdateMomentRestr(momentRestData)
try:
if MomentRestr.GetSizer(): MomentRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(MomentRestr,momentRestData),0)
mainSizer.Add((5,5),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
momentList = momentRestData['Moments']
if len(momentList):
table = []
rowLabels = []
bad = []
chisq = 0.
maxno = 0
for item in momentList:
maxno = max(maxno,len(item[0]))
colLabels = maxno*['atom','calc']+['target','esd']
Types = maxno*[wg.GRID_VALUE_STRING,wg.GRID_VALUE_FLOAT+':10,3']+2*[wg.GRID_VALUE_FLOAT+':10,3',]
for i,[indx,obs,esd] in enumerate(momentList):
try:
sum = 0.
atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
Mom = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx+4,3))
line = []
for a,atom in enumerate(atoms):
calc = G2mth.GetMag(Mom[a],Cell)
sum += calc
line += [atom,calc]
line += (maxno-len(atoms))*['','']
obs = sum/len(atoms)
line += [obs,esd]
for a,atom in enumerate(atoms):
chisq += momentRestData['wtFactor']*((obs-calc)/esd)**2
table.append(line)
rowLabels.append(str(i))
except KeyError:
print ('**** WARNING - missing atom - restraint deleted ****')
bad.append(i)
momentTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Moments = G2G.GSGrid(MomentRestr)
Moments.SetTable(momentTable, True)
Moments.AutoSizeColumns(False)
Moments.AutoSizeRows(False)
for r in range(len(momentList)):
for c in range(maxno*2+1):
Moments.SetReadOnly(r,c,True)
Moments.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
if not c%2 and not Moments.GetCellValue(r,c):
Moments.SetCellTextColour(r,c+1,VERY_LIGHT_GREY)
Moments.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
G2frame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2G.wxID_RESTCHANGEESD)
frac = '?'
if 'chisq' in Rvals:
frac = f"{100 * chisq / Rvals['chisq']:.1f}"
mainSizer.Add(wx.StaticText(MomentRestr,-1,
f'Moment restraints: sum(wt*(delt/sig)^2) = {chisq:.2f} ({frac}% of total), mean(wt*(delt/sig)^2) = {chisq/len(momentList):.2f}'
),0)
Moments.SetScrollRate(10,10)
Moments.SetMinSize((-1,300))
mainSizer.Add(Moments,1,wx.EXPAND,1)
else:
mainSizer.Add(wx.StaticText(MomentRestr,-1,'No magnetic moment restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(MomentRestr,mainSizer,Scroll=0)
def UpdateTextureRestr(textureRestData):
def OnDeleteRestraint(event):
rows = GetSelectedRows(Textures,'delete',G2frame)
G2frame.GetStatusBar().SetStatusText('',1)
if not rows:
G2frame.GetStatusBar().SetStatusText('First select restraints to be deleted',1)
return
rows.sort()
rows.reverse()
for row in rows:
textureList.remove(textureList[row])
wx.CallAfter(UpdateTextureRestr,textureRestData)
def OnCellChange(event):
r,c = event.GetRow(),event.GetCol()
try:
if c == 1: #grid size
new = int(textureTable.GetValue(r,c))
if new < 6 or new > 24:
raise ValueError
elif c in [2,4]: #esds
new = float(textureTable.GetValue(r,c))
if new < -1. or new > 2.:
raise ValueError
else:
new = textureTable.GetValue(r,c)
textureRestData['HKLs'][r][c] = new
except ValueError:
pass
wx.CallAfter(UpdateTextureRestr,textureRestData)
try:
if TextureRestr.GetSizer(): TextureRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
mainSizer.Add(WtBox(TextureRestr,textureRestData),0)
mainSizer.Add(wx.StaticText(TextureRestr,-1,
'NB: The texture restraints suppress negative pole figure values for the selected HKLs\n'
' "unit esd" gives a bias toward a flatter polefigure'),0)
mainSizer.Add((5,5),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
textureList = textureRestData['HKLs']
if len(textureList):
table = []
rowLabels = []
Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_LONG,wg.GRID_VALUE_FLOAT+':10,2',
wg.GRID_VALUE_BOOL,wg.GRID_VALUE_FLOAT+':10,2']
colLabels = ['HKL','grid','neg esd','use unit?','unit esd']
for i,[hkl,grid,esd1,ifesd2,esd2] in enumerate(textureList):
table.append(['%d %d %d'%(hkl[0],hkl[1],hkl[2]),grid,esd1,ifesd2,esd2])
rowLabels.append(str(i))
textureTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
Textures = G2G.GSGrid(TextureRestr)
Textures.SetTable(textureTable, True)
Textures.AutoSizeColumns(False)
for r in range(len(textureList)):
Textures.SetReadOnly(r,0,True)
Textures.SetCellStyle(r,0,VERY_LIGHT_GREY,True)
if not textureTable.GetValue(r,3):
Textures.SetReadOnly(r,4,True)
Textures.SetCellStyle(r,4,VERY_LIGHT_GREY,True)
Textures.SetCellTextColour(r,4,VERY_LIGHT_GREY)
Textures.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
if 'phoenix' in wx.version():
Textures.Bind(wg.EVT_GRID_CELL_CHANGED, OnCellChange)
else:
Textures.Bind(wg.EVT_GRID_CELL_CHANGE, OnCellChange)
G2frame.dataWindow.RestraintEdit.Enable(id=G2G.wxID_RESTDELETE,enable=True)
G2frame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2G.wxID_RESTDELETE)
mainSizer.Add(Textures,0,)
else:
mainSizer.Add(wx.StaticText(TextureRestr,-1,'No texture restraints for this phase'),0,)
G2phsGUI.SetPhaseWindow(TextureRestr,mainSizer,Scroll=0)
def UpdateGeneralRestr(generalRestData):
'''Display any generalized restraint expressions'''
def OnEditGenRestraint(event):
'''Edit a restraint expression'''
n = event.GetEventObject().index
parmDict = SetupParmDict(G2frame)
dlg = G2exG.ExpressionDialog(G2frame,parmDict,
exprObj=generalRestData['General'][n][0],
header="Edit a restraint expression",
fit=False,wildCard=G2frame.testSeqRefineMode())
restobj = dlg.Show(True)
if restobj:
generalRestData['General'][n][0] = restobj
wx.CallAfter(UpdateGeneralRestr,restrData['General'])
def OnDelGenRestraint(event): #does this work??
'''Delete a restraint expression'''
n = event.GetEventObject().index
del restrData['General']['General'][n]
wx.CallAfter(UpdateGeneralRestr,restrData['General'])
try:
if GeneralRestr.GetSizer(): GeneralRestr.GetSizer().Clear(True)
except:
pass
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add((5,5),0)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
hSizer.Add(wx.StaticText(GeneralRestr,wx.ID_ANY,'Weight factor: '))
hSizer.Add(G2G.ValidatedTxtCtrl(GeneralRestr,generalRestData,
'wtFactor',nDig=(10,1),typeHint=float))
btn = G2G.G2CheckBox(GeneralRestr,'Use?',generalRestData,'Use')
hSizer.Add(btn)
hSizer.Add((5,5),0)
btn = wx.Button(GeneralRestr, wx.ID_ANY,"Add restraint")
btn.Bind(wx.EVT_BUTTON,OnAddRestraint)
hSizer.Add(btn,0,wx.EXPAND|wx.ALL)
mainSizer.Add(hSizer,0)
mainSizer.Add((5,5),0)
for i in (G2G.wxID_RESTDELETE,G2G.wxID_RESRCHANGEVAL,G2G.wxID_RESTCHANGEESD):
G2frame.dataWindow.RestraintEdit.Enable(id=i,enable=False)
if generalRestData['General']:
parmDict = SetupParmDict(G2frame)
GridSiz = wx.FlexGridSizer(0,9,10,2)
GridSiz.Add((-1,-1))
GridSiz.Add(
wx.StaticText(GeneralRestr,wx.ID_ANY,'Expression'),
0,wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
GridSiz.Add((-1,-1))
# for lbl in ('expression',' ','target\nvalue','current\nvalue','esd'):
for lbl in ('target\nvalue','current\nvalue','esd'):
GridSiz.Add(
wx.StaticText(GeneralRestr,wx.ID_ANY,lbl,style=wx.CENTER),
0,wx.ALIGN_CENTER)
GridSiz.Add((-1,-1))
GridSiz.Add((-1,-1))
GridSiz.Add(
wx.StaticText(GeneralRestr,wx.ID_ANY,'Variables',style=wx.CENTER),
0,wx.ALIGN_CENTER)
for i,rest in enumerate(generalRestData['General']):
eq = rest[0]
txt = '{}: '.format(i+1)
GridSiz.Add(wx.StaticText(GeneralRestr,wx.ID_ANY,txt))
txt = eq.expression
if len(txt) > 50:
txt = txt[:47]+'... '
txtC = wx.StaticText(GeneralRestr,wx.ID_ANY,txt)
GridSiz.Add(txtC)
GridSiz.Add(wx.StaticText(GeneralRestr,wx.ID_ANY,' = '))
GridSiz.Add(
G2G.ValidatedTxtCtrl(GeneralRestr,rest,1,nDig=(10,3,'g'),typeHint=float)
)
# evaluate the expression
try:
calcobj = G2obj.ExpressionCalcObj(rest[0])
calcobj.SetupCalc(parmDict)
txt = ' {:f} '.format(calcobj.EvalExpression())
except:
txt = ' (error) '
txtC.SetForegroundColour("red")
GridSiz.Add(wx.StaticText(GeneralRestr,wx.ID_ANY,txt))
GridSiz.Add(
G2G.ValidatedTxtCtrl(GeneralRestr,rest,2,nDig=(10,3,'g'),typeHint=float)
)
btn = wx.Button(GeneralRestr, wx.ID_ANY,"Edit",size=(40,-1))
btn.index = i
btn.Bind(wx.EVT_BUTTON,OnEditGenRestraint)
GridSiz.Add(btn)
btn = wx.Button(GeneralRestr, wx.ID_ANY,"Delete",size=(60,-1))
btn.index = i
btn.Bind(wx.EVT_BUTTON,OnDelGenRestraint)
GridSiz.Add(btn)
txt = ''
for i in eq.assgnVars:
if txt: txt += '; '
txt += str(i) + '=' + str(eq.assgnVars[i])
if len(txt) > 50:
txt = txt[:47]+'...'
GridSiz.Add(wx.StaticText(GeneralRestr,wx.ID_ANY,txt))
mainSizer.Add(GridSiz)
G2phsGUI.SetPhaseWindow(GeneralRestr,mainSizer,Scroll=0)
def OnPageChanged(event):
page = event.GetSelection()
#G2frame.restrBook.SetSize(G2frame.dataWindow.GetClientSize()) #TODO -almost right
text = G2frame.restrBook.GetPageText(page)
G2frame.dataWindow.RestraintEdit.SetLabel(G2G.wxID_RESRCHANGEVAL,'Change value')
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_USEMOGUL,False)
if text == 'Bond':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_USEMOGUL,True)
bondRestData = restrData['Bond']
UpdateBondRestr(bondRestData)
elif text == 'Angle':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_USEMOGUL,True)
angleRestData = restrData['Angle']
UpdateAngleRestr(angleRestData)
elif text == 'Plane':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,False)
planeRestData = restrData['Plane']
UpdatePlaneRestr(planeRestData)
elif text == 'Chiral':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,False)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,True)
chiralRestData = restrData['Chiral']
UpdateChiralRestr(chiralRestData)
elif text == 'Torsion':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,False)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,False)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_AARESTRAINTPLOT,True)
torsionRestData = restrData['Torsion']
UpdateTorsionRestr(torsionRestData)
elif text == 'Ramachandran':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,False)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,False)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_AARESTRAINTPLOT,True)
ramaRestData = restrData['Rama']
UpdateRamaRestr(ramaRestData)
wx.CallAfter(G2plt.PlotRama,G2frame,phaseName,rama,ramaName)
elif text == 'Chem. comp.':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.SetLabel(G2G.wxID_RESRCHANGEVAL,'Change factor')
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTCHANGEESD,False)
chemcompRestData = restrData['ChemComp']
UpdateChemcompRestr(chemcompRestData)
elif text == 'Texture':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,True)
textureRestData = restrData['Texture']
UpdateTextureRestr(textureRestData)
elif text == 'Moments':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,True)
momentRestData = restrData['Moments']
UpdateMomentRestr(momentRestData)
elif text == 'General':
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESRCHANGEVAL,False)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_RESTCHANGEESD,False)
UpdateGeneralRestr(restrData['General'])
event.Skip()
# def RaisePage(event):
# 'Respond to a "select tab" menu button'
# # class PseudoEvent(object):
# # def __init__(self,page): self.page = page
# # def Skip(self): pass
# # def GetSelection(self): return self.page
# try:
# i = tabIndex.get(event.GetId())
# G2frame.restrBook.SetSelection(i)
# #OnPageChanged(PseudoEvent(i))
# except ValueError:
# print('Unexpected event in RaisePage')
#
def OnSelectPage(event):
'Called when an item is selected from the Select page menu'
# lookup the menu item that called us and get its text
tabname = TabSelectionIdDict.get(event.GetId())
if not tabname:
print ('Warning: menu item not in dict! id= %d'%event.GetId())
return
# find the matching tab
for PageNum in range(G2frame.restrBook.GetPageCount()):
if tabname == G2frame.restrBook.GetPageText(PageNum):
G2frame.restrBook.SetSelection(PageNum)
return
else:
print ("Warning: tab "+tabname+" was not found")
#### UpdateRestraints execution starts here
covdata = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Covariance'))
Nvars = 0
Rvals = {}
if 'Rvals' in covdata:
Nvars = len(covdata['varyList'])
Rvals = covdata['Rvals']
try:
phasedata = G2frame.GetPhaseData()[phaseName]
except KeyError: #delete unknown or previously deleted phases from Restraints
# deleting phase without refresh can cause wx to crash
#rId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Restraints')
#pId = G2gd.GetGPXtreeItemId(G2frame,rId,phaseName)
#G2frame.GPXtree.Delete(pId)
print('Unknown phase '+phaseName+' is deleted from Restraints')
G2frame.dataWindow.GetSizer().Add(
wx.StaticText(G2frame.dataWindow,-1,' Phase does not exist'),0)
return
restrData = data[phaseName]
if 'Bond' not in restrData:
restrData['Bond'] = {'wtFactor':1.0,'Range':1.1,'Bonds':[],'Use':True}
if 'Angle' not in restrData:
restrData['Angle'] = {'wtFactor':1.0,'Range':0.85,'Angles':[],'Use':True}
if 'Plane' not in restrData:
restrData['Plane'] = {'wtFactor':1.0,'Planes':[],'Use':True}
if 'Chiral' not in restrData:
restrData['Chiral'] = {'wtFactor':1.0,'Volumes':[],'Use':True}
if 'Torsion' not in restrData:
restrData['Torsion'] = {'wtFactor':1.0,'Coeff':{},'Torsions':[],'Use':True}
if 'Rama' not in restrData:
restrData['Rama'] = {'wtFactor':1.0,'Coeff':{},'Ramas':[],'Use':True}
if 'Texture' not in restrData:
restrData['Texture'] = {'wtFactor':1.0,'HKLs':[],'Use':True}
if 'ChemComp' not in restrData:
restrData['ChemComp'] = {'wtFactor':1.0,'Sites':[],'Use':True}
if 'General' not in restrData:
restrData['General'] = {'wtFactor':1.0,'General':[], 'Use':True}
General = phasedata['General']
if General['Type'] == 'magnetic' and 'Moments' not in restrData:
restrData['Moments'] = {'wtFactor':1.0,'Moments':[],'Use':True}
Cell = General['Cell'][1:7] #skip flag & volume
Amat,Bmat = G2lat.cell2AB(Cell)
SGData = General['SGData']
cx,ct,cs,cia = General['AtomPtrs']
Atoms = phasedata['Atoms']
AtLookUp = G2mth.FillAtomLookUp(Atoms,cia+8)
if 'macro' in General['Type']:
Names = [atom[0]+':'+atom[1]+atom[2]+' '+atom[3].ljust(4) for atom in Atoms]
Ids = []
Coords = []
Types = []
iBeg = 0
else:
Names = ['all '+ name for name in General['AtomTypes']]
iBeg = len(Names)
Types = [name for name in General['AtomTypes']]
Coords = [ [] for type in Types]
Ids = [ 0 for type in Types]
Names += [atom[ct-1] for atom in Atoms]
Types += [atom[ct] for atom in Atoms]
Coords += [atom[cx:cx+3] for atom in Atoms]
Ids += [atom[cia+8] for atom in Atoms]
rama = G2data.ramachandranDist['All']
ramaName = 'All'
G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RestraintMenu)
G2frame.Bind(wx.EVT_MENU, OnAddRestraint, id=G2G.wxID_RESTRAINTADD)
G2frame.Bind(wx.EVT_MENU, OnUseMogul, id=G2G.wxID_USEMOGUL)
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_USEMOGUL,True)
if 'macro' in phasedata['General']['Type']:
G2frame.dataWindow.RestraintEdit.Enable(G2G.wxID_AARESTRAINTADD,True)
G2frame.Bind(wx.EVT_MENU, OnAddAARestraint, id=G2G.wxID_AARESTRAINTADD)
G2frame.Bind(wx.EVT_MENU, OnPlotAARestraint, id=G2G.wxID_AARESTRAINTPLOT)
# GUI defined here
G2frame.restrBook = G2G.GSNoteBook(parent=G2frame.dataWindow)
G2frame.dataWindow.GetSizer().Add(G2frame.restrBook,1,wx.ALL|wx.EXPAND,1)
# clear menu and menu pointers
Pages = []
txt = 'Bond'
BondRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(BondRestr,txt)
Pages.append(txt)
txt = 'Angle'
AngleRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(AngleRestr,txt)
Pages.append(txt)
txt = 'Plane'
PlaneRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(PlaneRestr,txt)
Pages.append(txt)
txt = 'Chiral'
ChiralRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(ChiralRestr,txt)
Pages.append(txt)
if 'macro' in General['Type']:
txt = 'Torsion'
TorsionRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(TorsionRestr,txt)
Pages.append(txt)
txt = 'Ramachandran'
RamaRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(RamaRestr,txt)
Pages.append(txt)
txt = 'Chem. comp.'
ChemCompRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(ChemCompRestr,txt)
Pages.append(txt)
if 'magnetic' in General['Type']:
txt = 'Moments'
MomentRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(MomentRestr,txt)
Pages.append(txt)
txt = 'General'
GeneralRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(GeneralRestr,txt)
Pages.append(txt)
if General['SH Texture']['Order']:
txt = 'Texture'
TextureRestr = wx.ScrolledWindow(G2frame.restrBook)
G2frame.restrBook.AddPage(TextureRestr,txt)
Pages.append(txt)
UpdateBondRestr(restrData['Bond'])
G2frame.restrBook.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged)
# fill page selection menu
menu = G2frame.dataWindow.RestraintTab
for page in Pages:
if menu.FindItem(page) >= 0: continue # is tab already in menu?
Id = wx.NewId()
TabSelectionIdDict[Id] = page
menu.Append(Id,page,'')
G2frame.Bind(wx.EVT_MENU, OnSelectPage, id=Id)