Source code for GSASIIphsGUI

# -*- coding: utf-8 -*-
#GSASII - phase data display routines
#========== SVN repository information ###################
# $Date: 2021-07-21 20:04:47 +0000 (Wed, 21 Jul 2021) $
# $Author: toby $
# $Revision: 4998 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/GSASIIphsGUI.py $
# $Id: GSASIIphsGUI.py 4998 2021-07-21 20:04:47Z toby $
#========== SVN repository information ###################
'''
*GSASIIphsGUI: Phase GUI*
-------------------------

Module to create the GUI for display of phase information
in the data display window when a phase is selected.
Phase information is stored in one or more
:ref:`Phase Tree Item <Phase_table>` objects.
Note that there are functions
that respond to some tabs in the phase GUI in other modules
(such as GSASIIddata).

Main routine here is :func:`UpdatePhaseData`, which displays the phase information
(called from :func:`GSASIIdataGUI:SelectDataTreeItem`).

Other top-level routines are: 
:func:`GetSpGrpfromUser` (called locally only);
:func:`FindBondsDraw` and :func:`FindBondsDrawCell` (called locally and in GSASIIplot); 
:func:`SetPhaseWindow` (called locally and in GSASIIddataGUI and GSASIIrestrGUI, multiple locations)
to control scrolling. 
'''
from __future__ import division, print_function
import platform
import os
import wx
import wx.grid as wg
import wx.lib.scrolledpanel as wxscroll
import matplotlib as mpl
import math
import copy
import time
import sys
import random as ran
import subprocess as subp
import distutils.file_util as disfile
import scipy.optimize as so
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 4998 $")
import GSASIIlattice as G2lat
import GSASIIspc as G2spc
import GSASIIElem as G2elem
import GSASIIElemGUI as G2elemGUI
import GSASIIddataGUI as G2ddG
import GSASIIplot as G2plt
# if GSASIIpath.GetConfigValue('debug'):
#     print('Debug reloading',G2plt)
#     import imp
#     imp.reload(G2plt)
import GSASIIdataGUI as G2gd
import GSASIIIO as G2IO
import GSASIIstrMain as G2stMn
import GSASIIstrIO as G2strIO
import GSASIImath as G2mth
import GSASIIpwd as G2pwd
import GSASIIobj as G2obj
import GSASIIctrlGUI as G2G
import GSASIIfiles as G2fl
import GSASIIconstrGUI as G2cnstG
import numpy as np
import numpy.linalg as nl
import atmdata

try:
    wx.NewIdRef
    wx.NewId = wx.NewIdRef
except AttributeError:
    pass

VERY_LIGHT_GREY = wx.Colour(235,235,235)
WHITE = wx.Colour(255,255,255)
BLACK = wx.Colour(0,0,0)
RED = wx.Colour(255,0,0)
WACV = wx.ALIGN_CENTER_VERTICAL
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

# previous rigid body selections
prevResId = None
prevVecId = None

if '2' in platform.python_version_tuple()[0]:
    GkDelta = unichr(0x0394)
    Angstr = unichr(0x00c5)
else:
    GkDelta = chr(0x0394)
    Angstr = chr(0x00c5)   

#### phase class definitions ################################################################################
[docs]class SymOpDialog(wx.Dialog): '''Class to select a symmetry operator ''' def __init__(self,parent,SGData,New=True,ForceUnit=False): wx.Dialog.__init__(self,parent,-1,'Select symmetry operator', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) panel = wx.Panel(self) self.SGData = SGData self.New = New self.Force = ForceUnit self.OpSelected = [0,0,0,[0,0,0],False,False] mainSizer = wx.BoxSizer(wx.VERTICAL) if ForceUnit: choice = ['No','Yes'] self.force = wx.RadioBox(panel,-1,'Force to unit cell?',choices=choice) self.force.Bind(wx.EVT_RADIOBOX, self.OnOpSelect) mainSizer.Add(self.force,0,wx.TOP,5) # if SGData['SGInv']: choice = ['No','Yes'] self.inv = wx.RadioBox(panel,-1,'Choose inversion?',choices=choice) self.inv.Bind(wx.EVT_RADIOBOX, self.OnOpSelect) mainSizer.Add(self.inv,0) if SGData['SGLatt'] != 'P': LattOp = G2spc.Latt2text(SGData['SGCen']).split(';') self.latt = wx.RadioBox(panel,-1,'Choose cell centering?',choices=LattOp) self.latt.Bind(wx.EVT_RADIOBOX, self.OnOpSelect) mainSizer.Add(self.latt,0) if SGData['SGLaue'] in ['-1','2/m','mmm','4/m','4/mmm']: Ncol = 2 else: Ncol = 3 OpList = [] for Opr in SGData['SGOps']: OpList.append(G2spc.MT2text(Opr)) self.oprs = wx.RadioBox(panel,-1,'Choose space group operator?',choices=OpList, majorDimension=Ncol) self.oprs.Bind(wx.EVT_RADIOBOX, self.OnOpSelect) mainSizer.Add(self.oprs,0,wx.BOTTOM,5) mainSizer.Add(wx.StaticText(panel,-1," Choose unit cell?"),0) cellSizer = wx.BoxSizer(wx.HORIZONTAL) cellName = ['X','Y','Z'] self.cell = [] for i in range(3): self.cell.append(wx.SpinCtrl(panel,-1,cellName[i],size=wx.Size(50,20))) self.cell[-1].SetRange(-3,3) self.cell[-1].SetValue(0) self.cell[-1].Bind(wx.EVT_SPINCTRL, self.OnOpSelect) cellSizer.Add(self.cell[-1],0) mainSizer.Add(cellSizer,0,wx.BOTTOM,5) if self.New: choice = ['No','Yes'] self.new = wx.RadioBox(panel,-1,'Generate new positions?',choices=choice) self.new.Bind(wx.EVT_RADIOBOX, self.OnOpSelect) mainSizer.Add(self.new,0) OkBtn = wx.Button(panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) panel.SetSizer(mainSizer) panel.Fit() self.Fit() def OnOpSelect(self,event): self.OpSelected[0] = self.inv.GetSelection() if self.SGData['SGLatt'] != 'P': self.OpSelected[1] = self.latt.GetSelection() self.OpSelected[2] = self.oprs.GetSelection() for i in range(3): self.OpSelected[3][i] = float(self.cell[i].GetValue()) if self.New: self.OpSelected[4] = self.new.GetSelection() if self.Force: self.OpSelected[5] = self.force.GetSelection() def GetSelection(self): return self.OpSelected def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL)
#==============================================================================
[docs]class SphereEnclosure(wx.Dialog): ''' Add atoms within sphere of enclosure to drawing :param wx.Frame parent: reference to parent frame (or None) :param general: general data (includes drawing data) :param atoms: drawing atoms data :param indx: list of selected atoms (may be empty) ''' def __init__(self,parent,general,drawing,indx): wx.Dialog.__init__(self,parent,wx.ID_ANY,'Supply sphere info', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.panel = wx.Panel(self) #just a dummy - gets destroyed in Draw! self.General = general self.Drawing = drawing self.indx = indx self.Sphere = [3.0,] self.centers = [] self.atomTypes = [[item,False] for item in self.General['AtomTypes']] self.CenterOnParent() self.Draw() def Draw(self): def OnAtomType(event): Obj = event.GetEventObject() Id = Ind[Obj.GetId()] self.atomTypes[Id][1] = Obj.GetValue() self.panel.Destroy() self.panel = wx.Panel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(wx.StaticText(self.panel,label=' Sphere of enclosure controls:'),0) topSizer = wx.BoxSizer(wx.HORIZONTAL) atoms = [] if len(self.indx): topSizer.Add(wx.StaticText(self.panel,label=' Sphere centered at atoms: '),0,WACV) cx,ct,cs = self.Drawing['atomPtrs'][:3] for Id in self.indx: if Id < len(self.Drawing['Atoms']): atom = self.Drawing['Atoms'][Id] self.centers.append(atom[cx:cx+3]) atoms.append('%s(%s)'%(atom[ct-1],atom[cs-1])) else: self.centers.append(list(self.Drawing['viewPoint'][0])) atoms.append('View point') topSizer.Add(wx.ComboBox(self.panel,choices=atoms,value=atoms[0], style=wx.CB_READONLY|wx.CB_DROPDOWN),0,WACV) else: topSizer.Add(wx.StaticText(self.panel,label=' Sphere centered at drawing view point'),0,WACV) self.centers.append(self.Drawing['viewPoint'][0]) mainSizer.Add(topSizer,0) sphereSizer = wx.BoxSizer(wx.HORIZONTAL) sphereSizer.Add(wx.StaticText(self.panel,label=' Sphere radius: '),0,WACV) radius = G2G.ValidatedTxtCtrl(self.panel,self.Sphere,0,nDig=(10,3),size=(65,25)) sphereSizer.Add(radius,0,WACV) mainSizer.Add(sphereSizer,0) mainSizer.Add(wx.StaticText(self.panel,label=' Target selected atoms:'),0) atSizer = wx.BoxSizer(wx.HORIZONTAL) Ind = {} for i,item in enumerate(self.atomTypes): atm = wx.CheckBox(self.panel,label=item[0]) atm.SetValue(item[1]) atm.Bind(wx.EVT_CHECKBOX, OnAtomType) Ind[atm.GetId()] = i atSizer.Add(atm,0,WACV) mainSizer.Add(atSizer,0) OkBtn = wx.Button(self.panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(self.panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) self.panel.Fit() self.Fit() def GetSelection(self): used = [] for atm in self.atomTypes: if atm[1]: used.append(str(atm[0])) return self.centers,self.Sphere[0],used def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL)
#==============================================================================
[docs]class TransformDialog(wx.Dialog): ''' Phase transformation X' = M*(X-U)+V :param wx.Frame parent: reference to parent frame (or None) :param phase: parent phase data #NB: commonNames & commonTrans defined in GSASIIdataGUI = G2gd ''' def __init__(self,parent,phase,Trans=np.eye(3),Uvec=np.zeros(3),Vvec=np.zeros(3),ifMag=False,BNSlatt=''): wx.Dialog.__init__(self,parent,wx.ID_ANY,'Setup phase transformation', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.panel = wx.Panel(self) #just a dummy - gets destroyed in Draw! self.Phase = copy.deepcopy(phase) #will be a new phase! # self.Super = phase['General']['Super'] # if self.Super: # self.Trans = np.eye(4) # self.Vec = np.zeros(4) # else: self.Trans = Trans self.Uvec = Uvec self.Vvec = Vvec self.oldSpGrp = phase['General']['SGData']['SpGrp'] self.oldSGdata = phase['General']['SGData'] self.newSpGrp = self.Phase['General']['SGData']['SpGrp'] self.SGData = G2spc.SpcGroup(self.newSpGrp)[1] self.oldCell = phase['General']['Cell'][1:8] self.newCell = self.Phase['General']['Cell'][1:8] self.Common = 'abc' self.ifMag = ifMag if ifMag: self.BNSlatt = BNSlatt self.ifConstr = False self.Mtrans = False self.kvec = [0.,0.,0.] self.Draw() def Draw(self): def OnCommon(event): Obj = event.GetEventObject() self.Common = Obj.GetValue() self.Mtrans = False if '*' in self.Common: A,B = G2lat.cell2AB(self.oldCell[:6]) self.newCell[2:5] = [A[2,2],90.,90.] a,b = G2lat.cell2AB(self.newCell[:6]) self.Trans = np.inner(a,B) #correct! self.ifConstr = False self.newSpGrp = 'P 1' SGErr,SGData = G2spc.SpcGroup(self.newSpGrp) self.Phase['General']['SGData'] = SGData else: if self.Common == G2gd.commonNames[-1]: #change setting self.Vvec = G2spc.spg2origins[self.oldSpGrp] self.newSpGrp = self.oldSpGrp else: self.Trans = G2gd.commonTrans[self.Common] if 'R' == self.Common[-1]: self.newSpGrp += ' r' SGErr,SGData = G2spc.SpcGroup(self.newSpGrp) self.Phase['General']['SGData'] = SGData SGTxt.SetLabel(self.newSpGrp) OnTest(event) def OnSpaceGroup(event): event.Skip() SpcGp = GetSpGrpfromUser(self.panel,self.newSpGrp) if SpcGp == self.newSpGrp or SpcGp is None: #didn't change it! return # try a lookup on the user-supplied name SpGrpNorm = G2spc.StandardizeSpcName(SpcGp) if SpGrpNorm: SGErr,self.SGData = G2spc.SpcGroup(SpGrpNorm) else: SGErr,self.SGData = G2spc.SpcGroup(SpcGp) if SGErr: text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous'] SGTxt.SetLabel(self.newSpGrp) msg = 'Space Group Error' Text = '\n'.join(text) wx.MessageBox(Text,caption=msg,style=wx.ICON_EXCLAMATION) else: text,table = G2spc.SGPrint(self.SGData) self.Phase['General']['SGData'] = self.SGData self.newSpGrp = SpcGp SGTxt.SetLabel(self.Phase['General']['SGData']['SpGrp']) msg = 'Space Group Information' G2G.SGMessageBox(self.panel,msg,text,table).Show() if self.ifMag: self.BNSlatt = self.SGData['SGLatt'] G2spc.SetMagnetic(self.SGData) if self.Phase['General']['Type'] == 'magnetic': Nops = len(self.SGData['SGOps'])*len(self.SGData['SGCen']) if self.SGData['SGInv']: Nops *= 2 self.SGData['SpnFlp'] = Nops*[1,] del self.oldSGdata['MAXMAGN'] wx.CallAfter(self.Draw) def OnShowOps(event): text,table = G2spc.SGPrint(self.SGData,AddInv=True) if self.ifMag: msg = 'Magnetic space group information' OprNames,SpnFlp = G2spc.GenMagOps(self.SGData) text[0] = ' Magnetic Space Group: '+self.SGData['MagSpGrp'] text[3] = ' The magnetic lattice point group is '+self.SGData['MagPtGp'] G2G.SGMagSpinBox(self.panel,msg,text,table,self.SGData['SGCen'],OprNames, self.SGData['SpnFlp'],False).Show() else: msg = 'Space group information' G2G.SGMessageBox(self.panel,msg,text,table).Show() def OnTest(event): if self.Mtrans: self.newCell = G2lat.TransformCell(self.oldCell[:6],self.Trans.T) else: self.newCell = G2lat.TransformCell(self.oldCell[:6],self.Trans) wx.CallAfter(self.Draw) def OnMag(event): self.ifMag = True self.BNSlatt = self.SGData['SGLatt'] G2spc.SetMagnetic(self.SGData) wx.CallAfter(self.Draw) def OnConstr(event): self.ifConstr = constr.GetValue() def OnBNSlatt(event): Obj = event.GetEventObject() self.BNSlatt = Obj.GetValue() if self.BNSlatt == self.SGData['SGLatt']: return GenSym,GenFlg,BNSsym = G2spc.GetGenSym(self.SGData) self.SGData['BNSlattsym'] = [self.BNSlatt,BNSsym[self.BNSlatt]] self.SGData['SGSpin'] = [1,]*len(self.SGData['SGSpin']) wx.CallAfter(self.Draw) def OnMtrans(event): Obj = event.GetEventObject() self.Mtrans = Obj.GetValue() def OnSpinOp(event): Obj = event.GetEventObject() isym = Indx[Obj.GetId()]+1 spCode = {'red':-1,'black':1} self.SGData['SGSpin'][isym] = spCode[Obj.GetValue()] G2spc.CheckSpin(isym,self.SGData) G2spc.SetMagnetic(self.SGData) wx.CallAfter(self.Draw) self.panel.Destroy() self.panel = wx.Panel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) if self.ifMag: if self.BNSlatt != self.SGData['SGLatt']: GenSym,GenFlg,BNSsym = G2spc.GetGenSym(self.SGData) self.SGData['BNSlattsym'] = [self.BNSlatt,BNSsym[self.BNSlatt]] else: mag = wx.Button(self.panel,label='Make new phase magnetic?') mag.Bind(wx.EVT_BUTTON,OnMag) mainSizer.Add(mag,0) MatSizer = wx.BoxSizer(wx.HORIZONTAL) transSizer = wx.BoxSizer(wx.VERTICAL) transSizer.Add((5,5),0) transSizer.Add(wx.StaticText(self.panel,label= " Cell transformation via g'=gM; g=metric tensor \n XYZ transformation via M*(X-U)+V = X'; M* = inv(M)")) # if self.Super: # Trmat = wx.FlexGridSizer(4,4,0,0) # else: commonSizer = wx.BoxSizer(wx.HORIZONTAL) commonSizer.Add(wx.StaticText(self.panel,label=' Common transformations: '),0,WACV) if self.oldSpGrp not in G2spc.spg2origins: common = wx.ComboBox(self.panel,value=self.Common,choices=G2gd.commonNames[:-1], style=wx.CB_READONLY|wx.CB_DROPDOWN) else: common = wx.ComboBox(self.panel,value=self.Common,choices=G2gd.commonNames, style=wx.CB_READONLY|wx.CB_DROPDOWN) common.Bind(wx.EVT_COMBOBOX,OnCommon) commonSizer.Add(common,0,WACV) transSizer.Add(commonSizer) Trmat = wx.FlexGridSizer(4,6,0,0) Trmat.Add((10,0),0) Trmat.Add(wx.StaticText(self.panel,label=' M'),wx.ALIGN_CENTER) Trmat.Add((10,0),0) Trmat.Add((10,0),0) Trmat.Add(wx.StaticText(self.panel,label=' U'),wx.ALIGN_CENTER) Trmat.Add(wx.StaticText(self.panel,label=' V'),wx.ALIGN_CENTER) for iy,line in enumerate(self.Trans): for ix,val in enumerate(line): item = G2G.ValidatedTxtCtrl(self.panel,self.Trans[iy],ix,nDig=(10,3),size=(65,25)) Trmat.Add(item) Trmat.Add((25,0),0) vec = G2G.ValidatedTxtCtrl(self.panel,self.Uvec,iy,nDig=(10,3),size=(65,25)) Trmat.Add(vec) vec = G2G.ValidatedTxtCtrl(self.panel,self.Vvec,iy,nDig=(10,3),size=(65,25)) Trmat.Add(vec) transSizer.Add(Trmat) MatSizer.Add((10,0),0) MatSizer.Add(transSizer) mainSizer.Add(MatSizer) if self.ifMag: MagSizer = wx.BoxSizer(wx.HORIZONTAL) if not self.oldSGdata.get('MAXMAGN',[]): Mtrans = wx.CheckBox(self.panel,label=' Use matrix transform?') Mtrans.SetValue(self.Mtrans) Mtrans.Bind(wx.EVT_CHECKBOX,OnMtrans) MagSizer.Add(Mtrans,0,WACV) mainSizer.Add(MagSizer,0) mainSizer.Add(wx.StaticText(self.panel,label=' Old lattice parameters:'),0) mainSizer.Add(wx.StaticText(self.panel,label= ' a = %.5f b = %.5f c = %.5f'%(self.oldCell[0],self.oldCell[1],self.oldCell[2])),0) mainSizer.Add(wx.StaticText(self.panel,label=' alpha = %.3f beta = %.3f gamma = %.3f'% (self.oldCell[3],self.oldCell[4],self.oldCell[5])),0) mainSizer.Add(wx.StaticText(self.panel,label=' volume = %.3f'%(self.oldCell[6])),0) mainSizer.Add(wx.StaticText(self.panel,label=' New lattice parameters:'),0) mainSizer.Add(wx.StaticText(self.panel,label= ' a = %.5f b = %.5f c = %.5f'%(self.newCell[0],self.newCell[1],self.newCell[2])),0) mainSizer.Add(wx.StaticText(self.panel,label=' alpha = %.3f beta = %.3f gamma = %.3f'% (self.newCell[3],self.newCell[4],self.newCell[5])),0) mainSizer.Add(wx.StaticText(self.panel,label=' volume = %.3f'%(self.newCell[6])),0) sgSizer = wx.BoxSizer(wx.HORIZONTAL) sgSizer.Add(wx.StaticText(self.panel,label=' Target space group: '),0,WACV) SGTxt = wx.Button(self.panel,wx.ID_ANY,self.newSpGrp,size=(100,-1)) SGTxt.Bind(wx.EVT_BUTTON,OnSpaceGroup) sgSizer.Add(SGTxt,0,WACV) showOps = wx.Button(self.panel,label=' Show operators?') showOps.Bind(wx.EVT_BUTTON,OnShowOps) sgSizer.Add(showOps,0,WACV) mainSizer.Add(sgSizer,0) if 'magnetic' not in self.Phase['General']['Type']: if self.ifMag: Indx = {} GenSym,GenFlg,BNSsym = G2spc.GetGenSym(self.SGData) BNSizer = wx.BoxSizer(wx.HORIZONTAL) BNSizer.Add(wx.StaticText(self.panel,label=' Select BNS lattice:'),0,WACV) BNSkeys = [self.SGData['SGLatt'],]+list(BNSsym.keys()) BNSkeys.sort() try: #this is an ugly kluge - bug in wx.ComboBox if self.BNSlatt[2] in ['a','b','c']: BNSkeys.reverse() except: pass BNS = wx.ComboBox(self.panel,choices=BNSkeys,style=wx.CB_READONLY|wx.CB_DROPDOWN) BNS.SetValue(self.BNSlatt) BNS.Bind(wx.EVT_COMBOBOX,OnBNSlatt) BNSizer.Add(BNS,0,WACV) spinColor = ['black','red'] spCode = {-1:'red',1:'black'} for isym,sym in enumerate(GenSym[1:]): BNSizer.Add(wx.StaticText(self.panel,label=' %s: '%(sym.strip())),0,WACV) spinOp = wx.ComboBox(self.panel,value=spCode[self.SGData['SGSpin'][isym+1]],choices=spinColor, style=wx.CB_READONLY|wx.CB_DROPDOWN) Indx[spinOp.GetId()] = isym spinOp.Bind(wx.EVT_COMBOBOX,OnSpinOp) BNSizer.Add(spinOp,0,WACV) OprNames,SpnFlp = G2spc.GenMagOps(self.SGData) self.SGData['SpnFlp'] = SpnFlp mainSizer.Add(BNSizer,0) mainSizer.Add(wx.StaticText(self.panel,label=' Magnetic Space Group: '+self.SGData['MagSpGrp']),0) if self.ifMag: mainSizer.Add(wx.StaticText(self.panel, \ label=' NB: Nonmagnetic atoms will be deleted from new phase'),0) constr = wx.CheckBox(self.panel,label=' Make constraints between phases?') constr.SetValue(self.ifConstr) constr.Bind(wx.EVT_CHECKBOX,OnConstr) mainSizer.Add(constr,0) TestBtn = wx.Button(self.panel,-1,"Test") TestBtn.Bind(wx.EVT_BUTTON, OnTest) OkBtn = wx.Button(self.panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(self.panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(TestBtn) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) self.panel.Fit() self.Fit() def GetSelection(self): self.Phase['General']['SGData'] = self.SGData if self.ifMag: self.Phase['General']['Name'] += ' mag: ' else: self.Phase['General']['Name'] += ' %s'%(self.Common) if self.Mtrans: self.Phase['General']['Cell'][1:] = G2lat.TransformCell(self.oldCell[:6],self.Trans.T) return self.Phase,self.Trans.T,self.Uvec,self.Vvec,self.ifMag,self.ifConstr,self.Common else: self.Phase['General']['Cell'][1:] = G2lat.TransformCell(self.oldCell[:6],self.Trans) return self.Phase,self.Trans,self.Uvec,self.Vvec,self.ifMag,self.ifConstr,self.Common def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL)
#==============================================================================
[docs]class UseMagAtomDialog(wx.Dialog): '''Get user selected magnetic atoms after cell transformation ''' def __init__(self,parent,Name,Atoms,atCodes,atMxyz,ifMag=True,ifOK=False,ifDelete=False): title = 'Subgroup atom list' if ifMag: title = 'Magnetic atom selection' wx.Dialog.__init__(self,parent,wx.ID_ANY,title, pos=wx.DefaultPosition,size=(450,275), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) self.panel = wxscroll.ScrolledPanel(self) #just a dummy - gets destroyed in Draw! # self.panel = wx.Panel(self) #just a dummy - gets destroyed in Draw! self.Name = Name self.Atoms = Atoms self.atCodes = atCodes self.atMxyz = atMxyz self.ifMag = ifMag self.ifOK = ifOK self.ifDelete = ifDelete self.Use = len(self.Atoms)*[True,] self.Draw() def Draw(self): def OnUseChk(event): Obj = event.GetEventObject() iuse = Indx[Obj.GetId()] self.Use[iuse] = not self.Use[iuse] Obj.SetValue(self.Use[iuse]) self.panel.Destroy() self.panel = wxscroll.ScrolledPanel(self,style = wx.DEFAULT_DIALOG_STYLE) Indx = {} Mstr = [' Mx',' My',' Mz'] Xstr = ['X','Y','Z'] mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(wx.StaticText(self.panel,label='For: %s'%self.Name),0) if self.ifMag: mainSizer.Add(wx.StaticText(self.panel,label=' Name, x, y, z, allowed moments, mag. site sym:'),0) else: mainSizer.Add(wx.StaticText(self.panel,label=' Name, x, y, z, allowed xyz, site sym:'),0) atmSizer = wx.FlexGridSizer(0,2,5,5) for iuse,[use,atom,mxyz] in enumerate(zip(self.Use,self.Atoms,self.atMxyz)): mstr = [' ---',' ---',' ---'] for i,mx in enumerate(mxyz[1]): if mx: if self.ifMag: mstr[i] = Mstr[i] else: mstr[i] = Xstr[i] if self.ifMag: useChk = wx.CheckBox(self.panel,label='Use?') Indx[useChk.GetId()] = iuse useChk.SetValue(use) useChk.Bind(wx.EVT_CHECKBOX, OnUseChk) atmSizer.Add(useChk,0,WACV) else: atmSizer.Add((2,2),0) text = ' %5s %10.5f %10.5f %10.5f (%s,%s,%s) %s '%(atom[0],atom[3],atom[4],atom[5],mstr[0],mstr[1],mstr[2],mxyz[0]) atmSizer.Add(wx.StaticText(self.panel,label=text),0,WACV) mainSizer.Add(atmSizer) btnSizer = wx.BoxSizer(wx.HORIZONTAL) if self.ifOK: OKBtn = wx.Button(self.panel,-1,"OK") OKBtn.Bind(wx.EVT_BUTTON, self.OnNo) btnSizer.Add(OKBtn) else: YesBtn = wx.Button(self.panel,-1,"Yes") YesBtn.Bind(wx.EVT_BUTTON, self.OnYes) NoBtn = wx.Button(self.panel,-1,"No") NoBtn.Bind(wx.EVT_BUTTON, self.OnNo) btnSizer.Add((20,20),1) btnSizer.Add(YesBtn) btnSizer.Add((20,20),1) btnSizer.Add(NoBtn) if self.ifDelete: DeleteBtn = wx.Button(self.panel,-1,"Delete") DeleteBtn.Bind(wx.EVT_BUTTON, self.OnDelete) btnSizer.Add((20,20),1) btnSizer.Add(DeleteBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) size = np.array(self.GetSize()) self.panel.SetupScrolling() self.panel.SetAutoLayout(1) size = [size[0]-5,size[1]-20] #this fiddling is needed for older wx! self.panel.SetSize(size) def GetSelection(self): useAtoms = [] useatCodes = [] for use,atom,code in zip(self.Use,self.Atoms,self.atCodes): if use: useAtoms.append(atom) useatCodes.append(code) return useAtoms,useatCodes def OnYes(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_YES) def OnNo(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_NO) def OnDelete(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_DELETE)
#==============================================================================
[docs]class RotationDialog(wx.Dialog): ''' Get Rotate & translate matrix & vector - currently not used needs rethinking - possible use to rotate a group of atoms about some vector/origin + translation ''' def __init__(self,parent): wx.Dialog.__init__(self,parent,wx.ID_ANY,'Atom group rotation/translation', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.panel = wx.Panel(self) #just a dummy - gets destroyed in Draw! self.Trans = np.eye(3) self.Vec = np.zeros(3) self.rotAngle = 0. self.rotVec = np.array([0.,0.,1.]) self.Expand = '' self.Draw() def Draw(self): def OnExpand(event): self.Expand = expand.GetValue() def OnRotAngle(event): event.Skip() self.rotAngle = float(rotangle.GetValue()) rotangle.SetValue('%5.3f'%(self.rotAngle)) Q = G2mth.AVdeg2Q(self.rotAngle,self.rotVec) self.Trans = G2mth.Q2Mat(Q) self.Draw() def OnRotVec(event): event.Skip() vals = rotvec.GetValue() vals = vals.split() self.rotVec = np.array([float(val) for val in vals]) rotvec.SetValue('%5.3f %5.3f %5.3f'%(self.rotVec[0],self.rotVec[1],self.rotVec[2])) Q = G2mth.AVdeg2Q(self.rotAngle,self.rotVec) self.Trans = G2mth.Q2Mat(Q) self.Draw() self.panel.Destroy() self.panel = wx.Panel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) MatSizer = wx.BoxSizer(wx.HORIZONTAL) transSizer = wx.BoxSizer(wx.VERTICAL) transSizer.Add(wx.StaticText(self.panel,label=" XYZ Transformation matrix && vector: "+ \ "\n B*M*A*(X-V)+V = X'\n A,B: Cartesian transformation matrices")) Trmat = wx.FlexGridSizer(3,5,0,0) for iy,line in enumerate(self.Trans): for ix,val in enumerate(line): item = G2G.ValidatedTxtCtrl(self.panel,self.Trans[iy],ix,nDig=(10,3),size=(65,25)) Trmat.Add(item) Trmat.Add((25,0),0) vec = G2G.ValidatedTxtCtrl(self.panel,self.Vec,iy,nDig=(10,3),size=(65,25)) Trmat.Add(vec) transSizer.Add(Trmat) MatSizer.Add((10,0),0) MatSizer.Add(transSizer) mainSizer.Add(MatSizer) rotationBox = wx.BoxSizer(wx.HORIZONTAL) rotationBox.Add(wx.StaticText(self.panel,label=' Rotation angle: '),0,WACV) # Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0) rotangle = wx.TextCtrl(self.panel,value='%5.3f'%(self.rotAngle), size=(50,25),style=wx.TE_PROCESS_ENTER) rotangle.Bind(wx.EVT_TEXT_ENTER,OnRotAngle) rotangle.Bind(wx.EVT_KILL_FOCUS,OnRotAngle) rotationBox.Add(rotangle,0,WACV) rotationBox.Add(wx.StaticText(self.panel,label=' about vector: '),0,WACV) # Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0) rotvec = wx.TextCtrl(self.panel,value='%5.3f %5.3f %5.3f'%(self.rotVec[0],self.rotVec[1],self.rotVec[2]), size=(100,25),style=wx.TE_PROCESS_ENTER) rotvec.Bind(wx.EVT_TEXT_ENTER,OnRotVec) rotvec.Bind(wx.EVT_KILL_FOCUS,OnRotVec) rotationBox.Add(rotvec,0,WACV) mainSizer.Add(rotationBox,0) expandChoice = ['','xy','xz','yz','xyz'] expandBox = wx.BoxSizer(wx.HORIZONTAL) expandBox.Add(wx.StaticText(self.panel,label=' Expand -1 to +1 on: '),0,WACV) expand = wx.ComboBox(self.panel,value=self.Expand,choices=expandChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) expand.Bind(wx.EVT_COMBOBOX,OnExpand) expandBox.Add(expand,0,WACV) expandBox.Add(wx.StaticText(self.panel,label=' and find unique atoms '),0,WACV) mainSizer.Add(expandBox) OkBtn = wx.Button(self.panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(self.panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) self.panel.Fit() self.Fit() def GetSelection(self): return self.Trans,self.Vec,self.Expand def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL)
#==============================================================================
[docs]class DIFFaXcontrols(wx.Dialog): ''' Solicit items needed to prepare DIFFaX control.dif file ''' def __init__(self,parent,ctrls,parms=None): wx.Dialog.__init__(self,parent,wx.ID_ANY,'DIFFaX controls', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.panel = wx.Panel(self) #just a dummy - gets destroyed in Draw! self.ctrls = ctrls self.calcType = 'powder pattern' self.plane = 'h0l' self.planeChoice = ['h0l','0kl','hhl','h-hl',] self.lmax = '2' self.lmaxChoice = [str(i+1) for i in range(6)] self.Parms = parms self.Parm = None if self.Parms != None: self.Parm = self.Parms[0] self.parmRange = [0.,1.] self.parmStep = 2 self.Inst = 'Gaussian' self.Draw() def Draw(self): def OnCalcType(event): self.calcType = calcType.GetValue() wx.CallAfter(self.Draw) def OnPlane(event): self.plane = plane.GetValue() def OnMaxL(event): self.lmax = lmax.GetValue() def OnParmSel(event): self.Parm = parmsel.GetValue() def OnNumStep(event): self.parmStep = int(numStep.GetValue()) def OnParmRange(event): event.Skip() vals = parmrange.GetValue().split() try: vals = [float(vals[0]),float(vals[1])] except ValueError: vals = self.parmRange parmrange.SetValue('%.3f %.3f'%(vals[0],vals[1])) self.parmRange = vals def OnInstSel(event): self.Inst = instsel.GetValue() self.panel.Destroy() self.panel = wx.Panel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(wx.StaticText(self.panel,label=' Controls for DIFFaX'),0) if self.Parms: mainSizer.Add(wx.StaticText(self.panel,label=' Sequential powder pattern simulation'),0) else: calcChoice = ['powder pattern','selected area'] calcSizer = wx.BoxSizer(wx.HORIZONTAL) calcSizer.Add(wx.StaticText(self.panel,label=' Select calculation type: '),0,WACV) calcType = wx.ComboBox(self.panel,value=self.calcType,choices=calcChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) calcType.Bind(wx.EVT_COMBOBOX,OnCalcType) calcSizer.Add(calcType,0,WACV) mainSizer.Add(calcSizer) if self.Parms: parmSel = wx.BoxSizer(wx.HORIZONTAL) parmSel.Add(wx.StaticText(self.panel,label=' Select parameter to vary: '),0,WACV) parmsel = wx.ComboBox(self.panel,value=self.Parm,choices=self.Parms, style=wx.CB_READONLY|wx.CB_DROPDOWN) parmsel.Bind(wx.EVT_COMBOBOX,OnParmSel) parmSel.Add(parmsel,0,WACV) mainSizer.Add(parmSel) mainSizer.Add(wx.StaticText(self.panel,label=' Enter parameter range & no. steps: '),0,WACV) parmRange = wx.BoxSizer(wx.HORIZONTAL) numChoice = [str(i+1) for i in range(10)] # Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0) parmrange = wx.TextCtrl(self.panel,value='%.3f %.3f'%(self.parmRange[0],self.parmRange[1]), style=wx.TE_PROCESS_ENTER) parmrange.Bind(wx.EVT_TEXT_ENTER,OnParmRange) parmrange.Bind(wx.EVT_KILL_FOCUS,OnParmRange) parmRange.Add(parmrange,0,WACV) numStep = wx.ComboBox(self.panel,value=str(self.parmStep),choices=numChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) numStep.Bind(wx.EVT_COMBOBOX,OnNumStep) parmRange.Add(numStep,0,WACV) mainSizer.Add(parmRange) if 'selected' in self.calcType: planeSizer = wx.BoxSizer(wx.HORIZONTAL) planeSizer.Add(wx.StaticText(self.panel,label=' Select plane: '),0,WACV) plane = wx.ComboBox(self.panel,value=self.plane,choices=self.planeChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) plane.Bind(wx.EVT_COMBOBOX,OnPlane) planeSizer.Add(plane,0,WACV) planeSizer.Add(wx.StaticText(self.panel,label=' Max. l index: '),0,WACV) lmax = wx.ComboBox(self.panel,value=self.lmax,choices=self.lmaxChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) lmax.Bind(wx.EVT_COMBOBOX,OnMaxL) planeSizer.Add(lmax,0,WACV) mainSizer.Add(planeSizer) else: instChoice = ['None','Mean Gaussian','Gaussian',] instSizer = wx.BoxSizer(wx.HORIZONTAL) instSizer.Add(wx.StaticText(self.panel,label=' Select instrument broadening: '),0,WACV) instsel = wx.ComboBox(self.panel,value=self.Inst,choices=instChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) instsel.Bind(wx.EVT_COMBOBOX,OnInstSel) instSizer.Add(instsel,0,WACV) mainSizer.Add(instSizer) OkBtn = wx.Button(self.panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(self.panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) self.panel.Fit() self.Fit() def GetSelection(self): if 'powder' in self.calcType: return 'PWDR',self.Inst,self.Parm,self.parmRange,self.parmStep elif 'selected' in self.calcType: return 'SADP',self.plane,self.lmax def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL)
#==============================================================================
[docs]class AddHatomDialog(wx.Dialog): '''H atom addition dialog. After :meth:`ShowModal` returns, the results are found in dict :attr:`self.data`, which is accessed using :meth:`GetData`. :param wx.Frame parent: reference to parent frame (or None) :param dict Neigh: a dict of atom names with list of atom name, dist pairs for neighboring atoms :param dict phase: a dict containing the phase as defined by :ref:`Phase Tree Item <Phase_table>` ''' def __init__(self,parent,Neigh,phase): wx.Dialog.__init__(self,parent,wx.ID_ANY,'H atom add', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.panel = wxscroll.ScrolledPanel(self) #just a dummy - gets destroyed in Draw! self.Neigh = Neigh self.phase = phase self.Hatoms = [] self.Draw(self.Neigh,self.phase)
[docs] def Draw(self,Neigh,phase): '''Creates the contents of the dialog. Normally called by :meth:`__init__`. ''' def OnHSelect(event): Obj = event.GetEventObject() item,i = Indx[Obj.GetId()] for obj in Indx[item]: obj.SetValue(False) Obj.SetValue(True) self.Neigh[item][2] = i def OnBond(event): Obj = event.GetEventObject() inei,ibond = Indx[Obj.GetId()] self.Neigh[inei][1][0][ibond][2] = Obj.GetValue() self.panel.Destroy() self.panel = wxscroll.ScrolledPanel(self,style = wx.DEFAULT_DIALOG_STYLE) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(wx.StaticText(self.panel,-1,'H atom add controls for phase %s:'%(phase['General']['Name'])), 0,wx.LEFT|wx.TOP,10) mainSizer.Add(wx.StaticText(self.panel,-1,'NB: Check selections as they may not be correct'),0|wx.LEFT,10) mainSizer.Add(wx.StaticText(self.panel,-1," Atom: Add # H's Use: Neighbors, dist"),0,wx.TOP|wx.LEFT,5) nHatms = ['0','1','2','3'] dataSizer = wx.FlexGridSizer(0,3,0,0) Indx = {} for inei,neigh in enumerate(Neigh): dataSizer.Add(wx.StaticText(self.panel,-1,' %s: '%(neigh[0])),0,WACV) nH = 1 #for O atom if 'C' in neigh[0] or 'N' in neigh[0]: nH = 4-len(neigh[1][0]) checks = wx.BoxSizer(wx.HORIZONTAL) Ids = [] for i in range(nH+1): nHs = wx.CheckBox(self.panel,-1,label=nHatms[i]) if i == neigh[2]: nHs.SetValue(True) Indx[nHs.GetId()] = [inei,i] Ids.append(nHs) nHs.Bind(wx.EVT_CHECKBOX, OnHSelect) checks.Add(nHs,0,WACV) Indx[inei] = Ids dataSizer.Add(checks,0,WACV) lineSizer = wx.BoxSizer(wx.HORIZONTAL) for ib,bond in enumerate(neigh[1][0]): Bond = wx.CheckBox(self.panel,-1,label=': %s, %.3f'%(bond[0],bond[1])) Bond.SetValue(bond[2]) Indx[Bond.GetId()] = [inei,ib] Bond.Bind(wx.EVT_CHECKBOX,OnBond) lineSizer.Add(Bond,0,WACV) dataSizer.Add(lineSizer,0,WACV|wx.RIGHT,10) mainSizer.Add(dataSizer,0,wx.LEFT,5) CancelBtn = wx.Button(self.panel,-1,'Cancel') CancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) OkBtn = wx.Button(self.panel,-1,'Ok') OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(CancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) size = np.array(self.GetSize()) self.panel.SetupScrolling() self.panel.SetAutoLayout(1) size = [size[0]-5,size[1]-20] #this fiddling is needed for older wx! self.panel.SetSize(size)
[docs] def GetData(self): 'Returns the values from the dialog' for neigh in self.Neigh: for ibond,bond in enumerate(neigh[1][0]): if not bond[2]: neigh[1][1][1][ibond] = 0 #deselected bond neigh[1][1][1] = [a for a in neigh[1][1][1] if a] return self.Neigh #has #Hs to add for each entry
[docs] def OnOk(self,event): 'Called when the OK button is pressed' parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK)
def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL)
#### Phase editing routines ################################################################################ # def DrawAtomsReplaceByID(data,loc,atom,ID): # '''Replace all atoms in drawing array with an ID matching the specified value''' # atomData = data['Drawing']['Atoms'] # indx = G2mth.FindAtomIndexByIDs(atomData,loc,[ID,]) # for ind in indx: # atomData[ind] = MakeDrawAtom(data,atom,atomData[ind]) # def MakeDrawAtom(data,atom,oldatom=None): # 'needs a description' # AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE', # 'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK'] # AA1letter = ['A','R','N','D','C','Q','E','G','H','I', # 'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' '] # generalData = data['General'] # Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7]) # SGData = generalData['SGData'] # deftype = G2obj.validateAtomDrawType(GSASIIpath.GetConfigValue('DrawAtoms_default'),generalData) # if generalData['Type'] in ['nuclear','faulted',]: # if oldatom: # opr = oldatom[5] # if atom[9] == 'A': # X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[11:17]) # atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:11]+list(U)+oldatom[17:]][0] # else: # X = G2spc.ApplyStringOps(opr,SGData,atom[3:6]) # atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:]+oldatom[17:]][0] # else: # atomInfo = [atom[:2]+atom[3:6]+['1',]+[deftype]+ # ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0] # ct,cs = [1,8] #type & color # elif generalData['Type'] == 'magnetic': # if oldatom: # opr = oldatom[8] # mom = np.array(atom[7:10]) # if generalData['Super']: # SSGData = generalData['SSGData'] # Mom = G2spc.ApplyStringOpsMom(opr,SGData,SSGData,mom) # else: # Mom = G2spc.ApplyStringOpsMom(opr,SGData,None,mom) # if atom[12] == 'A': # X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[14:20]) # atomInfo = [atom[:2]+list(X)+list(Mom)+oldatom[8:12]+atom[12:14]+list(U)+oldatom[20:]][0] # else: # X = G2spc.ApplyStringOps(opr,SGData,atom[3:6]) # atomInfo = [atom[:2]+list(X)+list(Mom)+oldatom[8:12]+atom[12:]+oldatom[20:]][0] # else: # atomInfo = [atom[:2]+atom[3:6]+atom[7:10]+['1',]+[deftype]+ # ['',]+[[255,255,255],]+atom[12:]+[[],[]]][0] # ct,cs = [1,11] #type & color # elif generalData['Type'] == 'macromolecular': # try: # oneLetter = AA3letter.index(atom[1]) # except ValueError: # oneLetter = -1 # atomInfo = [[atom[1].strip()+atom[0],]+ # [AA1letter[oneLetter]+atom[0],]+atom[2:5]+ # atom[6:9]+['1',]+[deftype]+['',]+[[255,255,255],]+atom[12:]+[[],[]]][0] # ct,cs = [4,11] #type & color # atNum = generalData['AtomTypes'].index(atom[ct]) # atomInfo[cs] = list(generalData['Color'][atNum]) # return atomInfo
[docs]def getAtomSelections(AtmTbl,cn=0,action='action',includeView=False,ask=True): '''get selected atoms from table or ask user if none are selected :param list AtmTbl: atom or draw atom table :param int cn: atom name position :param str action: description for prompt, when needed :param bool includeView: if True, the viewpoint is included as an option in the selection dialog :returns: indx (list) selected atoms from indices in table. If includeView is True, indx can contain index n (where there are n atoms in table). This is indicates the viewpoint. ''' indx = AtmTbl.GetSelectedRows() indx += [row for row,col in AtmTbl.GetSelectedCells()] for top,bottom in zip([r for r,c in AtmTbl.GetSelectionBlockTopLeft()], [r for r,c in AtmTbl.GetSelectionBlockBottomRight()]): indx += list(range(top,bottom+1)) indx = list(set(indx)) if indx or not ask: return indx choices = [] for i in range(AtmTbl.GetNumberRows()): val = AtmTbl.GetCellValue(i,cn) if val in choices: val += '_' + str(i) choices.append(val) if not choices: return if includeView: choices.append('View point') dlg = G2G.G2MultiChoiceDialog(AtmTbl.GetTopLevelParent(), 'Select atoms','Select atoms for '+action,choices) if dlg.ShowModal() == wx.ID_OK: indx = dlg.GetSelections() dlg.Destroy() return indx
def SetPhaseWindow(phasePage,mainSizer=None,Scroll=0): if mainSizer is not None: phasePage.SetSizer(mainSizer) phasePage.SetAutoLayout(True) phasePage.SetScrollRate(10,10) phasePage.SendSizeEvent() phasePage.Scroll(0,Scroll) def GetSpGrpfromUser(parent,SpGrp): helptext = '''\t\t\tGSAS-II space group information Space groups are entered here as given in Volume I or Volume A of the International Tables using the short Hermann-Mauguin symbol,except that spaces are placed between axial fields (e.g. "P 4/m m m", "F D 3 M" or "p -3 1 m"). NB: the cubic "bar" in "F d -3 m" is unnecessary, and upper/lower case is not required. Where a centrosymmetric tetragonal or cubic space group has alternate origin settings, Origin choice 2 (with the center of symmetry at the origin, which gives an -x,-y,-z symmetry operator) is always used. Refer to the relevant pages in IT I or A to find the offset in atom positions between the two choices. For rhombohedral space groups, (R xxx) the hexagonal setting is assumed. Append a final R to the name (R xxx R) to indicate that a rhombohedral cell should be used (not recommended when alpha >> 120 or << 60, due to correlation.) For standard settings of space groups, space group numbers (1-230) can alternately be entered. GSAS-II will accept non-standard settings of space groups. For example, space group "P -1" can be set to include face centering, using symbol "F -1" and "P 1 1 21/a" as a nonstandard version of "P 21/c". Review the symmetry operators generated by GSAS-II to confirm that you have entered the right symbol for your structure. ''' dlg = G2G.SingleStringDialog(parent,'Get Space Group', ' Input the space group with spaces between axial fields \n (e.g. p 21/c, P 63/m m c, P 4/m m m) or enter a space\n group number between 1 and 230.', value=SpGrp,help=helptext) if not dlg.Show(): dlg.Destroy() return SpGrp else: try: # has a space group number been input? spcnum = int(dlg.GetValue()) if 1 <= spcnum <= 230: SpcGp = G2spc.spgbyNum[spcnum] else: msg = 'Space Group Error' wx.MessageBox('Invalid space group number',caption=msg,style=wx.ICON_EXCLAMATION) return except: #get rid of extra spaces between fields first Flds = dlg.GetValue().split() for fld in Flds: fld = fld.strip() SpcGp = ' '.join(Flds).capitalize() finally: dlg.Destroy() return SpcGp
[docs]def FindBondsDraw(data): '''Generally used routine where cell is from data ''' generalData = data['General'] cell = generalData['Cell'][1:7] FindBondsDrawCell(data,cell)
[docs]def getAtomRadii(data): '''Get radii for atoms, using generalData['DisAglCtls']['BondRadii'] to override generalData['BondRadii'] when present. Fix to make sure that all elements in generalData are present in DisAglCtls. ''' generalData = data['General'] if 'DisAglCtls' not in generalData: return generalData['AtomTypes'],generalData['BondRadii'] if 'BondRadii' not in generalData['DisAglCtls']: return generalData['AtomTypes'],generalData['BondRadii'] DisAglCtls = generalData['DisAglCtls'] if len(generalData['BondRadii']) != len(DisAglCtls['BondRadii']): for typ,dis in zip(generalData['AtomTypes'],generalData['BondRadii']): if typ not in DisAglCtls['AtomTypes']: DisAglCtls['AtomTypes'].append(typ) DisAglCtls['AngleRadii'].append(dis) DisAglCtls['BondRadii'].append(dis) return DisAglCtls['AtomTypes'],DisAglCtls['BondRadii']
[docs]def FindCoordinationByLabel(data): '''Map out molecular connectivity by determining the atoms bonded to each atom, by label. The atoms bonded to each atom in the asymmetric unit is determined and returned in a dict. Works best ''' generalData = data['General'] cx,ct,cs,cia = generalData['AtomPtrs'] atomTypes,radii = getAtomRadii(data) SGData = generalData['SGData'] cellArray = G2lat.CellBlock(1) Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7]) neighborArray = {} error = '' for atomA in data['Atoms']: lblA = atomA[0] if lblA in neighborArray: if error: error += ', ' error += lblA else: neighborArray[lblA] = [] xyzA = np.array(atomA[cx:cx+3]) indA = atomTypes.index(atomA[ct]) for atomB in data['Atoms']: indB = atomTypes.index(atomB[ct]) sumR = data['Drawing']['radiusFactor']*(radii[indA]+radii[indB]) symAtms = [atm[0] for atm in G2spc.GenAtom(np.array(atomB[cx:cx+3]),SGData,False,6*[0],True)] symCellAtms = np.concatenate([cellArray+i for i in symAtms]) dists = np.sqrt(np.sum(np.inner(Amat,symCellAtms-xyzA)**2,axis=0)) if np.any(np.logical_and(dists < sumR, dists != 0)): if atomB[0] not in neighborArray[lblA]: neighborArray[lblA].append(atomB[0]) if error: print('Warning, duplicated atom labels:',error) return neighborArray
[docs]def FindCoordination(ind,data,neighborArray,coordsArray,cmx=0,targets=None): '''Find atoms coordinating atom ind, speed-up version. This only searches to atoms already added to the Draw Array, though we might want to search to all atoms in the asymmetric unity (which would mean searching against atomsAll, but would also require a reformat of atom entry to match difference in format between atoms and drawatoms. ''' generalData = data['General'] Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7]) atomTypes,radii = getAtomRadii(data) atomData = data['Drawing']['Atoms'] cx,ct,cs,ci = data['Drawing']['atomPtrs'] #atomsAll = data['Atoms'] #cxa,cta,csa,cia = generalData['AtomPtrs'] SGData = generalData['SGData'] cellArray = G2lat.CellBlock(1) newAtomList = [] atomA = atomData[ind] xyzA = np.array(atomA[cx:cx+3]) lblA = atomA[0] indA = atomTypes.index(atomA[ct]) for atomB in atomData: if targets and atomB[ct] not in targets: continue if atomB[0] not in neighborArray[lblA]: continue indB = atomTypes.index(atomB[ct]) sumR = data['Drawing']['radiusFactor']*(radii[indA]+radii[indB]) xyzB = np.array(atomB[cx:cx+3]) Uij = atomB[cs+5:cs+5+6] coords = [] symMisc = [] for item in G2spc.GenAtom(xyzB,SGData,False,Uij,True): coords.append(item[0]) symMisc.append(item[1:4]) symCoords = np.array(coords) dists = np.sqrt(np.sum(np.inner(Amat, np.array([symCoords+i-xyzA for i in cellArray]) )**2,axis=0)) for icell,isym in np.argwhere(np.logical_and(dists < sumR, dists != 0.0)): xyz = symCoords[isym] + cellArray[icell] item = [None]+list(symMisc[isym]) atom = copy.deepcopy(atomB) atom[cx:cx+3] = xyz Opr = abs(item[2])%100 M = SGData['SGOps'][Opr-1][0] if cmx: opNum = G2spc.GetOpNum(item[2],SGData) mom = np.array(atom[cmx:cmx+3]) if SGData['SGGray']: atom[cmx:cmx+3] = np.inner(mom,M)*nl.det(M) else: atom[cmx:cmx+3] = np.inner(mom,M)*nl.det(M)*SGData['SpnFlp'][opNum-1] atom[cs-1] = str(item[2])+'+' atom[cs+5:cs+5+6] = item[1] # have we already found an atom at this site? if np.any(np.all(np.isclose(xyz,coordsArray,atol=0.0002),axis=1)): continue # are we going to add it already? if True in [np.allclose(np.array(xyz),np.array(a[cx:cx+3]),atol=0.0002) for a in newAtomList]: continue C = xyz-symCoords[isym]+item[3] atom[cs-1] += str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2]))) newAtomList.append(atom) return newAtomList
[docs]def FindBondsDrawCell(data,cell): '''uses numpy & masks - very fast even for proteins! allows different cell as input from seq. refinements ''' import numpy.ma as ma cx,ct,cs,ci = data['Drawing']['atomPtrs'] hydro = data['Drawing']['showHydrogen'] atomData = data['Drawing']['Atoms'] generalData = data['General'] Amat,Bmat = G2lat.cell2AB(cell) atomTypes,radii = getAtomRadii(data) try: indH = atomTypes.index('H') radii[indH] = 0.5 except: pass for atom in atomData: atom[-2] = [] #clear out old bonds/polyhedra atom[-1] = [] Indx = range(len(atomData)) Atoms = [] Styles = [] Radii = [] Names = [] for atom in atomData: Atoms.append(np.array(atom[cx:cx+3])) Styles.append(atom[cs]) Names.append(ord(atom[ct-1].ljust(4)[3])) try: if not hydro and atom[ct] == 'H': Radii.append(0.0) else: Radii.append(radii[atomTypes.index(atom[ct])]) except ValueError: #changed atom type! Radii.append(0.20) Atoms = np.array(Atoms) Radii = np.array(Radii) Names = np.array(Names) IASRN = zip(Indx,Atoms,Styles,Radii,Names) for atomA in IASRN: if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']: Dx = Atoms-atomA[1] dist = ma.masked_less(np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0)),0.5) #gets rid of G2frame & disorder "bonds" < 0.5A if generalData['Type'] == 'macromolecular': #eliminate cross disorder residue bonds m1 = ma.getmask(dist) if atomA[4] in [ord('A'),]: m2 = ma.getmask(ma.masked_equal(Names,ord('B'))) dist = ma.array(dist,mask=ma.mask_or(m1,m2)) if atomA[4] in [ord('B'),]: m2 = ma.getmask(ma.masked_equal(Names,ord('A'))) dist = ma.array(dist,mask=ma.mask_or(m1,m2)) sumR = atomA[3]+Radii IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.)) #get indices of bonded atoms i = atomA[0] for j in IndB[0]: if Styles[i] == 'polyhedra': atomData[i][-2].append(np.inner(Amat,Dx[j])) elif Styles[j] != 'polyhedra' and j > i: atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j]) atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j]) if Styles[i] == 'polyhedra': Bonds = atomData[i][-2] Faces = [] if len(Bonds) > 2: FaceGen = G2lat.uniqueCombinations(Bonds,3) #N.B. this is a generator for face in FaceGen: vol = nl.det(face) if abs(vol) > 1. or len(Bonds) == 3: if vol < 0.: face = [face[0],face[2],face[1]] face = np.array(face) if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any(): norm = np.cross(face[1]-face[0],face[2]-face[0]) norm /= np.sqrt(np.sum(norm**2)) Faces.append([face,norm]) atomData[i][-1] = Faces
[docs]def VoidMap(data,aMax=1,bMax=1,cMax=1,gridspacing=.25,probeRadius=.5, aMin=0,bMin=0,cMin=0): '''Compute points where there are no atoms within probeRadius A. All atoms in the Atoms list are considered, provided their occupancy is non-zero. :param dict data: Phase data array :param float aMax: Maximum along the *a* direction (fractional units). Defaults to 1. :param float bMax: Maximum along the *b* direction (fractional units). Defaults to 1. :param float cMax: Maximum along the *c* direction (fractional units). Defaults to 1. :param float gridspacing=.25: Approximate spacing of points (fractional units). Defaults to 1. :param float ,probeRadius=.5: :param float aMin: Minimum along the *a* direction (fractional units). Defaults to 0. :param float bMin: Minimum along the *b* direction (fractional units). Defaults to 0. :param float cMin: Minimum along the *c* direction (fractional units). Defaults to 0. ''' VDWdict = dict(zip(data['General']['AtomTypes'],data['General']['vdWRadii'])) cell = data['General']['Cell'][1:7] Amat,Bmat = G2lat.cell2AB(cell) # orthogonalization matrix SGData = data['General']['SGData'] surroundingCells = G2lat.CellBlock(1) xx,yy,zz = np.meshgrid( np.linspace(aMin,aMax,int(0.5+cell[0]*(aMax-aMin)/gridspacing),endpoint=False), np.linspace(bMin,bMax,int(0.5+cell[1]*(bMax-bMin)/gridspacing),endpoint=False), np.linspace(cMin,cMax,int(0.5+cell[2]*(cMax-cMin)/gridspacing),endpoint=False)) coordGrd = np.array([xyz for xyz in zip(xx.ravel(),yy.ravel(),zz.ravel())]) lgclArray = [True for i in xx.ravel()] cx,ct,cs,cia = data['General']['AtomPtrs'] nind = len(data['Atoms']) pgbar = wx.ProgressDialog('Fill unit cell for %d atoms'%nind,'Atoms done=',nind+1, style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT) screenSize = wx.ClientDisplayRect() Size = pgbar.GetSize() if 50 < Size[0] < 500: # sanity check on size, since this fails w/Win & wx3.0 pgbar.SetSize((int(Size[0]*1.2),Size[1])) # increase size a bit along x pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5)) for i,atom in enumerate(data['Atoms']): if atom[cx+3] <= 0: continue radius = VDWdict.get(atom[ct]) cellMin = -radius/np.array(cell[0:3]) cellMax = radius/np.array(cell[0:3]) + (aMax,bMax,cMax) if radius is None: print('Skipping atom {}, no radius'.format(atom[0])) continue radius += probeRadius result = G2spc.GenAtom(atom[cx:cx+3],SGData,Move=True) for item in result: for scell in surroundingCells: XYZ = item[0] + scell if np.any((XYZ < cellMin, XYZ > cellMax)): continue lgclArray = np.logical_and(lgclArray,np.sqrt(np.sum(np.inner(Amat,coordGrd-XYZ)**2,axis=0))>radius) GoOn = pgbar.Update(i,newmsg='Atoms done=%d'%(i)) if not GoOn[0]: break pgbar.Destroy() print('found ',len(coordGrd[lgclArray]),'points gridspacing,probeRadius=',gridspacing,probeRadius) return coordGrd[lgclArray]
[docs]def SetDrawingDefaults(drawingData): """Add required items into data['drawing'] array if not present. This does not add all the items in SetupDrawingData, but it seems that this is not a problem. Perhaps the two routines could be combined? """ defaultDrawing = {'viewPoint':[[0.5,0.5,0.5],[]],'showHydrogen':True, 'backColor':[0,0,0],'depthFog':False,'Zclip':50.0,'cameraPos':50.,'Zstep':0.5, 'radiusFactor':0.85,'contourLevel':1.,'bondRadius':0.1,'ballScale':0.33, 'vdwScale':0.67,'ellipseProb':50,'sizeH':0.50,'unitCellBox':True, 'showABC':True,'selectedAtoms':[],'Atoms':[],'oldxy':[],'magMult':1.0, 'bondList':{},'viewDir':[1,0,0],'Plane':[[0,0,1],False,False,0.0,[255,255,0]], 'peakMoveView':True,'PeakDistRadius':0.0,'showVoids':False,'showMap':False, 'atomsExpandRadius':5.,'atomsDistRadius':2.5,'Voids':[], 'VPPeakDistRad':0.,'VPatomsExpandRad':0.,'VPatomsDistRad':0., } for key in defaultDrawing: if key not in drawingData: drawingData[key] = defaultDrawing[key]
[docs]def updateAddRBorientText(G2frame,testRBObj,Bmat): '''Update all orientation text on the Add RB panel ''' A,V = G2mth.Q2AVdeg(testRBObj['rbObj']['Orient'][0]) testRBObj['rbObj']['OrientVec'][0] = A testRBObj['rbObj']['OrientVec'][1:] = np.inner(Bmat,V) for i,val in enumerate(testRBObj['rbObj']['OrientVec']): G2frame.testRBObjSizers['OrientVecSiz'][i].SetValue(val) G2frame.testRBObjSizers['OrientVecSiz'][4].SetValue( int(10*testRBObj['rbObj']['OrientVec'][0]))
[docs]def UpdatePhaseData(G2frame,Item,data): '''Create the data display window contents when a phase is clicked on in the main (data tree) window. Called only from :meth:`GSASIIdataGUI.SelectDataTreeItem`, which in turn is called from :meth:`GSASIIdataGUI.GSASII.OnDataTreeSelChanged` when a Phase tree item is selected. This creates all tabs on the page and fills their contents. Routine OnPageChanged is called each time a tab is pressed and updates the contents of the tab's page. :param wx.frame G2frame: the main GSAS-II frame object :param wx.TreeItemId Item: the tree item that was selected :param dict data: all the information on the phase in a dictionary ''' def GetReflData(G2frame,phaseName,reflNames): ReflData = {'RefList':[],'Type':''} if '' in reflNames: return None for reflName in reflNames: if 'PWDR' in reflName: PatternId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root, reflName) if not PatternId: #got 0 return None reflSets = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,PatternId,'Reflection Lists')) reflData = reflSets[phaseName] elif 'HKLF' in reflName: PatternId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root, reflName) if not PatternId: #got 0 return None reflData = G2frame.GPXtree.GetItemPyData(PatternId)[1] if 'Type' not in reflData: reflData['Type'] = 'SXC' if ReflData['Type'] and reflData['Type'] != ReflData['Type']: G2frame.ErrorDialog('Data type conflict', reflName+' conflicts with previous '+ReflData['Type']) return None ReflData['RefList'] += list(reflData['RefList']) ReflData['Type'] = reflData['Type'] return ReflData def SetupGeneral(): try: G2elem.SetupGeneral(data,G2frame.dirname) except ValueError as msg: wx.MessageBox(msg,caption='Element symbol error') ##### General phase routines ################################################################################ def UpdateGeneral(Scroll=0,SkipDraw=False): '''Draw the controls for the General phase data subpage ''' """ This is the default dictionary structure for phase data (taken from GSASII.py) 'General':{ 'Name':PhaseName 'Type':'nuclear' 'SGData':SGData 'Cell':[False,10.,10.,10.,90.,90.,90,1000.] 'AtomPtrs':[] 'Pawley dmin':1.0, 'Pawley neg wt':0.0} 'Atoms':[] 'Drawing':{} """ def NameSizer(): def SetDefaultSSsymbol(): if generalData['SGData']['SGLaue'] in '-1': return '(abg)' elif generalData['SGData']['SGLaue'] in ['2/m']: if generalData['SGData']['SGUniq'] == 'a': return '(a00)' elif generalData['SGData']['SGUniq'] == 'b': return '(0b0)' elif generalData['SGData']['SGUniq'] == 'c': return '(00g)' else: return '(00g)' def OnPhaseName(event): event.Skip() oldName = generalData['Name'] phaseRIdList,usedHistograms = G2frame.GetPhaseInfofromTree() phaseNameList = usedHistograms.keys() # phase names in use newName = NameTxt.GetValue().strip() if newName and newName != oldName: newName = G2obj.MakeUniqueLabel(newName,list(phaseNameList)) generalData['Name'] = newName G2frame.G2plotNB.Rename(oldName,generalData['Name']) G2frame.GPXtree.SetItemText(Item,generalData['Name']) # change phase name key in Reflection Lists for each histogram for hist in data['Histograms']: ht = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,hist) rt = G2gd.GetGPXtreeItemId(G2frame,ht,'Reflection Lists') if not rt: continue RfList = G2frame.GPXtree.GetItemPyData(rt) if oldName not in RfList: print('Warning: '+oldName+' not in Reflection List for '+ hist) continue RfList[newName] = RfList[oldName] del RfList[oldName] NameTxt.SetValue(generalData['Name']) def OnPhaseType(event): if not len(generalData['AtomTypes']): #can change only if no atoms! generalData['Type'] = TypeTxt.GetValue() pages = [G2frame.phaseDisplay.GetPageText(PageNum) for PageNum in range(G2frame.phaseDisplay.GetPageCount())] if generalData['Type'] == 'faulted': G2frame.Bind(wx.EVT_MENU, OnLoadDIFFaX, id=G2G.wxID_LOADDIFFAX) G2frame.Bind(wx.EVT_MENU, OnSimulate, id=G2G.wxID_LAYERSIMULATE) G2frame.Bind(wx.EVT_MENU, OnSeqSimulate, id=G2G.wxID_SEQUENCESIMULATE) G2frame.Bind(wx.EVT_MENU, OnFitLayers, id=G2G.wxID_LAYERSFIT) if 'Wave Data' in pages: pass # G2frame.phaseDisplay.DeletePage(pages.index('Wave Data')) if 'MC/SA' in pages: pass # G2frame.phaseDisplay.DeletePage(pages.index('MC/SA')) if 'RB Models' in pages: pass # G2frame.phaseDisplay.DeletePage(pages.index('RB Models')) if 'Layers' not in pages: if 'Layers' not in data: data['Layers'] = {'Laue':'-1','Cell':[False,1.,1.,1.,90.,90.,90,1.], 'Width':[[1.,1.],[False,False]],'Toler':0.01,'AtInfo':{}, 'Layers':[],'Stacking':[],'Transitions':[]} G2frame.layerData = wx.ScrolledWindow(G2frame.phaseDisplay) G2frame.phaseDisplay.InsertPage(3,G2frame.layerData,'Layers') Id = wx.NewId() TabSelectionIdDict[Id] = 'Layers' wx.CallAfter(UpdateGeneral) elif generalData['Type'] == 'magnetic': generalData['AtomPtrs'] = [3,1,10,12] SGData = generalData['SGData'] Nops = len(SGData['SGOps'])*len(SGData['SGCen']) if SGData['SGInv']: Nops *= 2 SGData['SpnFlp'] = Nops*[1,] else: if 'Wave Data' in pages: G2frame.phaseDisplay.DeletePage(pages.index('Wave Data')) if 'MC/SA' not in pages: G2frame.MCSA = wx.ScrolledWindow(G2frame.phaseDisplay) G2frame.phaseDisplay.InsertPage(7,G2frame.MCSA,'MC/SA') Id = wx.NewId() TabSelectionIdDict[Id] = 'MC/SA' wx.CallAfter(UpdateGeneral) else: G2frame.ErrorDialog('Phase type change error','Can change phase type only if there are no atoms') TypeTxt.SetValue(generalData['Type']) def OnSpaceGroup(event): if generalData['SGData']['SGFixed']: msg = 'Fixed cif generated magnetic space group' text = 'space group can not be changed' wx.MessageBox(text,caption=msg,style=wx.ICON_EXCLAMATION) text,table = G2spc.SGPrint(generalData['SGData']) SGTxt.SetLabel(generalData['SGData']['SpGrp']) msg = 'cif based Space Group Information' G2G.SGMessageBox(General,msg,text,table).Show() return # try a lookup on the user-supplied name SpcGp = GetSpGrpfromUser(General,SpGrp) if SpcGp == SpGrp: text,table = G2spc.SGPrint(generalData['SGData']) SGTxt.SetLabel(generalData['SGData']['SpGrp']) msg = 'Space Group Information' G2G.SGMessageBox(General,msg,text,table).Show() return #unchanged - do nothing but show info SpGrpNorm = G2spc.StandardizeSpcName(SpcGp) if SpGrpNorm: SGErr,SGData = G2spc.SpcGroup(SpGrpNorm) else: SGErr,SGData = G2spc.SpcGroup(SpcGp) if SGErr: text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous'] SGTxt.SetLabel(generalData['SGData']['SpGrp']) msg = 'Space Group Error' Text = '\n'.join(text) wx.MessageBox(Text,caption=msg,style=wx.ICON_EXCLAMATION) else: if "1'" in SpcGp: generalData['Type'] = 'magnetic' generalData['Modulated'] = True if generalData['Type'] == 'magnetic': Nops = len(SGData['SGOps'])*len(SGData['SGCen']) if SGData['SGInv']: Nops *= 2 GenSym,GenFlg = G2spc.GetGenSym(SGData)[:2] SGData['GenSym'] = GenSym SGData['GenFlg'] = GenFlg SGData['MagSpGrp'] = G2spc.MagSGSym(SGData) G2spc.ApplyBNSlatt(SGData,SGData['BNSlattsym']) SGData['SpnFlp'] = Nops*[1,] if generalData['Modulated']: generalData['SuperSg'] = SetDefaultSSsymbol() generalData['SSGData'] = G2spc.SSpcGroup(generalData['SGData'],generalData['SuperSg'])[1] if SGData['SGGray']: SGData['SpnFlp'] += Nops*[-1,] text,table = G2spc.SGPrint(SGData) generalData['SGData'] = SGData SGTxt.SetLabel(generalData['SGData']['SpGrp']) msg = 'Space Group Information' G2G.SGMessageBox(General,msg,text,table).Show() G2spc.UpdateSytSym(data) NShkl = len(G2spc.MustrainNames(SGData)) NDij = len(G2spc.HStrainNames(SGData)) for hist in data['Histograms']: if 'HStrain' in data['Histograms'][hist]: #PWDR only data['Histograms'][hist]['Mustrain'][4:6] = [NShkl*[0.01,],NShkl*[False,]] data['Histograms'][hist]['HStrain'] = [NDij*[0.0,],NDij*[False,]] if data['Drawing']: data['Drawing']['Atoms'] = [] wx.CallAfter(UpdateGeneral) def OnModulated(event): if not len(generalData['AtomTypes']): #can change only if no atoms! pages = [G2frame.phaseDisplay.GetPageText(PageNum) for PageNum in range(G2frame.phaseDisplay.GetPageCount())] if generalData['Type'] in ['nuclear','magnetic']: generalData['Modulated'] = modulated.GetValue() if generalData['Modulated']: if 'SuperSg' not in generalData: generalData['SuperSg'] = SetDefaultSSsymbol() generalData['SSGData'] = G2spc.SSpcGroup(generalData['SGData'],generalData['SuperSg'])[1] if 'SuperVec' not in generalData: generalData['Super'] = True generalData['SuperVec'] = [[0.,0.,0.],False,4] generalData['SSGData'] = {} if '4DmapData' not in generalData: generalData['4DmapData'] = mapDefault.copy() generalData['4DmapData'].update({'MapType':'Fobs'}) if 'MC/SA' in pages: pass # G2frame.phaseDisplay.DeletePage(pages.index('MC/SA')) #this crashes!! if 'Layers' in pages: pass # G2frame.phaseDisplay.DeletePage(pages.index('Layers')) if 'Wave Data' not in pages: G2frame.waveData = wx.ScrolledWindow(G2frame.phaseDisplay) G2frame.phaseDisplay.InsertPage(3,G2frame.waveData,'Wave Data') Id = wx.NewId() TabSelectionIdDict[Id] = 'Wave Data' # deleting page now causes Mac crash, postpone until page is redrawn # else: # if 'Wave Data' in pages: # G2frame.phaseDisplay.DeletePage(pages.index('Wave Data')) wx.CallAfter(UpdateGeneral) else: if generalData['Type'] == 'magnetic': pages = [G2frame.phaseDisplay.GetPageText(PageNum) for PageNum in range(G2frame.phaseDisplay.GetPageCount())] generalData['Modulated'] = modulated.GetValue() if generalData['Modulated']: if 'SuperSg' not in generalData: generalData['SuperSg'] = SetDefaultSSsymbol() generalData['SSGData'] = G2spc.SSpcGroup(generalData['SGData'],generalData['SuperSg'])[1] if 'SuperVec' not in generalData: generalData['Super'] = 1 generalData['SuperVec'] = [[0.,0.,0.],False,4] generalData['SSGData'] = {} if '4DmapData' not in generalData: generalData['4DmapData'] = mapDefault.copy() generalData['4DmapData'].update({'MapType':'Fobs'}) if 'Wave Data' not in pages: G2frame.waveData = wx.ScrolledWindow(G2frame.phaseDisplay) G2frame.phaseDisplay.InsertPage(3,G2frame.waveData,'Wave Data') Id = wx.NewId() TabSelectionIdDict[Id] = 'Wave Data' Atoms = data['Atoms'] for atom in Atoms: atom += [{'SS1':{'waveType':'Fourier','Sfrac':[],'Spos':[],'Sadp':[],'Smag':[]}}] wx.CallAfter(UpdateGeneral) else: G2frame.ErrorDialog('Modulation type change error','Can change modulation only if there are no atoms') modulated.SetValue(generalData['Modulated']) nameSizer = wx.BoxSizer(wx.HORIZONTAL) nameSizer.Add(wx.StaticText(General,-1,' Phase name: '),0,WACV) # Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0) NameTxt = wx.TextCtrl(General,-1,value=generalData['Name'],style=wx.TE_PROCESS_ENTER) NameTxt.Bind(wx.EVT_TEXT_ENTER,OnPhaseName) NameTxt.Bind(wx.EVT_KILL_FOCUS,OnPhaseName) nameSizer.Add(NameTxt,0,WACV) nameSizer.Add(wx.StaticText(General,-1,' Phase type: '),0,WACV) TypeTxt = wx.ComboBox(General,-1,value=generalData['Type'],choices=phaseTypes, style=wx.CB_READONLY|wx.CB_DROPDOWN) TypeTxt.Bind(wx.EVT_COMBOBOX, OnPhaseType) nameSizer.Add(TypeTxt,0,WACV) nameSizer.Add(wx.StaticText(General,-1,' Space group: '),0,WACV) SpGrp = generalData['SGData']['SpGrp'] if generalData['SGData']['SGGray']: SpGrp += " 1'" SGTxt = wx.Button(General,wx.ID_ANY,SpGrp,size=(100,-1)) SGTxt.Bind(wx.EVT_BUTTON,OnSpaceGroup) nameSizer.Add(SGTxt,0,WACV) if generalData['Type'] in ['nuclear','magnetic']: modulated = wx.CheckBox(General,label='Modulated? ') modulated.SetValue(generalData['Modulated']) modulated.Bind(wx.EVT_CHECKBOX,OnModulated) nameSizer.Add(modulated,0,WACV) # add help button to bring up help web page - at right sede of window nameSizer.Add((-1,-1),1,WACV) nameSizer.Add(G2G.HelpButton(General,helpIndex=G2frame.dataWindow.helpKey),0,WACV) return nameSizer def CellSizer(): cellGUIlist = [[['m3','m3m'],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])], [['3R','3mR'],6,zip([" a = "," alpha = "," Vol = "],["%.5f","%.3f","%.3f"],[True,True,False],[0,3,0])], [['3','3m1','31m','6/m','6/mmm','4/m','4/mmm'],6,zip([" a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])], [['mmm'],8,zip([" a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"], [True,True,True,False],[0,1,2,0])], [['2/m'+'a'],10,zip([" a = "," b = "," c = "," alpha = "," Vol = "], ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,3,0])], [['2/m'+'b'],10,zip([" a = "," b = "," c = "," beta = "," Vol = "], ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])], [['2/m'+'c'],10,zip([" a = "," b = "," c = "," gamma = "," Vol = "], ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,5,0])], [['-1'],7,zip([" a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "], ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"], [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]] def OnCellRef(event): generalData['Cell'][0] = cellRef.GetValue() def OnCellChange(invalid,value,tc): SGData = generalData['SGData'] laue = SGData['SGLaue'] if laue == '2/m': laue += SGData['SGUniq'] cell = generalData['Cell'] Obj = tc ObjId = cellList.index(Obj.GetId()) try: value = max(1.0,float(tc.GetValue())) except ValueError: if ObjId < 3: #bad cell edge - reset value = cell[ObjId+1] else: #bad angle value = 90. if laue in ['m3','m3m']: cell[1] = cell[2] = cell[3] = value cell[4] = cell[5] = cell[6] = 90.0 Obj.SetValue(cell[1]) elif laue in ['3R','3mR']: if ObjId == 0: cell[1] = cell[2] = cell[3] = value Obj.SetValue(cell[1]) else: cell[4] = cell[5] = cell[6] = value Obj.SetValue(cell[4]) elif laue in ['3','3m1','31m','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(cell[1]) else: cell[3] = value Obj.SetValue(cell[3]) elif laue in ['mmm']: cell[ObjId+1] = value cell[4] = cell[5] = cell[6] = 90. Obj.SetValue(cell[ObjId+1]) elif laue in ['2/m'+'a']: cell[5] = cell[6] = 90. if ObjId != 3: cell[ObjId+1] = value Obj.SetValue(cell[ObjId+1]) else: cell[4] = value Obj.SetValue(cell[4]) elif laue in ['2/m'+'b']: cell[4] = cell[6] = 90. if ObjId != 3: cell[ObjId+1] = value Obj.SetValue(cell[ObjId+1]) else: cell[5] = value Obj.SetValue(cell[5]) elif laue in ['2/m'+'c']: cell[4] = cell[5] = 90. if ObjId != 3: cell[ObjId+1] = value Obj.SetValue(cell[ObjId+1]) else: cell[6] = value Obj.SetValue(cell[6]) else: cell[ObjId+1] = value Obj.SetValue(cell[1+ObjId]) cell[7] = G2lat.calc_V(G2lat.cell2A(cell[1:7])) volVal.SetValue("%.3f"%(cell[7])) density,mattCoeff = G2mth.getDensity(generalData) if denSizer: denSizer[1].SetValue('%.3f'%(density)) if denSizer[2]: denSizer[2].SetValue('%.3f'%(mattCoeff)) cell = generalData['Cell'] laue = generalData['SGData']['SGLaue'] if laue == '2/m': laue += generalData['SGData']['SGUniq'] for cellGUI in cellGUIlist: if laue in cellGUI[0]: useGUI = cellGUI cellSizer = wx.FlexGridSizer(0,useGUI[1]+1,5,5) if PWDR: cellRef = wx.CheckBox(General,-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(General,label=txt),0,WACV) Fmt = (10,5) if '.3' in fmt: Fmt = (10,3) if ifEdit: #a,b,c,etc. cellVal = G2G.ValidatedTxtCtrl(General,generalData['Cell'],Id+1, xmin=0.1,xmax=500.,nDig=Fmt,OnLeave=OnCellChange) cellSizer.Add(cellVal,0,WACV) cellList.append(cellVal.GetId()) else: #volume volVal = wx.TextCtrl(General,value=(fmt%(cell[7])),style=wx.TE_READONLY) volVal.SetBackgroundColour(VERY_LIGHT_GREY) cellSizer.Add(volVal,0,WACV) return cellSizer def ElemSizer(): def OnIsotope(event): Obj = event.GetEventObject() item = Indx[Obj.GetId()] isotope = Obj.GetValue() nCols = len(generalData['AtomTypes'])+1 data['General']['Isotope'][item] = isotope indx = generalData['AtomTypes'].index(item) wt = generalData['Isotopes'][item][isotope]['Mass'] elemSizer.GetChildren()[indx+3*nCols+1].Window.SetValue('%.3f'%(wt)) #tricky data['General']['AtomMass'][indx] = wt density,mattCoeff = G2mth.getDensity(generalData) denSizer[1].SetValue('%.3f'%(density)) if denSizer[2]: denSizer[2].SetValue('%.3f'%(mattCoeff)) elemSizer = wx.FlexGridSizer(0,len(generalData['AtomTypes'])+1,1,1) elemSizer.Add(wx.StaticText(General,label=' Elements'),0,WACV) for elem in generalData['AtomTypes']: typTxt = wx.TextCtrl(General,value=elem,style=wx.TE_READONLY) typTxt.SetBackgroundColour(VERY_LIGHT_GREY) elemSizer.Add(typTxt,0,WACV) elemSizer.Add(wx.StaticText(General,label=' Isotope'),0,WACV) for elem in generalData['AtomTypes']: choices = list(generalData['Isotopes'][elem].keys()) isoSel = wx.ComboBox(General,-1,value=generalData['Isotope'][elem],choices=choices, style=wx.CB_READONLY) isoSel.Bind(wx.EVT_COMBOBOX,OnIsotope) Indx[isoSel.GetId()] = elem elemSizer.Add(isoSel,1,wx.EXPAND) elemSizer.Add(wx.StaticText(General,label=' No. per cell'),0,WACV) for elem in generalData['AtomTypes']: numbTxt = wx.TextCtrl(General,value='%.1f'%(generalData['NoAtoms'][elem]), style=wx.TE_READONLY) numbTxt.SetBackgroundColour(VERY_LIGHT_GREY) elemSizer.Add(numbTxt,0,WACV) elemSizer.Add(wx.StaticText(General,label=' Atom weight'),0,WACV) for wt in generalData['AtomMass']: wtTxt = wx.TextCtrl(General,value='%.3f'%(wt),style=wx.TE_READONLY) wtTxt.SetBackgroundColour(VERY_LIGHT_GREY) elemSizer.Add(wtTxt,0,WACV) elemSizer.Add(wx.StaticText(General,label=' Bond radii'),0,WACV) for rad in generalData['BondRadii']: bondRadii = wx.TextCtrl(General,value='%.2f'%(rad),style=wx.TE_READONLY) bondRadii.SetBackgroundColour(VERY_LIGHT_GREY) elemSizer.Add(bondRadii,0,WACV) elemSizer.Add(wx.StaticText(General,label=' Angle radii'),0,WACV) for rad in generalData['AngleRadii']: elemTxt = wx.TextCtrl(General,value='%.2f'%(rad),style=wx.TE_READONLY) elemTxt.SetBackgroundColour(VERY_LIGHT_GREY) elemSizer.Add(elemTxt,0,WACV) elemSizer.Add(wx.StaticText(General,label=' van der Waals radii'),0,WACV) for rad in generalData['vdWRadii']: elemTxt = wx.TextCtrl(General,value='%.2f'%(rad),style=wx.TE_READONLY) elemTxt.SetBackgroundColour(VERY_LIGHT_GREY) elemSizer.Add(elemTxt,0,WACV) elemSizer.Add(wx.StaticText(General,label=' Default color'),0,WACV) for R,G,B in generalData['Color']: colorTxt = wx.TextCtrl(General,value='',style=wx.TE_READONLY) colorTxt.SetBackgroundColour(wx.Colour(R,G,B)) elemSizer.Add(colorTxt,0,WACV) if generalData['Type'] == 'magnetic': elemSizer.Add(wx.StaticText(General,label=' Lande g factor: '),0,WACV) for ig,elem in enumerate(generalData['AtomTypes']): gfac = generalData['Lande g'][ig] if gfac == None: elemSizer.Add((5,0),) else: gfacTxt = G2G.ValidatedTxtCtrl(General,generalData['Lande g'],ig, xmin=0.5,xmax=3.0,nDig=(10,2)) elemSizer.Add(gfacTxt,0,WACV) return elemSizer def DenSizer(): generalData['Mass'] = G2mth.getMass(generalData) density,mattCoeff = G2mth.getDensity(generalData) denSizer = wx.BoxSizer(wx.HORIZONTAL) denSizer.Add(wx.StaticText(General,-1,' Density: '),0,WACV) denTxt = wx.TextCtrl(General,-1,'%.3f'%(density),style=wx.TE_READONLY) denTxt.SetBackgroundColour(VERY_LIGHT_GREY) denSizer.Add(denTxt,0,WACV) mattTxt = None if generalData['Type'] == 'macromolecular' and generalData['Mass'] > 0.0: denSizer.Add(wx.StaticText(General,-1,' Matthews coeff.: '), 0,WACV) mattTxt = wx.TextCtrl(General,-1,'%.3f'%(mattCoeff),style=wx.TE_READONLY) mattTxt.SetBackgroundColour(VERY_LIGHT_GREY) denSizer.Add(mattTxt,0,WACV) return denSizer,denTxt,mattTxt def MagSizer(): def OnSpinOp(event): if SGData['SGFixed']: msg = 'Fixed cif generated spins' text = 'Spin configuration can not be changed; it will be reset' wx.MessageBox(text,caption=msg,style=wx.ICON_EXCLAMATION) wx.CallAfter(UpdateGeneral) return Obj = event.GetEventObject() isym = Indx[Obj.GetId()]+1 spCode = {'red':-1,'black':1} SGData['SGSpin'][isym] = spCode[Obj.GetValue()] G2spc.CheckSpin(isym,SGData) wx.CallAfter(UpdateGeneral) def OnBNSlatt(event): Obj = event.GetEventObject() BNSlatt = Obj.GetValue() SGData = generalData['SGData'] SpcGrp = SGData['SpGrp'] if SGData['SGGray']: SpcGrp += " 1'" SGErr,SGData = G2spc.SpcGroup(SpcGrp) if '_' in BNSlatt: SGData['BNSlattsym'] = [BNSlatt,BNSsym[BNSlatt]] else: SGData['BNSlattsym'] = [SGData['SGLatt'],[0.,0.,0.]] SGData['SGSpin'] = [1,]*len(SGData['SGSpin']) #set to all black GenSym,GenFlg = G2spc.GetGenSym(SGData)[:2] SGData['GenSym'] = GenSym SGData['GenFlg'] = GenFlg SGData['MagSpGrp'] = G2spc.MagSGSym(SGData) G2spc.ApplyBNSlatt(SGData,SGData['BNSlattsym']) generalData['SGData'] = SGData G2spc.UpdateSytSym(data) wx.CallAfter(UpdateGeneral) def OnShowSpins(event): msg = 'Magnetic space group information' text,table = G2spc.SGPrint(SGData,AddInv=not SGData['SGFixed']) text[0] = ' Magnetic Space Group: '+SGData['MagSpGrp'] text[3] = ' The magnetic lattice point group is '+SGData['MagPtGp'] if SGData['SGGray'] and "1'" not in text[0]: text[0] += " 1'" text[3] += "1'" G2G.SGMagSpinBox(General,msg,text,table,SGData['SGCen'],OprNames, SGData['SpnFlp'],SGData['SGGray']& (not SGData['SGFixed'])).Show() SGData = generalData['SGData'] GenSym,GenFlg,BNSsym = G2spc.GetGenSym(SGData) if 'BNSlattsym' not in SGData: SGData['BNSlattsym'] = [SGData['SGLatt'],[0,0,0]] Indx = {} MagSym = SGData['MagSpGrp'] if SGData['SGGray'] and "1'" not in MagSym: MagSym += " 1'" magSizer = wx.BoxSizer(wx.VERTICAL) magSizer.Add(wx.StaticText(General,label=' Magnetic spin operator selection:'),0) spinSizer = wx.BoxSizer(wx.HORIZONTAL) if SGData['SGFixed']: SpnFlp = SGData['SpnFlp'] spinSizer.Add(wx.StaticText(General,label=' Magnetic phase from mcif file; no change in spin inversion allowed'),0,WACV) OprNames = G2spc.GenMagOps(SGData)[0] else: if not len(GenSym): # or SGData['SGGray']: spinSizer.Add(wx.StaticText(General,label=' No spin inversion allowed'),0,WACV) OprNames,SpnFlp = G2spc.GenMagOps(SGData) else: spinSizer.Add(wx.StaticText(General,label=' BNS lattice: '),0,WACV) BNSkeys = [SGData['SGLatt'],]+list(BNSsym.keys()) BNSkeys.sort() try: #this is an ugly kluge - bug in wx.ComboBox if SGData['BNSlattsym'][0][2] in ['a','b','c']: BNSkeys.reverse() except: pass BNS = wx.ComboBox(General, choices=BNSkeys,style=wx.CB_READONLY|wx.CB_DROPDOWN) BNS.SetValue(SGData['BNSlattsym'][0]) BNS.Bind(wx.EVT_COMBOBOX,OnBNSlatt) spinSizer.Add(BNS,0,WACV) spinColor = ['black','red'] spCode = {-1:'red',1:'black'} for isym,sym in enumerate(GenSym[1:]): spinSizer.Add(wx.StaticText(General,label=' %s: '%(sym.strip())),0,WACV) spinOp = wx.ComboBox(General,value=spCode[SGData['SGSpin'][isym+1]],choices=spinColor, style=wx.CB_READONLY|wx.CB_DROPDOWN) Indx[spinOp.GetId()] = isym spinOp.Bind(wx.EVT_COMBOBOX,OnSpinOp) spinSizer.Add(spinOp,0,WACV) OprNames,SpnFlp = G2spc.GenMagOps(SGData) SGData['SpnFlp'] = SpnFlp SGData['OprNames'] = OprNames magSizer.Add(spinSizer) msgSizer = wx.BoxSizer(wx.HORIZONTAL) msgSizer.Add(wx.StaticText(General,label=' Magnetic space group: %s '%(MagSym)),0,WACV) showSpins = wx.Button(General,label=' Show spins?') showSpins.Bind(wx.EVT_BUTTON,OnShowSpins) msgSizer.Add(showSpins,0,WACV) magSizer.Add(msgSizer) dminSizer = wx.BoxSizer(wx.HORIZONTAL) dminSizer.Add(wx.StaticText(General,label=' Magnetic reflection d-min: '),0,WACV) dminVal = G2G.ValidatedTxtCtrl(General,generalData,'MagDmin',nDig=(10,4),xmin=0.7) dminSizer.Add(dminVal,0,WACV) magSizer.Add(dminSizer,0) return magSizer def ModulatedSizer(name): def OnShowSOps(event): SSGData = generalData['SSGData'] text,table = G2spc.SSGPrint(generalData['SGData'],SSGData,not SGData['SGFixed']) msg = 'Superspace Group Information' G2G.SGMessageBox(General,msg,text,table,SGData.get('SpnFlp',[])).ShowModal() def OnSuperGp(event): #for HKLF needs to reject SSgps not agreeing with modVec! 'Respond to selection of a modulation group' wx.BeginBusyCursor() Choice = G2spc.SSChoice(SGData) wx.EndBusyCursor() dlg = wx.Dialog(General,style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(wx.StaticText(dlg,wx.ID_OK,'Select or enter a modulation group'),0,wx.ALIGN_CENTER) sizer.Add((10,10)) superGp = wx.ComboBox(dlg,value=generalData['SuperSg'],choices=Choice,style=wx.CB_DROPDOWN|wx.TE_READONLY) sizer.Add(superGp) sizer.Add((10,10)) btnsizer = wx.StdDialogButtonSizer() btn = wx.Button(dlg, wx.ID_OK) btn.SetDefault() btnsizer.AddButton(btn) btn = wx.Button(dlg, wx.ID_CANCEL) btnsizer.AddButton(btn) btnsizer.Realize() sizer.Add(btnsizer, 0, wx.EXPAND|wx.ALL, 5) dlg.SetSizer(sizer) sizer.Fit(dlg) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: try: SSymbol = superGp.GetValue().strip() except AttributeError: # not sure why needed SSymbol = superGp.GetLabel().strip() else: dlg.Destroy() return dlg.Destroy() try: E,SSGData = G2spc.SSpcGroup(generalData['SGData'],SSymbol) except: E = 'Invalid modulation group' SSGData = None if SSGData: Vec = generalData['SuperVec'][0] #(3+1) only modSymb = SSGData['modSymb'] generalData['SuperVec'][0] = G2spc.SSGModCheck(Vec,modSymb)[0] generalData['SSGData'] = SSGData generalData['SuperSg'] = SSymbol OnShowSOps(event) else: # needed in case someone manually enters an invalid SSG? Text = '\n'.join([E+'\nSuperspace Group entry ignored']) G2G.G2MessageBox(General,Text,'Superspace Group Error') wx.CallAfter(UpdateGeneral) def OnVecRef(event): generalData['SuperVec'][1] = Ref.GetValue() def OnMax(event): generalData['SuperVec'][2] = int(Max.GetValue()) Indx = {} ssSizer = wx.BoxSizer(wx.VERTICAL) modSizer = wx.BoxSizer(wx.HORIZONTAL) modSizer.Add(wx.StaticText(General,label=' '+name.capitalize()+' structure controls: '),0,WACV) SGData = generalData['SGData'] SpGrp = SGData.get('MagSpGrp',SGData['SpGrp']) if SGData['SGGray']: SpGrp += " 1'" modSizer.Add(wx.StaticText(General,label=' Superspace group: %s '%SpGrp),0,WACV) if not SGData['SGFixed']: val = generalData['SuperSg'] superGp = wx.Button(General,wx.ID_ANY,val,size=(100,-1)) superGp.Bind(wx.EVT_BUTTON,OnSuperGp) else: superGp = wx.StaticText(General,label=generalData['SuperSg']) modSizer.Add(superGp,0,WACV) modSizer.Add((5,5),0) showOps = wx.Button(General,label='Show ops.') showOps.Bind(wx.EVT_BUTTON,OnShowSOps) modSizer.Add(showOps,0,WACV) if PWDR: modSizer.Add(wx.StaticText(General,label=' Max index: '),0,WACV) indChoice = ['1','2','3','4','5','6','7'] if 'Magnetic' in name.capitalize(): #limit to one for now indChoice = ['1',] Max = wx.ComboBox(General,-1,value='%d'%(generalData['SuperVec'][2]),choices=indChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) Max.Bind(wx.EVT_COMBOBOX,OnMax) modSizer.Add(Max,0,WACV) ssSizer.Add(modSizer,0) vecSizer = wx.FlexGridSizer(1,5,5,5) vecSizer.Add(wx.StaticText(General,label=' Modulation vector: '),0,WACV) modS = G2spc.splitSSsym(generalData['SuperSg'])[0] generalData['SuperVec'][0],ifShow = G2spc.SSGModCheck(generalData['SuperVec'][0],modS) for i,[val,show] in enumerate(zip(generalData['SuperVec'][0],ifShow)): if show: modVal = G2G.ValidatedTxtCtrl(General,generalData['SuperVec'][0],i,nDig=(10,4),xmin=-1.,xmax=2.) vecSizer.Add(modVal,0,WACV) Indx[modVal.GetId()] = i else: modVal = wx.TextCtrl(General,value=('%.3f'%(val)), size=wx.Size(50,20),style=wx.TE_READONLY) modVal.SetBackgroundColour(VERY_LIGHT_GREY) vecSizer.Add(modVal,0,WACV) if PWDR: Ref = wx.CheckBox(General,label='Refine?') Ref.SetValue(generalData['SuperVec'][1]) Ref.Bind(wx.EVT_CHECKBOX, OnVecRef) vecSizer.Add(Ref,0,WACV) ssSizer.Add(vecSizer) return ssSizer def PawleySizer(): def OnPawleyRef(event): generalData['doPawley'] = pawlRef.GetValue() pawleySizer = wx.BoxSizer(wx.HORIZONTAL) pawleySizer.Add(wx.StaticText(General,label=' Pawley controls: '),0,WACV) pawlRef = wx.CheckBox(General,-1,label=' Do Pawley refinement?') pawlRef.SetValue(generalData['doPawley']) pawlRef.Bind(wx.EVT_CHECKBOX,OnPawleyRef) pawleySizer.Add(pawlRef,0,WACV) pawleySizer.Add(wx.StaticText(General,label=' Pawley dmin: '),0,WACV) pawlMin = G2G.ValidatedTxtCtrl(General,generalData,'Pawley dmin',size=(65,25), xmin=0.25,xmax=20.,nDig=(10,5)) pawleySizer.Add(pawlMin,0,WACV) pawleySizer.Add(wx.StaticText(General,label=' Pawley dmax: '),0,WACV) pawlMax = G2G.ValidatedTxtCtrl(General,generalData,'Pawley dmax',size=(65,25), xmin=2.0,xmax=100.,nDig=(10,5)) pawleySizer.Add(pawlMax,0,WACV) pawleySizer.Add(wx.StaticText(General,label=' Pawley neg. wt.: '),0,WACV) pawlNegWt = G2G.ValidatedTxtCtrl(General,generalData,'Pawley neg wt',size=(65,25), xmin=0.,xmax=1.,nDig=(10,3,'g')) pawleySizer.Add(pawlNegWt,0,WACV) return pawleySizer def MapSizer(): def OnMapType(event): Map['MapType'] = mapType.GetValue() if 'delt-F' in Map['MapType']: data['Drawing']['contourColor'] = 'RdYlGn' else: data['Drawing']['contourColor'] = 'YlGnBu' def OnRefList(event): if not refsList: G2G.G2MessageBox(G2frame,'No reflections') return dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select reflection sets to use', 'Use data',refsList) try: if dlg.ShowModal() == wx.ID_OK: if not len(dlg.GetSelections()): dlg.Destroy() return Map['RefList'] = [refsList[i] for i in dlg.GetSelections()] else: dlg.Destroy() return finally: dlg.Destroy() wx.CallAfter(UpdateGeneral,General.GetScrollPos(wx.VERTICAL)) def OnDysnomia(event): data['General']['doDysnomia'] = not data['General']['doDysnomia'] pages = [G2frame.phaseDisplay.GetPageText(PageNum) for PageNum in range(G2frame.phaseDisplay.GetPageCount())] if generalData['doDysnomia']: if 'Dysnomia' not in pages: G2frame.MEMData = wx.ScrolledWindow(G2frame.phaseDisplay) G2frame.Bind(wx.EVT_MENU, OnLoadDysnomia, id=G2G.wxID_LOADDYSNOMIA) G2frame.Bind(wx.EVT_MENU, OnSaveDysnomia, id=G2G.wxID_SAVEDYSNOMIA) G2frame.Bind(wx.EVT_MENU, OnRunDysnomia, id=G2G.wxID_RUNDYSNOMIA) G2frame.phaseDisplay.InsertPage(7,G2frame.MEMData,'Dysnomia') Id = wx.NewId() TabSelectionIdDict[Id] = 'Dysnomia' if 'Dysnomia' not in data: #set defaults here data['Dysnomia'] = {'DenStart':'uniform','Optimize':'ZSPA','Lagrange':['user',0.001,0.05], 'wt pwr':0,'E_factor':1.,'Ncyc':5000,'prior':'uniform','Lam frac':[1,0,0,0,0,0,0,0], 'overlap':0.2,'MEMdmin':1.0} else: if 'Dysnomia' in pages: G2frame.phaseDisplay.DeletePage(pages.index('Dysnomia')) #patch if 'cutOff' not in Map: Map['cutOff'] = 100.0 if 'Resolution' in Map: Map['GridStep'] = Map['Resolution'] mapTypes = ['Fobs','Fcalc','delt-F','2*Fo-Fc','Omit','2Fo-Fc Omit','Patterson'] refsList = [item for item in G2gd.GetGPXtreeDataNames(G2frame,['HKLF','PWDR']) if item in data['Histograms'].keys()] if not generalData['AtomTypes']: mapTypes = ['Patterson',] Map['MapType'] = 'Patterson' mapSizer = wx.BoxSizer(wx.VERTICAL) lineSizer = wx.BoxSizer(wx.HORIZONTAL) lineSizer.Add(wx.StaticText(General,label=' Fourier map controls: Map type: '),0,WACV) mapType = wx.ComboBox(General,value=Map['MapType'],choices=mapTypes, style=wx.CB_READONLY|wx.CB_DROPDOWN) mapType.Bind(wx.EVT_COMBOBOX,OnMapType) lineSizer.Add(mapType,0,WACV) lineSizer.Add(wx.StaticText(General,label=' Reflection sets: '),0,WACV) if 'list' not in str(type(Map['RefList'])): #patch Map['RefList'] = [Map['RefList'],] lineSizer.Add(wx.ComboBox(General,value=Map['RefList'][0],choices=Map['RefList'], style=wx.CB_DROPDOWN|wx.CB_READONLY),0,WACV) refList = wx.Button(General,label='Select reflection sets') refList.Bind(wx.EVT_BUTTON,OnRefList) lineSizer.Add(refList,0,WACV) mapSizer.Add(lineSizer,0) line2Sizer = wx.BoxSizer(wx.HORIZONTAL) line2Sizer.Add(wx.StaticText(General,label=' Map grid step: '),0,WACV) mapRes = G2G.ValidatedTxtCtrl(General,Map,'GridStep',nDig=(10,2),xmin=0.1,xmax=2.) line2Sizer.Add(mapRes,0,WACV) line2Sizer.Add(wx.StaticText(General,label=' Peak cutoff %: '),0,WACV) cutOff = G2G.ValidatedTxtCtrl(General,Map,'cutOff',nDig=(10,1),xmin=1.0,xmax=100.) line2Sizer.Add(cutOff,0,WACV) if len(Map['RefList']) and not generalData['Modulated']: if all(['PWDR' in map for map in Map['RefList']]): Dysno = wx.CheckBox(General,-1,label=' Use Dysnomia (Max. Ent. Method)?') Dysno.SetValue(generalData['doDysnomia']) Dysno.Bind(wx.EVT_CHECKBOX,OnDysnomia) line2Sizer.Add(Dysno,0,WACV) mapSizer.Add(line2Sizer,0) return mapSizer def FlipSizer(): #patches if 'k-Max' not in Flip: Flip['k-Max'] = 20. if 'Resolution' in Flip: Flip['GridStep'] = Flip['Resolution'] def OnRefList(event): dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select reflection sets to use', 'Use data',refsList) try: if dlg.ShowModal() == wx.ID_OK: if not len(dlg.GetSelections()): dlg.Destroy() return Flip['RefList'] = [refsList[i] for i in dlg.GetSelections()] else: dlg.Destroy() return finally: dlg.Destroy() wx.CallAfter(UpdateGeneral,General.GetScrollPos(wx.VERTICAL)) def OnNormElem(event): PE = G2elemGUI.PickElement(G2frame,ifNone=True) if PE.ShowModal() == wx.ID_OK: Flip['Norm element'] = PE.Elem.strip() normElem.SetLabel(Flip['Norm element']) PE.Destroy() def OnTestHKL(event): event.Skip() Obj = event.GetEventObject() name = Obj.GetName() try: vals = Obj.GetValue().split() Id = int(name.split('hkl')[1]) HKL = [int(val) for val in vals] Flip['testHKL'][Id] = HKL except ValueError: HKL = Flip['testHKL'][Id] Obj.SetValue('%3d %3d %3d'%(HKL[0],HKL[1],HKL[2])) refsList = [item for item in G2gd.GetGPXtreeDataNames(G2frame,['HKLF','PWDR']) if item in data['Histograms'].keys()] flipSizer = wx.BoxSizer(wx.VERTICAL) lineSizer = wx.BoxSizer(wx.HORIZONTAL) lineSizer.Add(wx.StaticText(General,label=' Charge flip controls: Reflection sets: '),0,WACV) if 'list' not in str(type(Flip['RefList'])): #patch Flip['RefList'] = [Flip['RefList'],] lineSizer.Add(wx.ComboBox(General,value=Flip['RefList'][0],choices=Flip['RefList'], style=wx.CB_DROPDOWN|wx.CB_READONLY),0,WACV) refList = wx.Button(General,label='Select reflection sets') refList.Bind(wx.EVT_BUTTON,OnRefList) lineSizer.Add(refList,0,WACV) lineSizer.Add(wx.StaticText(General,label=' Normalizing element: '),0,WACV) normElem = wx.Button(General,label=Flip['Norm element'],style=wx.TE_READONLY) normElem.Bind(wx.EVT_BUTTON,OnNormElem) lineSizer.Add(normElem,0,WACV) flipSizer.Add(lineSizer,0) line2Sizer = wx.BoxSizer(wx.HORIZONTAL) line2Sizer.Add(wx.StaticText(General,label=' Map grid step: '),0,WACV) flipRes = G2G.ValidatedTxtCtrl(General,Flip,'GridStep',nDig=(10,2),xmin=0.10,xmax=2.) line2Sizer.Add(flipRes,0,WACV) line2Sizer.Add(wx.StaticText(General,label=' k-Factor (0.1-1.2): '),0,WACV) kFactor = G2G.ValidatedTxtCtrl(General,Flip,'k-factor',nDig=(10,3),xmin=0.1,xmax=1.2) line2Sizer.Add(kFactor,0,WACV) line2Sizer.Add(wx.StaticText(General,label=' k-Max (>=10.0): '),0,WACV) kMax = G2G.ValidatedTxtCtrl(General,Flip,'k-Max',nDig=(10,1),xmin=10.) line2Sizer.Add(kMax,0,WACV) flipSizer.Add(line2Sizer,0) line3Sizer = wx.BoxSizer(wx.HORIZONTAL) line3Sizer.Add(wx.StaticText(General,label=' Test HKLs:'),0,WACV) if len(Flip['testHKL']) < 5: Flip['testHKL'] += [[1,1,1],[0,2,0],[1,2,3]] HKL = Flip['testHKL'] for ih,hkl in enumerate(Flip['testHKL']): # Zstep = G2G.ValidatedTxtCtrl(drawOptions,drawingData,'Zstep',nDig=(10,2),xmin=0.01,xmax=4.0) hkl = wx.TextCtrl(General,value='%3d %3d %3d'%(HKL[ih][0],HKL[ih][1],HKL[ih][2]), style=wx.TE_PROCESS_ENTER,name='hkl%d'%(ih)) hkl.Bind(wx.EVT_TEXT_ENTER,OnTestHKL) hkl.Bind(wx.EVT_KILL_FOCUS,OnTestHKL) line3Sizer.Add(hkl,0,WACV) flipSizer.Add(line3Sizer) return flipSizer def MCSASizer(): def OnRefList(event): MCSAdata['Data source'] = refList.GetValue() def OnCycles(event): MCSAdata['Cycles'] = int(cycles.GetValue()) def OnAlist(event): MCSAdata['Algorithm'] = Alist.GetValue() OnShowTsched() wx.CallAfter(UpdateGeneral,General.GetScrollPos(wx.VERTICAL)) def OnRanStart(event): MCSAdata['ranStart'] = ranStart.GetValue() # def OnAutoRan(event): # MCSAdata['autoRan'] = autoRan.GetValue() def OnAnneal(event): event.Skip() Obj = event.GetEventObject() ind,fmt = Indx[Obj.GetId()] if ind == 2: #No. trials try: val = int(Obj.GetValue()) if 1 <= val: MCSAdata['Annealing'][ind] = val except ValueError: Obj.SetValue(fmt%(MCSAdata['Annealing'][ind])) else: try: val = float(Obj.GetValue()) if .0 <= val: MCSAdata['Annealing'][ind] = val Obj.SetValue(fmt%(MCSAdata['Annealing'][ind])) except ValueError: MCSAdata['Annealing'][ind] = None Obj.SetValue(str(MCSAdata['Annealing'][ind])) def ShowTsched(invalid,value,tc): OnShowTsched() def OnShowTsched(): if MCSAdata['Algorithm'] in ['fast','log']: Y = G2mth.makeTsched(MCSAdata) XY = [np.arange(len(Y)),np.log10(Y)] G2plt.PlotXY(G2frame,[XY,],labelX='T-step',labelY='log(T)',newPlot=True,lines=True,Title='Annealing schedule') # OnShowTsched() refList = [] if len(data['Pawley ref']): refList = ['Pawley reflections',] refList += [item for item in G2gd.GetGPXtreeDataNames(G2frame,['HKLF','PWDR']) if item in data['Histograms'].keys()] mcsaSizer = wx.BoxSizer(wx.VERTICAL) lineSizer = wx.BoxSizer(wx.HORIZONTAL) lineSizer.Add(wx.StaticText(General,label=' Monte Carlo/Simulated Annealing controls: Reflection set from: '),0,WACV) refList = wx.ComboBox(General,-1,value=MCSAdata['Data source'],choices=refList, style=wx.CB_READONLY|wx.CB_DROPDOWN) refList.Bind(wx.EVT_COMBOBOX,OnRefList) lineSizer.Add(refList,0,WACV) lineSizer.Add(wx.StaticText(General,label=' d-min: '),0,WACV) dmin = G2G.ValidatedTxtCtrl(General,MCSAdata,'dmin',nDig=(10,3),xmin=1.,xmax=5.) lineSizer.Add(dmin,0,WACV) mcsaSizer.Add(lineSizer) mcsaSizer.Add((5,5),) line2Sizer = wx.BoxSizer(wx.HORIZONTAL) line2Sizer.Add(wx.StaticText(General,label=' MC/SA runs: '),0,WACV) Cchoice = [str(2**i) for i in range(13)] cycles = wx.ComboBox(General,-1,value=str(MCSAdata.get('Cycles',1)),choices=Cchoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) cycles.Bind(wx.EVT_COMBOBOX,OnCycles) line2Sizer.Add(cycles,0,WACV) line2Sizer.Add((5,0),) ranStart = wx.CheckBox(General,-1,label=' MC/SA Refine at ') ranStart.Bind(wx.EVT_CHECKBOX, OnRanStart) ranStart.SetValue(MCSAdata.get('ranStart',False)) line2Sizer.Add(ranStart,0,WACV) MCSAdata['ranRange'] = MCSAdata.get('ranRange',10.) #patch for old gpx files ranRange = G2G.ValidatedTxtCtrl(General,MCSAdata,'ranRange',nDig=(10,1),xmin=1.,xmax=99.) line2Sizer.Add(ranRange,0,WACV) line2Sizer.Add(wx.StaticText(General,label='% of ranges. '),0,WACV) mcsaSizer.Add(line2Sizer) mcsaSizer.Add((5,5),) line3Sizer = wx.BoxSizer(wx.HORIZONTAL) Achoice = ['log','fast','Basin Hopping'] #these work not 'boltzmann','cauchy', line3Sizer.Add(wx.StaticText(General,label=' MC/SA schedule: '),0,WACV) Alist = wx.ComboBox(General,-1,value=MCSAdata['Algorithm'],choices=Achoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) Alist.Bind(wx.EVT_COMBOBOX,OnAlist) line3Sizer.Add(Alist,0,WACV) if MCSAdata['Algorithm'] in ['fast',]: Names = [' quench: ',' c-factor: '] parms = 'fast parms' for i,name in enumerate(Names): line3Sizer.Add(wx.StaticText(General,label=name),0,WACV) Ajump = G2G.ValidatedTxtCtrl(General,MCSAdata[parms],i,nDig=(10,2),xmin=0.1,xmax=1.,OnLeave=ShowTsched) line3Sizer.Add(Ajump,0,WACV) elif 'log' in MCSAdata['Algorithm']: line3Sizer.Add(wx.StaticText(General,label=' slope: '),0,WACV) slope = G2G.ValidatedTxtCtrl(General,MCSAdata,'log slope',nDig=(10,3),xmin=0.25,xmax=1.0,OnLeave=ShowTsched) line3Sizer.Add(slope,0,WACV) elif 'Basin Hopping' in MCSAdata['Algorithm']: pass #TODO basinhopping controls here? mcsaSizer.Add(line3Sizer) mcsaSizer.Add((5,5),) line3Sizer = wx.BoxSizer(wx.HORIZONTAL) line3Sizer.Add(wx.StaticText(General,label=' Annealing schedule: '),0,WACV) if 'Basin Hopping' in MCSAdata['Algorithm']: line3Sizer.Add(wx.StaticText(General,label=' Test temp: '),0,WACV) line3Sizer.Add(G2G.ValidatedTxtCtrl(General,MCSAdata['Annealing'],0,nDig=(10,5)),0,WACV) else: line3Sizer.Add(wx.StaticText(General,label=' Start temp: '),0,WACV) line3Sizer.Add(G2G.ValidatedTxtCtrl(General,MCSAdata['Annealing'],0,nDig=(10,5),OnLeave=ShowTsched),0,WACV) line3Sizer.Add(wx.StaticText(General,label=' Final temp: '),0,WACV) line3Sizer.Add(G2G.ValidatedTxtCtrl(General,MCSAdata['Annealing'],1,nDig=(10,5),OnLeave=ShowTsched),0,WACV) line3Sizer.Add(wx.StaticText(General,label=' No. trials: '),0,WACV) line3Sizer.Add(G2G.ValidatedTxtCtrl(General,MCSAdata['Annealing'],2),0,WACV) mcsaSizer.Add(line3Sizer) return mcsaSizer def compareSizer(): def OnOatmOsel(event): generalData['Compare']['Oatoms'] = oatmsel.GetStringSelection() def OnTatmOsel(event): generalData['Compare']['Tatoms'] = tatmsel.GetStringSelection() def OnCompPlots(event): pName = generalData['Name'] Oatoms = generalData['Compare']['Oatoms'] Tatoms = generalData['Compare']['Tatoms'] bName = '%s-%s'%(Oatoms,Tatoms) try: Bonds = generalData['Compare']['Bonds'][bName] except KeyError: print('need to do Compare first for %s polyhedra plots'%bName) return Tilts = generalData['Compare']['Tilts'][bName] Vects = generalData['Compare']['Vects'][bName] dVects = generalData['Compare']['dVects'][bName] if len(Bonds['Obonds']): print(' Octahedra:') Bonds['Obonds'] = np.array(Bonds['Obonds']) Bmean = np.mean(Bonds['Obonds']) Bstd = np.std(Bonds['Obonds']) title = '%s-%s Octahedral bond lengths'%(Oatoms,Tatoms) G2plt.PlotBarGraph(G2frame,Bonds['Obonds'],Xname=r'$Bond, \AA$',Title=title, PlotName='Oct %s Bond for %s'%(bName,pName)) Tilts['Otilts'] = np.array(Tilts['Otilts']) Tmean = np.mean(Tilts['Otilts']) Tstd = np.std(Tilts['Otilts']) G2plt.PlotBarGraph(G2frame,Tilts['Otilts'],Xname='Tilts, deg', Title='Octahedral %s tilts'%Oatoms,PlotName='Oct %s Tilts for %s'%(bName,pName)) dVects['Ovec'] = np.reshape(np.array(dVects['Ovec']),(-1,3)) for ix,aX in enumerate(['X','Y','Z']): G2plt.PlotBarGraph(G2frame,dVects['Ovec'].T[ix],Xname=r'$%s%s, \AA$'%(GkDelta,aX), Title='%s Octahedral distortion'%Oatoms,PlotName='Oct %s %s-Delta for %s'%(bName,aX,pName)) Vects['Ovec'] = np.array(Vects['Ovec']) #3D plot of tilt vectors X = Vects['Ovec'].T[0] Y = Vects['Ovec'].T[1] Z = Vects['Ovec'].T[2] R = Tilts['Otilts'] G2plt.PlotXYZvect(G2frame,X,Y,Z,R,r'X-axis',r'Y-axis',r'Z-axis', Title=r'%s Octahedral tilt vectors'%Oatoms,PlotName='Oct %s tilts for %s'%(bName,pName)) print(' %s-%s bond distance: %.3f(%d)'%(Oatoms,Tatoms,Bmean,Bstd*1000)) print(' %s tilt angle: %.2f(%d)'%(Oatoms,Tmean,Tstd*100)) if len(Bonds['Tbonds']): print('Tetrahedra:') Bonds['Tbonds'] = np.array(Bonds['Tbonds']) Bmean = np.mean(Bonds['Tbonds']) Bstd = np.std(Bonds['Tbonds']) title = '%s-%s Tetrahedral bond lengths'%(Oatoms,Tatoms) G2plt.PlotBarGraph(G2frame,Bonds['Tbonds'],Xname=r'$Bond, \AA$',Title=title, PlotName='Tet %s Bond for %s'%(bName,pName)) Tilts['Ttilts'] = np.array(Tilts['Ttilts']) Tmean = np.mean(Tilts['Ttilts']) Tstd = np.std(Tilts['Ttilts']) G2plt.PlotBarGraph(G2frame,Tilts['Ttilts'],Xname='Tilts, deg', Title='Tetrahedral %s tilts'%Oatoms,PlotName='Tet %s Tilts for %s'%(bName,pName)) dVects['Tvec'] = np.reshape(np.array(dVects['Tvec']),(-1,3)) for ix,aX in enumerate(['X','Y','Z']): G2plt.PlotBarGraph(G2frame,dVects['Tvec'].T[ix],Xname=r'$%s%s, \AA$'%(GkDelta,aX), Title='%s Tetrahedral distortion'%Oatoms,PlotName='Tet %s %s-Delta for %s'%(bName,aX,pName)) Vects['Tvec'] = np.array(Vects['Tvec']) X = Vects['Tvec'].T[0] Y = Vects['Tvec'].T[1] Z = Vects['Tvec'].T[2] R = Tilts['Ttilts'] G2plt.PlotXYZvect(G2frame,X,Y,Z,R,r'X-axis',r'Y-axis',r'Z-axis', Title=r'%s Tetrahedral tilt vectors'%Oatoms,PlotName='Tet %s tilts for %s'%(bName,pName)) print(' %s-%s bond distance: %.3f(%d)'%(Oatoms,Tatoms,Bmean,Bstd*1000)) print(' %s tilt angle: %.2f(%d)'%(Oatoms,Tmean,Tstd*100)) Oatoms = generalData['Compare']['Oatoms'] Tatoms = generalData['Compare']['Tatoms'] bName = '%s-%s'%(Oatoms,Tatoms) atTypes = generalData['AtomTypes'] compSizer = wx.BoxSizer(wx.VERTICAL) compSizer.Add(wx.StaticText(General,label=' Compare polyhedra to ideal octahedra/tetrahedra:'),0) atmselSizer = wx.BoxSizer(wx.HORIZONTAL) atmselSizer.Add(wx.StaticText(General,label=' Select origin atom type: '),0,WACV) oatmsel = wx.ComboBox(General,choices=atTypes,style=wx.CB_READONLY|wx.CB_DROPDOWN) oatmsel.SetStringSelection(generalData['Compare']['Oatoms']) oatmsel.Bind(wx.EVT_COMBOBOX,OnOatmOsel) atmselSizer.Add(oatmsel,0,WACV) atmselSizer.Add(wx.StaticText(General,label=' Select target atom type: '),0,WACV) tatmsel = wx.ComboBox(General,choices=atTypes,style=wx.CB_READONLY|wx.CB_DROPDOWN) tatmsel.SetStringSelection(generalData['Compare']['Tatoms']) tatmsel.Bind(wx.EVT_COMBOBOX,OnTatmOsel) atmselSizer.Add(tatmsel,0,WACV) atmselSizer.Add(wx.StaticText(General,label=' Sampling fraction:: '),0,WACV) atmselSizer.Add(G2G.ValidatedTxtCtrl(General,generalData['Compare'],'Sampling',nDig=(8,3),xmin=0.0,xmax=1.0,),0,WACV) try: if len(generalData['Compare']['Bonds'][bName]['Obonds']) or len(generalData['Compare']['Bonds'][bName]['Tbonds']): plotBtn = wx.Button(General,label='Show plots?') plotBtn.Bind(wx.EVT_BUTTON,OnCompPlots) atmselSizer.Add(plotBtn) except KeyError: pass compSizer.Add(atmselSizer,0) return compSizer # UpdateGeneral execution starts here phaseTypes = ['nuclear','magnetic','macromolecular','faulted'] SetupGeneral() generalData = data['General'] # remove the Wave Data tab when present and not needed if not generalData['Modulated']: pages = [G2frame.phaseDisplay.GetPageText(PageNum) for PageNum in range(G2frame.phaseDisplay.GetPageCount())] if 'Wave Data' in pages: G2frame.phaseDisplay.DeletePage(pages.index('Wave Data')) Map = generalData['Map'] Flip = generalData['Flip'] MCSAdata = generalData['MCSA controls'] PWDR = any(['PWDR' in item for item in data['Histograms'].keys()]) #patches if 'Pawley dmax' not in data['General']: data['General']['Pawley dmax'] = 100.0 if 'SGFixed' not in data['General']['SGData']: data['General']['SGData']['SGFixed'] = False if 'SGGray' not in data['General']['SGData']: data['General']['SGData']['SGGray'] = False #end patches if General.GetSizer(): General.GetSizer().Clear(True) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add((5,5),0) mainSizer.Add(NameSizer(),0,wx.EXPAND) mainSizer.Add((5,5),0) mainSizer.Add(CellSizer(),0) mainSizer.Add((5,5),0) Indx = {} denSizer = None if len(generalData['AtomTypes']): denSizer = DenSizer() mainSizer.Add(denSizer[0]) mainSizer.Add((5,5),0) mainSizer.Add(ElemSizer()) G2G.HorizontalLine(mainSizer,General) if generalData['Type'] == 'magnetic': if not generalData['SGData']['SGFixed']: GenSym,GenFlg,BNSsym = G2spc.GetGenSym(generalData['SGData']) generalData['SGData']['GenSym'] = GenSym generalData['SGData']['GenFlg'] = GenFlg generalData['SGData']['MagSpGrp'] = G2spc.MagSGSym(generalData['SGData']) mainSizer.Add(MagSizer()) G2G.HorizontalLine(mainSizer,General) if generalData['Modulated']: G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_SINGLEMCSA,False) G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_MULTIMCSA,False) G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_4DCHARGEFLIP,True) mainSizer.Add(ModulatedSizer(generalData['Type']+' modulated')) G2G.HorizontalLine(mainSizer,General) else: G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_SINGLEMCSA,True) G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_MULTIMCSA,True) G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_4DCHARGEFLIP,False) mainSizer.Add(PawleySizer()) G2G.HorizontalLine(mainSizer,General) mainSizer.Add(MapSizer()) G2G.HorizontalLine(mainSizer,General) mainSizer.Add(FlipSizer()) if generalData['Type'] in ['nuclear','macromolecular','faulted',]: G2G.HorizontalLine(mainSizer,General) mainSizer.Add(MCSASizer()) G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_COMPARESTRUCTURE,False) if generalData['SGData']['SpGrp'] == 'P 1': G2frame.dataWindow.GeneralCalc.Enable(G2G.wxID_COMPARESTRUCTURE,True) G2G.HorizontalLine(mainSizer,General) mainSizer.Add(compareSizer()) if SkipDraw: mainSizer.Clear(True) return G2frame.GetStatusBar().SetStatusText('',1) SetPhaseWindow(General,mainSizer,Scroll=Scroll) def OnTransform(event): Trans = np.eye(3) Uvec = np.zeros(3) Vvec = np.zeros(3) ifMag = False BNSlatt = '' while True: dlg = TransformDialog(G2frame,data,Trans,Uvec,Vvec,ifMag,BNSlatt) try: if dlg.ShowModal() == wx.ID_OK: newPhase,Trans,Uvec,Vvec,ifMag,ifConstr,Common = dlg.GetSelection() newPhase['ranId'] = ran.randint(0,sys.maxsize) SGData = newPhase['General']['SGData'] if ifMag: BNSlatt = SGData['BNSlattsym'][0] SGData['GenSym'],SGData['GenFlg'],BNSsym = G2spc.GetGenSym(SGData) if '_' in BNSlatt: SGData['BNSlattsym'] = [BNSlatt,BNSsym[BNSlatt]] G2spc.ApplyBNSlatt(SGData,SGData['BNSlattsym']) if SGData['SGGray']: if SGData['SGInv']: SGData['SpnFlp'] = np.concatenate((SGData['SpnFlp'],SGData['SpnFlp'])) SGData['SpnFlp'] = np.concatenate((SGData['SpnFlp'],-1*SGData['SpnFlp'])) SGData['MagSpGrp'] = G2spc.MagSGSym(SGData) if not '_' in BNSlatt: SGData['SGSpin'] = G2spc.GetSGSpin(SGData,SGData['MagSpGrp']) else: return finally: dlg.Destroy() if 'setting' in Common: #don't make new phase, Just move atoms! generalData = data['General'] cx,ct,cs,cia = generalData['AtomPtrs'] SGData = generalData['SGData'] if SGData['SpGrp'] in G2spc.spg2origins: T = G2spc.spg2origins[SGData['SpGrp']] Atoms = data['Atoms'] for atom in Atoms: for i in [0,1,2]: atom[cx+i] += T[i] SytSym,Mul,Nop,dupDir = G2spc.SytSym(atom[3:6],SGData) # update symmetry & mult atom[cs:cs+2] = SytSym,Mul data['Drawing'] = [] #force redraw of page sub = G2frame.GPXtree.GetSelection() G2frame.GPXtree.SelectItem(G2frame.GPXtree.root) wx.CallAfter(G2frame.GPXtree.SelectItem,sub) return else: phaseName = newPhase['General']['Name'] newPhase,atCodes = G2lat.TransformPhase(data,newPhase,Trans,Uvec,Vvec,ifMag) detTrans = np.abs(nl.det(Trans)) generalData = newPhase['General'] SGData = generalData['SGData'] SGData['fromParent'] = [Trans,Uvec,Vvec] #save these Atoms = newPhase['Atoms'] if ifMag: atMxyz = [] for atom in Atoms: if data['General']['Super']: atom += [{'SS1':{'waveType':'Fourier','Sfrac':[],'Spos':[],'Sadp':[],'Smag':[]}}] SytSym,Mul,Nop,dupDir = G2spc.SytSym(atom[3:6],SGData) CSI = G2spc.GetCSpqinel(SGData['SpnFlp'],dupDir) MagSytSym = G2spc.MagSytSym(SytSym,dupDir,SGData) atMxyz.append([MagSytSym,CSI[0]]) dlg = UseMagAtomDialog(G2frame,SGData['MagSpGrp'],Atoms,atCodes,atMxyz,ifDelete=False) try: opt = dlg.ShowModal() if opt == wx.ID_YES: newPhase['Atoms'],atCodes = dlg.GetSelection() generalData['Lande g'] = len(generalData['AtomTypes'])*[2.,] break else: return finally: dlg.Destroy() else: break NShkl = len(G2spc.MustrainNames(SGData)) NDij = len(G2spc.HStrainNames(SGData)) UseList = newPhase['Histograms'] for hist in UseList: UseList[hist]['Scale'] /= detTrans #scale by 1/volume ratio UseList[hist]['Mustrain'][4:6] = [NShkl*[0.01,],NShkl*[False,]] UseList[hist]['HStrain'] = [NDij*[0.0,],NDij*[False,]] newPhase['General']['Map'] = mapDefault.copy() sub = G2frame.GPXtree.AppendItem(parent= G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Phases'),text=phaseName) G2frame.GPXtree.SetItemPyData(sub,newPhase) newPhase['Drawing'] = [] if ifConstr: G2cnstG.TransConstraints(G2frame,data,newPhase,Trans,Vvec,atCodes) #data is old phase G2frame.GPXtree.SelectItem(sub) def OnCompare(event): generalData = data['General'] cx,ct,cs,cia = generalData['AtomPtrs'] atNames = [atm[ct-1] for atm in data['Atoms']] if not generalData['Compare']['Oatoms'] or not generalData['Compare']['Tatoms']: G2frame.ErrorDialog('Compare atom selection error','Select atoms for polygon comparison first') return bName = '%s-%s'%(generalData['Compare']['Oatoms'],generalData['Compare']['Tatoms']) DisAglCtls = generalData.get('DisAglCtls',{}) dlg = G2G.DisAglDialog(G2frame,DisAglCtls,generalData) if dlg.ShowModal() == wx.ID_OK: generalData['DisAglCtls'] = dlg.GetData() dlg.Destroy() Natm = len(data['Atoms']) iAtm= 0 pgbar = wx.ProgressDialog('Process polyhedron compare for %d atoms'%Natm,'Atoms done=',Natm+1, style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT) Tilts = generalData['Compare']['Tilts'] Tilts.update({bName:{'Otilts':[],'Ttilts':[]}}) Bonds = generalData['Compare']['Bonds'] Bonds.update({bName:{'Obonds':[],'Tbonds':[]}}) Vects = generalData['Compare']['Vects'] Vects.update({bName:{'Ovec':[],'Tvec':[]}}) dVects = generalData['Compare']['dVects'] dVects.update({bName:{'Ovec':[],'Tvec':[]}}) Oatoms = generalData['Compare']['Oatoms'] nOct = 0 nTet = 0 nElse = 0 for iatm,atom in enumerate(data['Atoms']): if atom[ct] == Oatoms: if ran.random() > generalData['Compare']['Sampling']: iAtm += 1 continue results = G2mth.FindAllNeighbors(data,atom[ct-1],atNames,Orig=iatm)[0] #slow step if len(results) == 4: bond,std,meanDisp,stdDisp,A,V,dVec = G2mth.FindTetrahedron(results) Bonds[bName]['Tbonds'].append(bond) Tilts[bName]['Ttilts'].append(A) Vects[bName]['Tvec'].append(V) dVects[bName]['Tvec'].append(dVec) nTet += 1 elif len(results) == 6: bond,std,meanDisp,stdDisp,A,V,dVec = G2mth.FindOctahedron(results) Bonds[bName]['Obonds'].append(bond) Tilts[bName]['Otilts'].append(A) Vects[bName]['Ovec'].append(V) dVects[bName]['Ovec'].append(dVec) nOct += 1 else: print('%s is something else with %d vertices'%(atom[ct-1],len(results))) nElse += 1 GoOn = pgbar.Update(iAtm,newmsg='Atoms done=%d'%(iAtm)) iAtm += 1 if not GoOn[0]: print(' Compare aborted') break print(' Compare finished; nOct = %d, nTet = %d, nOther = %d'%(nOct,nTet,nElse)) pgbar.Destroy() wx.CallAfter(UpdateGeneral,General.GetScrollPos(wx.VERTICAL)) def OnUseBilbao(event): PatternName = data['magPhases'] PatternId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,PatternName) UnitCellsId = G2gd.GetGPXtreeItemId(G2frame,PatternId, 'Unit Cells List') UCdata = list(G2frame.GPXtree.GetItemPyData(UnitCellsId)) magData = UCdata[5] if len(UCdata[0]) < 17: #old version of k-SUBGROUPSMAG baseList = range(1,len(magData)+1) else: baseList = UCdata[0][16] magKeep = [] magIds = [] magchoices = [] ifMag = False itemList = [phase.get('gid',ip+1) for ip,phase in enumerate(magData)] phaseDict = dict(zip(itemList,magData)) for im,mid in enumerate(baseList): magdata = phaseDict[mid] if magdata['Keep']: if 'magAtms' in magdata: ifMag = True magdata['No.'] = im+1 trans = G2spc.Trans2Text(magdata['Trans']) vec = G2spc.Latt2text([magdata['Uvec'],]) magKeep.append(magdata) magIds.append(mid) magchoices.append('(%d) %s; (%s) + (%s)'%(im+1,magdata['Name'],trans,vec)) if not len(magKeep): G2frame.ErrorDialog('Subgroup/magnetic phase selection error','No magnetic phases found; be sure to "Keep" some') return if ifMag: dlg = wx.SingleChoiceDialog(G2frame,'Select magnetic space group','Make new magnetic phase',magchoices) else: dlg = wx.SingleChoiceDialog(G2frame,'Select subgroup','Make new subgroup phase',magchoices) opt = dlg.ShowModal() if opt == wx.ID_OK: sel = dlg.GetSelection() magchoice = magKeep[sel] magId = magIds[sel] if ifMag: phaseName = '%s-mag_%d'%(data['General']['Name'],magchoice['No.']) else: phaseName = '%s-sub_%d'%(data['General']['Name'],magchoice['No.']) newPhase = copy.deepcopy(data) newPhase['ranId'] = ran.randint(0,sys.maxsize), del newPhase['magPhases'] generalData = newPhase['General'] generalData['Name'] = phaseName generalData['SGData'] = copy.deepcopy(magchoice['SGData']) generalData['Cell'][1:] = magchoice['Cell'][:] generalData['MagDmin'] = 1.0 SGData = generalData['SGData'] vvec = np.array([0.,0.,0.]) newPhase,atCodes = G2lat.TransformPhase(data,newPhase,magchoice['Trans'],magchoice['Uvec'],vvec,ifMag) Atoms = newPhase['Atoms'] Atms = [] AtCods = [] atMxyz = [] for ia,atom in enumerate(Atoms): if ifMag and not len(G2elem.GetMFtable([atom[1],],[2.0,])): continue atom[0] += '_%d'%ia atom[2] = '' #clear away refinement flags SytSym,Mul,Nop,dupDir = G2spc.SytSym(atom[3:6],SGData) Atms.append(atom) AtCods.append(atCodes[ia]) if ifMag: MagSytSym = G2spc.MagSytSym(SytSym,dupDir,SGData) CSI = G2spc.GetCSpqinel(SGData['SpnFlp'],dupDir) atMxyz.append([MagSytSym,CSI[0]]) else: CSI = G2spc.GetCSxinel(SytSym) atMxyz.append([SytSym,CSI[0]]) dlg = UseMagAtomDialog(G2frame,magchoices[sel],Atms,AtCods,atMxyz,ifMag=ifMag,ifDelete=True) try: opt = dlg.ShowModal() if opt == wx.ID_YES: G2frame.OnFileSave(event) #saves current state of Unit Cell List newPhase['Atoms'],atCodes = dlg.GetSelection() generalData['Lande g'] = len(generalData['AtomTypes'])*[2.,] elif opt == wx.ID_DELETE: magData[magId]['Keep'] = False return else: #wx.ID_NO return finally: dlg.Destroy() else: return NShkl = len(G2spc.MustrainNames(SGData)) NDij = len(G2spc.HStrainNames(SGData)) UseList = newPhase['Histograms'] detTrans = np.abs(nl.det(magchoice['Trans'])) for hist in UseList: UseList[hist]['Scale'] /= detTrans #scale by 1/volume ratio UseList[hist]['Mustrain'][4:6] = [NShkl*[0.01,],NShkl*[False,]] UseList[hist]['HStrain'] = [NDij*[0.0,],NDij*[False,]] newPhase['General']['Map'] = mapDefault.copy() sub = G2frame.GPXtree.AppendItem(parent= G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Phases'),text=phaseName) G2frame.GPXtree.SetItemPyData(sub,newPhase) newPhase['Drawing'] = [] if ifMag: G2cnstG.TransConstraints(G2frame,data,newPhase,magchoice['Trans'],vvec,atCodes) #data is old phase G2frame.newGPXfile = phaseName.replace('.','_')+'.gpx' #'.' in file names is a bad idea UCdata[5] = [] #clear away other mag choices from chem phase in new project G2frame.GPXtree.SetItemPyData(UnitCellsId,UCdata) G2frame.OnFileSaveas(event) G2frame.GPXtree.SelectItem(sub) ##### Atom routines ################################################################################ def FillAtomsGrid(Atoms): '''Display the contents of the Atoms tab ''' def RefreshAtomGrid(event): r,c = event.GetRow(),event.GetCol() if r < 0 and c < 0: for row in range(Atoms.GetNumberRows()): Atoms.SelectRow(row,True) return if r < 0: #double click on col label! Change all atoms! noSkip = True parms = '' if Atoms.GetColLabelValue(c) == 'refine': Type = generalData['Type'] if Type in ['nuclear','macromolecular','faulted',]: choice = ['F - site fraction','X - coordinates','U - thermal parameters'] elif Type in ['magnetic',]: choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment'] dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelections() parms = '' for x in sel: parms += choice[x][0] dlg.Destroy() elif Atoms.GetColLabelValue(c) == 'I/A': choice = ['Isotropic','Anisotropic'] dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal Motion',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parms = choice[sel][0] dlg.Destroy() elif Atoms.GetColLabelValue(c) == 'Type': choice = generalData['AtomTypes'] dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom types',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parms = choice[sel] noSkip = False Atoms.ClearSelection() for row in range(Atoms.GetNumberRows()): if parms == atomData[row][c]: Atoms.SelectRow(row,True) dlg.Destroy() SetupGeneral() elif Atoms.GetColLabelValue(c) == 'Name': choice = [] for r in range(Atoms.GetNumberRows()): if str(atomData[r][c]) not in choice: choice.append(str(atomData[r][c])) choice.sort() dlg = wx.SingleChoiceDialog(G2frame,'Select atom(s) by name', 'Name Selection',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parms = choice[sel] noSkip = False Atoms.ClearSelection() for row in range(Atoms.GetNumberRows()): if parms == atomData[row][c]: Atoms.SelectRow(row,True) dlg.Destroy() else: dlg.Destroy() return elif Atoms.GetColLabelValue(c) == 'residue': choice = [] for r in range(Atoms.GetNumberRows()): if str(atomData[r][c]) not in choice: choice.append(str(atomData[r][c])) choice.sort() dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parms = choice[sel] noSkip = False Atoms.ClearSelection() for row in range(Atoms.GetNumberRows()): if parms == atomData[row][c]: Atoms.SelectRow(row,True) dlg.Destroy() elif Atoms.GetColLabelValue(c) == 'res no': choice = [] for r in range(Atoms.GetNumberRows()): if str(atomData[r][c]) not in choice: choice.append(str(atomData[r][c])) dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue no.',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parms = choice[sel] noSkip = False Atoms.ClearSelection() for row in range(Atoms.GetNumberRows()): if int(parms) == atomData[row][c]: Atoms.SelectRow(row,True) dlg.Destroy() elif Atoms.GetColLabelValue(c) == 'chain': choice = [] for r in range(Atoms.GetNumberRows()): if atomData[r][c] not in choice: choice.append(atomData[r][c]) dlg = wx.SingleChoiceDialog(G2frame,'Select','Chain',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parms = choice[sel] noSkip = False Atoms.ClearSelection() for row in range(Atoms.GetNumberRows()): if parms == atomData[row][c]: Atoms.SelectRow(row,True) dlg.Destroy() elif Atoms.GetColLabelValue(c) == 'Uiso': #this needs to ask for value return #& then change all 'I' atoms; now do nothing else: return if noSkip: ui = colLabels.index('U11') us = colLabels.index('Uiso') ss = colLabels.index('site sym') for r in range(Atoms.GetNumberRows()): ID = atomData[r][ui+6] if parms != atomData[r][c] and Atoms.GetColLabelValue(c) == 'I/A': if parms == 'A': #'I' --> 'A' Uiso = float(Atoms.GetCellValue(r,us)) sytsym = atomData[r][ss] CSI = G2spc.GetCSuinel(sytsym) atomData[r][ui:ui+6] = Uiso*np.array(CSI[3]) atomData[r][us] = 0.0 Atoms.SetCellStyle(r,us,VERY_LIGHT_GREY,True) for i in range(6): ci = ui+i Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True) if CSI[2][i]: Atoms.SetCellStyle(r,ci,WHITE,False) else: #'A' --> 'I' Uij = atomData[r][ui:ui+6] Uiso = (Uij[0]+Uij[1]+Uij[2])/3.0 atomData[r][us] = Uiso Atoms.SetCellStyle(r,us,WHITE,False) for i in range(6): ci = ui+i atomData[r][ci] = 0.0 Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True) if not Atoms.IsReadOnly(r,c): if Atoms.GetColLabelValue(c) == 'refine': rbExcl = rbAtmDict.get(atomData[r][ui+6],'') if rbExcl: for excl in rbExcl: atomData[r][c] = parms.replace(excl,'') else: atomData[r][c] = parms else: atomData[r][c] = parms if 'Atoms' in data['Drawing']: G2mth.DrawAtomsReplaceByID(data,ui+6,atomData[r],ID) wx.CallAfter(Paint) def ChangeAtomCell(event): def chkUij(Uij,CSI): #needs to do something!!! return Uij SGData = generalData['SGData'] r,c = event.GetRow(),event.GetCol() replot = True if r >= 0 and c >= 0: ci = colLabels.index('I/A') ID = atomData[r][ci+8] if Atoms.GetColLabelValue(c) in ['x','y','z']: ci = colLabels.index('x') XYZ = atomData[r][ci:ci+3] if None in XYZ: XYZ = [0,0,0] SScol = colLabels.index('site sym') Mulcol = colLabels.index('mult') Sytsym,Mult = G2spc.SytSym(XYZ,SGData)[:2] atomData[r][SScol] = Sytsym atomData[r][Mulcol] = Mult if atomData[r][colLabels.index('I/A')] == 'A': ui = colLabels.index('U11') CSI = G2spc.GetCSuinel(Sytsym) atomData[r][ui:ui+6] = chkUij(atomData[r][ui:ui+6],Sytsym) for i in range(6): ci = i+ui Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True) if CSI[2][i]: Atoms.SetCellStyle(r,ci,WHITE,False) SetupGeneral() elif Atoms.GetColLabelValue(c) == 'Type': AtomTypeSelect(event) elif Atoms.GetColLabelValue(c) == 'I/A': #note use of text color to make it vanish! if atomData[r][c] == 'I': Uij = atomData[r][c+2:c+8] atomData[r][c+1] = (Uij[0]+Uij[1]+Uij[2])/3.0 Atoms.SetCellStyle(r,c+1,WHITE,False) Atoms.SetCellTextColour(r,c+1,BLACK) for i in range(6): ci = i+colLabels.index('U11') Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True) Atoms.SetCellTextColour(r,ci,VERY_LIGHT_GREY) atomData[r][ci] = 0.0 else: value = atomData[r][c+1] CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')]) Atoms.SetCellStyle(r,c+1,VERY_LIGHT_GREY,True) Atoms.SetCellTextColour(r,c+1,VERY_LIGHT_GREY) for i in range(6): ci = i+colLabels.index('U11') atomData[r][ci] = value*CSI[3][i] Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True) Atoms.SetCellTextColour(r,ci,BLACK) if CSI[2][i]: Atoms.SetCellStyle(r,ci,WHITE,False) atomData[r][c+1] = 0.0 elif Atoms.GetColLabelValue(c) in ['U11','U22','U33','U12','U13','U23']: value = atomData[r][c] CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')]) iUij = CSI[0][c-colLabels.index('U11')] for i in range(6): if iUij == CSI[0][i]: atomData[r][i+colLabels.index('U11')] = value*CSI[1][i] elif Atoms.GetColLabelValue(c) == 'refine': ci = colLabels.index('I/A') atomData[r][c] = atomData[r][c].replace(rbAtmDict.get(atomData[r][ci+8],''),'') replot = False elif Atoms.GetColLabelValue(c) in ['Mx','My','Mz']: value = atomData[r][c] cx = colLabels.index('x') SpnFlp = generalData['SGData']['SpnFlp'] SytSym,Mul,Nop,dupDir = G2spc.SytSym(atomData[r][cx:cx+3],SGData) CSI = G2spc.GetCSpqinel(SpnFlp,dupDir) iM = CSI[0][c-colLabels.index('Mx')] for i in range(3): if iM == CSI[0][i]: atomData[r][i+colLabels.index('Mx')] = value*CSI[1][i] if 'Atoms' in data['Drawing'] and replot: ci = colLabels.index('I/A') G2mth.DrawAtomsReplaceByID(data,ci+8,atomData[r],ID) G2plt.PlotStructure(G2frame,data) if SGData['SpGrp'] != 'P 1': #no need to update P 1 structures! wx.CallAfter(Paint) def AtomTypeSelect(event): r,c = event.GetRow(),event.GetCol() if Atoms.GetColLabelValue(c) == 'Type': PE = G2elemGUI.PickElement(G2frame,ifMag=ifMag) if PE.ShowModal() == wx.ID_OK: if PE.Elem != 'None': atomData[r][c] = PE.Elem.strip() name = atomData[r][c] if len(name) in [2,4]: atomData[r][c-1] = name[:2]+'%d'%(r+1) else: atomData[r][c-1] = name[:1]+'%d'%(r+1) PE.Destroy() SetupGeneral() wx.CallAfter(Paint) value = Atoms.GetCellValue(r,c) atomData[r][c] = value ci = colLabels.index('I/A') ID = atomData[r][ci+8] if 'Atoms' in data['Drawing']: G2mth.DrawAtomsReplaceByID(data,ci+8,atomData[r],ID) G2plt.PlotStructure(G2frame,data) SetupGeneral() else: event.Skip() def RowSelect(event): r,c = event.GetRow(),event.GetCol() if not (event.AltDown() or (event.ShiftDown() and event.ControlDown())): Atoms.frm = -1 if r < 0 and c < 0: if Atoms.IsSelection(): Atoms.ClearSelection() elif c < 0: #only row clicks ci = colLabels.index('I/A') if event.ControlDown() and not event.ShiftDown(): if r in Atoms.GetSelectedRows(): Atoms.DeselectRow(r) else: Atoms.SelectRow(r,True) elif event.ShiftDown() and not event.ControlDown(): indxs = Atoms.GetSelectedRows() Atoms.ClearSelection() ibeg = 0 if indxs: ibeg = indxs[-1] for row in range(ibeg,r+1): Atoms.SelectRow(row,True) elif event.AltDown() or (event.ShiftDown() and event.ControlDown()): if atomData[r][ci+8] in rbAtmDict: G2frame.ErrorDialog('Atom move error','Atoms in rigid bodies can not be moved') Atoms.frm = -1 Atoms.ClearSelection() else: if Atoms.frm < 0: #pick atom to be moved Atoms.frm = r Atoms.SelectRow(r,True) n = colLabels.index('Name') G2frame.GetStatusBar().SetStatusText('Atom '+atomData[r][n]+' is to be moved',1) else: #move it item = atomData.pop(Atoms.frm) atomData.insert(r,item) Atoms.frm = -1 G2frame.GetStatusBar().SetStatusText('',1) data['Drawing']['Atoms'] = [] #clear & rebuild Draw atoms table UpdateDrawAtoms() wx.CallAfter(Paint) else: G2frame.GetStatusBar().SetStatusText('Use right mouse click to brng up Atom editing options',1) Atoms.ClearSelection() Atoms.SelectRow(r,True) G2plt.PlotStructure(G2frame,data) def ChangeSelection(event): r,c = event.GetRow(),event.GetCol() if r < 0 and c < 0: Atoms.ClearSelection() if c < 0: if r in Atoms.GetSelectedRows(): Atoms.DeselectRow(r) else: Atoms.SelectRow(r,True) if r < 0: if c in Atoms.GetSelectedCols(): Atoms.DeselectCol(c) else: Atoms.SelectCol(c,True) def Paint(Scroll=0): 'Place atom info into the table' table = [] rowLabels = [] for i,atom in enumerate(atomData): table.append(atom) rowLabels.append(str(i)) atomTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types) try: Atoms.SetTable(atomTable, True, useFracEdit=False) # Paint may be called after the Grid has been deleted except: return Atoms.frm = -1 colType = colLabels.index('Type') colR = colLabels.index('refine') colSS = colLabels.index('site sym') colF = colLabels.index('frac') colX = colLabels.index('x') colIA = colLabels.index('I/A') colU11 = colLabels.index('U11') colUiso = colLabels.index('Uiso') colM = 0 if 'Mx' in colLabels: colM = colLabels.index('Mx') # atTypes = generalData['AtomTypes'] # Lande = generalData['Lande g'] # AtInfo = dict(zip(atTypes,Lande)) # next 3 lines do not seem to do anything. Removed 5/20/21 BHT # attr = wx.grid.GridCellAttr() # attr.IncRef() #fix from Jim Hester # attr.SetEditor(G2G.GridFractionEditor(Atoms)) # # loop over all cols in table, set cell editor for numerical items for c,t in enumerate(Types): if not t.startswith(wg.GRID_VALUE_FLOAT): continue attr = wx.grid.GridCellAttr() attr.IncRef() #fix from Jim Hester attr.SetEditor(G2G.GridFractionEditor(Atoms)) if c in range(colU11-1,colU11+6): Atoms.SetColSize(c,50) attr.SetBackgroundColour(VERY_LIGHT_GREY) attr.SetTextColour(VERY_LIGHT_GREY) attr.SetReadOnly(True) Atoms.SetColAttr(c, attr) for row in range(Atoms.GetNumberRows()): #this is slow for large numbers of atoms atId = atomData[row][colIA+8] rbExcl = rbAtmDict.get(atId,'') if Atoms.GetCellValue(row,colIA) == 'A': try: #patch for sytsym name changes CSI = G2spc.GetCSuinel(atomData[row][colSS]) except KeyError: Sytsym,Mult = G2spc.SytSym(atomData[row][colX:colX+3],SGData)[:2] atomData[row][colSS] = Sytsym atomData[row][colSS+1] = Mult CSI = G2spc.GetCSuinel(Sytsym) Atoms.SetCellStyle(row,colUiso,VERY_LIGHT_GREY,True) Atoms.SetCellTextColour(row,colUiso,VERY_LIGHT_GREY) for i in range(6): cj = colU11+i Atoms.SetCellTextColour(row,cj,BLACK) if G2lat.Uij2Ueqv(atomData[row][colU11:colU11+6],GS,Amat)[1]: Atoms.SetCellTextColour(row,cj,RED) Atoms.SetCellStyle(row,cj,VERY_LIGHT_GREY,True) if CSI[2][i] and 'U' not in rbExcl: Atoms.SetCellStyle(row,cj,WHITE,False) else: Atoms.SetCellStyle(row,colUiso,WHITE,False) Atoms.SetCellTextColour(row,colUiso,BLACK) if atomData[row][colUiso] < 0.: Atoms.SetCellTextColour(row,colUiso,RED) if 'U' in rbExcl: Atoms.SetCellStyle(row,colUiso,VERY_LIGHT_GREY,True) if colM: SytSym,Mul,Nop,dupDir = G2spc.SytSym(atomData[row][colX:colX+3],SGData) MagSytSym = G2spc.MagSytSym(SytSym,dupDir,SGData) Atoms.SetCellValue(row,colSS,MagSytSym) CSI = [] if not SGData['SGGray']: CSI = G2spc.GetCSpqinel(SpnFlp,dupDir) saveCSI = 0 for i in range(3): ci = i+colM Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True) Atoms.SetCellTextColour(row,ci,VERY_LIGHT_GREY) if CSI and CSI[1][i]: # and AtInfo and AtInfo[atomData[row][colType]]: if saveCSI != CSI[0][i]: Atoms.SetCellStyle(row,ci,WHITE,False) saveCSI = CSI[0][i] Atoms.SetCellTextColour(row,ci,BLACK) if 'F' in rbExcl: Atoms.SetCellStyle(row,colF,VERY_LIGHT_GREY,True) if 'X' in rbExcl: for c in range(0,colX+3): if c != colR: Atoms.SetCellStyle(row,c,VERY_LIGHT_GREY,True) Atoms.SetReadOnly(row,colType,True) Atoms.SetReadOnly(row,colSS,True) #site sym Atoms.SetReadOnly(row,colSS+1,True) #Mult Atoms.AutoSizeColumns(False) SetPhaseWindow(Atoms,Scroll=Atoms.GetScrollPos(wx.VERTICAL)) #### FillAtomsGrid main code if not data['Drawing']: #if new drawing - no drawing data! SetupDrawingData() generalData = data['General'] cell = generalData['Cell'][1:7] Amat = G2lat.cell2AB(cell)[0] GS = G2lat.cell2GS(cell) SpnFlp = generalData['SGData'].get('SpnFlp',[]) atomData = data['Atoms'] resRBData = data['RBModels'].get('Residue',[]) vecRBData = data['RBModels'].get('Vector',[]) global rbAtmDict rbAtmDict = {} for rbObj in resRBData+vecRBData: exclList = ['FX' for i in range(len(rbObj['Ids']))] rbAtmDict.update(dict(zip(rbObj['Ids'],exclList))) if rbObj['ThermalMotion'][0] != 'None': for id in rbObj['Ids']: rbAtmDict[id] += 'U' # exclList will be 'fx' or 'fxu' if TLS used in RB Items = [G2G.wxID_ATOMSEDITINSERT,G2G.wxID_ATOMSEDITDELETE, G2G.wxID_ATOMSMODIFY,G2G.wxID_ATOMSTRANSFORM,G2G.wxID_MAKEMOLECULE, G2G.wxID_ATOMVIEWINSERT,G2G.wxID_ATOMMOVE,G2G.wxID_ADDHATOM] if atomData: for item in Items: G2frame.dataWindow.AtomsMenu.Enable(item,True) else: for item in Items: G2frame.dataWindow.AtomsMenu.Enable(item,False) Items = [G2G.wxID_ATOMVIEWINSERT, G2G.wxID_ATOMSVIEWADD,G2G.wxID_ATOMMOVE] if 'showABC' in data['Drawing']: for item in Items: G2frame.dataWindow.AtomsMenu.Enable(item,True) else: for item in Items: G2frame.dataWindow.AtomsMenu.Enable(item,False) parmChoice = ': ,X,XU,U,F,FX,FXU,FU' if generalData['Type'] == 'magnetic': parmChoice += ',M,MX,MXU,MU,MF,MFX,MFXU,MFU' AAchoice = ": ,ALA,ARG,ASN,ASP,CYS,GLN,GLU,GLY,HIS,ILE,LEU,LYS,MET,PHE,PRO,SER,THR,TRP,TYR,VAL,MSE,HOH,UNK" Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+parmChoice,]+ \ 3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_FLOAT+':10,4', #x,y,z,frac wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+":I,A",] Types += 7*[wg.GRID_VALUE_FLOAT+':10,5',] colLabels = ['Name','Type','refine','x','y','z','frac','site sym','mult','I/A','Uiso','U11','U22','U33','U12','U13','U23'] ifMag = False if generalData['Type'] == 'macromolecular': colLabels = ['res no','residue','chain'] + colLabels Types = [wg.GRID_VALUE_STRING, wg.GRID_VALUE_CHOICE+AAchoice, wg.GRID_VALUE_STRING] + Types elif generalData['Type'] == 'magnetic': ifMag = True colLabels = colLabels[:7]+['Mx','My','Mz']+colLabels[7:] Types = Types[:7]+3*[wg.GRID_VALUE_FLOAT+':10,4',]+Types[7:] SGData = data['General']['SGData'] G2frame.GetStatusBar().SetStatusText('',1) if SGData['SpGrp'] in G2spc.spg2origins: G2frame.GetStatusBar().SetStatusText('Warning: Atom positions must correspond to 2nd setting for the space group '+SGData['SpGrp'],1) if SGData['SGPolax']: G2frame.GetStatusBar().SetStatusText('Warning: The location of the origin is arbitrary in '+SGData['SGPolax'],1) if 'phoenix' in wx.version(): Atoms.Bind(wg.EVT_GRID_CELL_CHANGED, ChangeAtomCell) else: Atoms.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeAtomCell) Atoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, AtomTypeSelect) Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid) Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect) Atoms.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, ChangeSelection) lblList = ('Set refine flags','Modify selected parameters', 'Insert new before selected','Transform selected', 'Set selected xyz to view point','Select all', 'Select from list','Set view point from selected', 'Delete') callList = (AtomRefine,AtomModify,OnAtomInsert,AtomTransform, OnAtomMove,OnSetAll,OnSetbyList,SetAtomsViewPoint, AtomDelete) onRightClick = Atoms.setupPopup(lblList,callList) Atoms.Bind(wg.EVT_GRID_CELL_RIGHT_CLICK, onRightClick) Atoms.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, onRightClick) Atoms.SetMargins(0,0) Paint() def OnAtomAdd(event): Elem = 'H' if data['General']['Type'] == 'magnetic': Elem = 'Fe' AtomAdd(0.,0.,0.,El=Elem) FillAtomsGrid(Atoms) event.StopPropagation() if data['Drawing']: G2plt.PlotStructure(G2frame,data) def OnAtomViewAdd(event): Elem = 'H' if data['General']['Type'] == 'magnetic': Elem = 'Fe' try: drawData = data['Drawing'] x,y,z = drawData['viewPoint'][0] AtomAdd(x,y,z,El=Elem) except: AtomAdd(0.,0.,0.,El=Elem) FillAtomsGrid(Atoms) event.StopPropagation() data['Drawing']['Atoms'] = [] UpdateDrawAtoms() G2plt.PlotStructure(G2frame,data) def AtomAdd(x,y,z,El='H',Name='UNK',update=True): atomData = data['Atoms'] generalData = data['General'] atId = ran.randint(0,sys.maxsize) SGData = generalData['SGData'] Sytsym,Mult = G2spc.SytSym([x,y,z],SGData)[:2] if generalData['Type'] == 'macromolecular': atomData.append([0,Name,'',Name,El,'',x,y,z,1.,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId]) elif generalData['Type'] in ['nuclear','faulted',]: if generalData['Modulated']: atomData.append([Name,El,'',x,y,z,1.,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId,[],[], {'SS1':{'waveType':'Fourier','Sfrac':[],'Spos':[],'Sadp':[],'Smag':[]}}]) else: atomData.append([Name,El,'',x,y,z,1.,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId]) elif generalData['Type'] == 'magnetic': if generalData['Modulated']: atomData.append([Name,El,'',x,y,z,1.,0.,0.,0.,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId,[],[], {'SS1':{'waveType':'Fourier','Sfrac':[],'Spos':[],'Sadp':[],'Smag':[]}}]) else: atomData.append([Name,El,'',x,y,z,1.,0.,0.,0.,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId]) SetupGeneral() # might be better to add new atom to Draw Atoms data['Drawing']['Atoms'] = [] # if 'Atoms' in data['Drawing']: # DrawAtomAdd(data['Drawing'],atomData[-1]) if update: UpdateDrawAtoms() G2plt.PlotStructure(G2frame,data) def OnAtomInsert(event): '''Inserts a new atom into list immediately before every selected atom ''' cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) for a in reversed(sorted(indx)): AtomInsert(a,0.,0.,0.) event.StopPropagation() FillAtomsGrid(Atoms) data['Drawing']['Atoms'] = [] UpdateDrawAtoms() G2plt.PlotStructure(G2frame,data) def OnAtomViewInsert(event): if 'Drawing' in data: drawData = data['Drawing'] x,y,z = drawData['viewPoint'][0] AtomAdd(x,y,z) FillAtomsGrid(Atoms) event.StopPropagation() def OnHydAtomAdd(event): '''Adds H atoms to fill out coordination sphere for selected atoms ''' cx,ct,cs,cia = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) if not indx: return DisAglCtls = {} generalData = data['General'] if 'DisAglCtls' in generalData: DisAglCtls = generalData['DisAglCtls'] dlg = G2G.DisAglDialog(G2frame,DisAglCtls,generalData,Reset=False) if dlg.ShowModal() == wx.ID_OK: DisAglCtls = dlg.GetData() if 'H' not in DisAglCtls['AtomTypes']: DisAglCtls['AtomTypes'].append('H') DisAglCtls['AngleRadii'].append(0.5) DisAglCtls['BondRadii'].append(0.5) else: dlg.Destroy() return dlg.Destroy() generalData['DisAglCtls'] = DisAglCtls atomData = data['Atoms'] AtNames = [atom[ct-1] for atom in atomData] AtLookUp = G2mth.FillAtomLookUp(atomData,cia+8) Neigh = [] AddHydIds = [] for ind in indx: atom = atomData[ind] if atom[ct] not in ['C','N','O']: continue neigh = [atom[ct-1],G2mth.FindNeighbors(data,atom[ct-1],AtNames),0] if len(neigh[1][0]) > 3 or (atom[ct] == 'O' and len(neigh[1][0]) > 1): continue nH = 1 #for O atom if atom[ct] in ['C','N']: nH = 4-len(neigh[1][0]) bonds = {item[0]:item[1:] for item in neigh[1][0]} nextName = '' if len(bonds) == 1: nextName = list(bonds.keys())[0] for bond in bonds: if 'C' in atom[ct]: if 'C' in bond and bonds[bond][0] < 1.42: nH -= 1 break elif 'O' in bond and bonds[bond][0] < 1.3: nH -= 1 break elif 'O' in atom[ct] and 'C' in bonds and bonds[bond][0] < 1.3: nH -= 1 break nextneigh = [] if nextName: nextneigh = G2mth.FindNeighbors(data,nextName,AtNames,notName=neigh[0]) if nextneigh[0]: neigh[1][1].append(nextneigh[1][1][0]) neigh[2] = max(0,nH) #set expected no. H's needed if len(neigh[1][0]): AddHydIds.append(neigh[1][1]) Neigh.append(neigh) if Neigh: letters = ['A','B','C'] HydIds = {} mapError = False dlg = AddHatomDialog(G2frame,Neigh,data) if dlg.ShowModal() == wx.ID_OK: Nat = len(atomData) Neigh = dlg.GetData() mapData = generalData['Map'] for ineigh,neigh in enumerate(Neigh): AddHydIds[ineigh].append(neigh[2]) loc = AtLookUp[AddHydIds[ineigh][0]]+1 if 'O' in neigh[0] and (not len(mapData['rho']) or not 'delt-F' in mapData['MapType']): mapError = True continue Hxyz,HU = G2mth.AddHydrogens(AtLookUp,generalData,atomData,AddHydIds[ineigh]) for iX,X in enumerate(Hxyz): AtomInsert(loc+iX,X[0],X[1],X[2],'H','H%s'%(neigh[0][1:]+letters[iX])) data['Atoms'][loc+iX][cia+1] = HU[iX] Id = data['Atoms'][loc+iX][cia+8] HydIds[Id] = [iX,AddHydIds[ineigh]] Nat += 1 AtLookUp = G2mth.FillAtomLookUp(atomData,cia+8) if mapError: G2frame.ErrorDialog('Add H atom error','Adding O-H atoms requires delt-F map') SetupGeneral() data['General']['HydIds'].update(HydIds) G2frame.dataWindow.AtomEdit.Enable(G2G.wxID_UPDATEHATOM,True) data['Drawing']['Atoms'] = [] UpdateDrawAtoms() FillAtomsGrid(Atoms) dlg.Destroy() G2plt.PlotStructure(G2frame,data) else: wx.MessageBox('No candidates found',caption='Add H atom Error',style=wx.ICON_EXCLAMATION) def OnHydAtomUpdate(event): generalData = data['General'] cx,ct,cs,cia = generalData['AtomPtrs'] atomData = data['Atoms'] AtLookUp = G2mth.FillAtomLookUp(atomData,cia+8) HydIds = data['General']['HydIds'] delList = [] for HId in HydIds: hydIds = HydIds[HId] num = hydIds[0] Hxyz,HU = G2mth.AddHydrogens(AtLookUp,generalData,atomData,hydIds[1]) try: if data['Atoms'][AtLookUp[HId]][ct] != 'H': raise KeyError data['Atoms'][AtLookUp[HId]][cx:cx+3] = Hxyz[num] data['Atoms'][AtLookUp[HId]][cia+1] = HU[num] except KeyError: delList.append(HId) continue for HId in delList: #clear out deleted H-atom pointers del HydIds[HId] if not len(HydIds): G2frame.dataWindow.AtomEdit.Enable(G2G.wxID_UPDATEHATOM,False) data['Drawing']['Atoms'] = [] UpdateDrawAtoms() FillAtomsGrid(Atoms) G2plt.PlotStructure(G2frame,data) def OnAtomMove(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) drawData = data['Drawing'] atomData = data['Atoms'] x,y,z = drawData['viewPoint'][0] colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())] cx = colLabels.index('x') ci = colLabels.index('I/A') if len(indx) != 1: G2frame.ErrorDialog('Atom move error','Only one atom can be moved') elif atomData[indx[0]][ci+8] in rbAtmDict: G2frame.ErrorDialog('Atom move error','Atoms in rigid bodies can not be moved') else: atomData[indx[0]][cx:cx+3] = [x,y,z] SetupGeneral() FillAtomsGrid(Atoms) ID = atomData[indx[0]][ci+8] G2mth.DrawAtomsReplaceByID(data,ci+8,atomData[indx[0]],ID) G2plt.PlotStructure(G2frame,data) event.StopPropagation() def AtomInsert(indx,x,y,z,El='H',Name='UNK'): atomData = data['Atoms'] generalData = data['General'] SGData = generalData['SGData'] Sytsym,Mult = G2spc.SytSym([x,y,z],SGData)[:2] atId = ran.randint(0,sys.maxsize) if generalData['Type'] == 'macromolecular': atomData.insert(indx,[0,Name,'',Name,El,'',x,y,z,1.,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId]) elif generalData['Type'] in ['nuclear','faulted',]: if generalData['Modulated']: atomData.insert(indx,[Name,El,'',x,y,z,1,Sytsym,Mult,0.,'I',0.01,0,0,0,0,0,0,atId,[],[], {'SS1':{'waveType':'Fourier','Sfrac':[],'Spos':[],'Sadp':[],'Smag':[]}}]) else: atomData.insert(indx,[Name,El,'',x,y,z,1.,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId]) SetupGeneral() elif generalData['Type'] == 'magnetic': if generalData['Modulated']: atomData.insert(indx,[Name,El,'',x,y,z,1.,0.,0.,0.,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,atId,[],[], {'SS1':{'waveType':'Fourier','Sfrac':[],'Spos':[],'Sadp':[],'Smag':[]}}]) else: atomData.insert(indx,[Name,El,'',x,y,z,1.,0.,0.,0.,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId]) data['Drawing']['Atoms'] = [] UpdateDrawAtoms() G2plt.PlotStructure(G2frame,data) def AtomDelete(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms) colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())] delList = '' for i in indx: if delList: delList += ', ' delList += data['Atoms'][i][0] dlg = wx.MessageDialog(G2frame, 'Do you want to delete atom(s): {}?'.format(delList), 'Confirm delete', wx.YES|wx.NO) try: dlg.CenterOnParent() result = dlg.ShowModal() finally: dlg.Destroy() if result != wx.ID_YES: return HydIds = data['General']['HydIds'] ci = colLabels.index('I/A') IDs = [] if not indx: return atomData = data['Atoms'] indx.sort() indx.reverse() msg = '' for ind in indx: atom = atomData[ind] if atom[ci+8] in rbAtmDict: if msg: msg += ', ' msg += atom[0] else: if atom[ci+8] in HydIds: #remove Hs from Hatom update dict del HydIds[atom[ci+8]] IDs.append(atom[ci+8]) del atomData[ind] if msg: G2frame.ErrorDialog('Atom delete error', 'ERROR - atom(s) in a rigid body were not deleted: '+msg) if 'Atoms' in data['Drawing']: Atoms.ClearSelection() DrawAtomsDeleteByIDs(IDs) data['Drawing']['Atoms'] = [] UpdateDrawAtoms() wx.CallAfter(FillAtomsGrid,Atoms) G2plt.PlotStructure(G2frame,data) SetupGeneral() if not len(HydIds): G2frame.dataWindow.AtomEdit.Enable(G2G.wxID_UPDATEHATOM,False) event.StopPropagation() def AtomRefine(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) if not indx: return colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())] c = colLabels.index('refine') atomData = data['Atoms'] generalData = data['General'] Type = generalData['Type'] if Type in ['nuclear','macromolecular','faulted',]: choice = ['F - site fraction','X - coordinates','U - thermal parameters'] elif Type in ['magnetic',]: choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment'] dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelections() parms = '' for x in sel: parms += choice[x][0] for r in indx: if not Atoms.IsReadOnly(r,c): atomData[r][c] = parms Atoms.ForceRefresh() dlg.Destroy() def AtomModify(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) if not indx: return atomData = data['Atoms'] generalData = data['General'] ifMag = False colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())] ci = colLabels.index('I/A') choices = ['Type','Name','x','y','z','frac','I/A','Uiso','Uij'] if generalData['Type'] == 'magnetic': choices += ['Mx','My','Mz',] ifMag = True dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom parameter',choices) parm = '' if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parm = choices[sel] cid = -1 if parm != 'Uij': cid = colLabels.index(parm) dlg.Destroy() if parm in ['Type']: dlg = G2elemGUI.PickElement(G2frame,ifMag=ifMag) if dlg.ShowModal() == wx.ID_OK: if dlg.Elem not in ['None']: El = dlg.Elem.strip() for r in indx: if not Atoms.IsReadOnly(r,0): #not if in RB! atomData[r][cid] = El if len(El) in [2,4]: atomData[r][cid-1] = El[:2]+'%d'%(r+1) else: atomData[r][cid-1] = El[:1]+'%d'%(r+1) SetupGeneral() if 'Atoms' in data['Drawing']: for r in indx: ID = atomData[r][ci+8] G2mth.DrawAtomsReplaceByID(data,ci+8,atomData[r],ID) FillAtomsGrid(Atoms) dlg.Destroy() elif parm in ['Name',]: dlg = wx.MessageDialog(G2frame,'Do you really want to rename the selected atoms?','Rename', wx.YES_NO | wx.ICON_QUESTION) try: result = dlg.ShowModal() if result == wx.ID_YES: for r in indx: if not Atoms.IsReadOnly(r,0): #not if in RB! El = atomData[r][cid+1] if len(El) in [2,4]: atomData[r][cid] = El[:2]+'%d'%(r+1) else: atomData[r][cid] = El[:1]+'%d'%(r+1) FillAtomsGrid(Atoms) finally: dlg.Destroy() elif parm in ['I/A']: choices = ['Isotropic','Anisotropic'] dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal parameter model',choices) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() parm = choices[sel][0] for r in indx: if Atoms.IsReadOnly(r,0): #not if in RB! continue atomData[r][cid] = parm if parm == 'A' and not any(atomData[r][cid+2:cid+8]): sytsym = atomData[r][cs] CSI = G2spc.GetCSuinel(sytsym) atomData[r][ci+2:ci+8] = atomData[r][ci+1]*np.array(CSI[3]) FillAtomsGrid(Atoms) dlg.Destroy() elif parm in ['frac','Uiso']: limits = [-1.,1.] val = 1.0 if parm in ['Uiso']: limits = [-0.25,0.25] val = 0.01 dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter new value for '+parm,val,limits) if dlg.ShowModal() == wx.ID_OK: parm = dlg.GetValue() for r in indx: if not Atoms.IsReadOnly(r,0): #not if in RB! atomData[r][cid] = parm SetupGeneral() FillAtomsGrid(Atoms) dlg.Destroy() elif parm == 'Uij': limits = [0.,0.25] val = 0.01 dlg = G2G.SingleFloatDialog(G2frame,'Convert Uiso to Uij','Enter default for Uiso'+parm,val,limits) if dlg.ShowModal() == wx.ID_OK: parm = dlg.GetValue() for r in indx: if not Atoms.IsReadOnly(r,0): #not if in RB! atomData[r][ci] = 'A' sytsym = atomData[r][cs] CSI = G2spc.GetCSuinel(sytsym) if atomData[r][ci+1] > 0.: atomData[r][ci+2:ci+8] = atomData[r][ci+1]*np.array(CSI[3]) else: atomData[r][ci+2:ci+8] = parm*np.array(CSI[3]) SetupGeneral() FillAtomsGrid(Atoms) dlg.Destroy() elif parm in ['x','y','z']: limits = [-1.,1.] val = 0. dlg = G2G.SingleFloatDialog(G2frame,'Atom shift','Enter shift for '+parm,val,limits) if dlg.ShowModal() == wx.ID_OK: parm = dlg.GetValue() for r in indx: if not Atoms.IsReadOnly(r,0): #not if in RB! atomData[r][cid] += parm SetupGeneral() FillAtomsGrid(Atoms) dlg.Destroy() elif parm in ['Mx','My','Mz',]: limits = [-10.,10.] val = 0. dlg = G2G.SingleFloatDialog(G2frame,'Atom moment','Enter new value for '+parm,val,limits) if dlg.ShowModal() == wx.ID_OK: parm = dlg.GetValue() for r in indx: if not Atoms.IsReadOnly(r,0): #not if in RB! atomData[r][cid] = parm SetupGeneral() FillAtomsGrid(Atoms) dlg.Destroy() data['Drawing']['Atoms'] = [] UpdateDrawAtoms() G2plt.PlotStructure(G2frame,data) def AtomTransform(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) if not indx: return generalData = data['General'] SpnFlp = generalData['SGData'].get('SpnFlp',[]) colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())] cx = colLabels.index('x') cuia = colLabels.index('I/A') cuij = colLabels.index('U11') css = colLabels.index('site sym') cmx = 0 if 'Mx' in colLabels: cmx = colLabels.index('Mx') atomData = data['Atoms'] SGData = generalData['SGData'] dlg = SymOpDialog(G2frame,SGData,True,True) New = False try: if dlg.ShowModal() == wx.ID_OK: Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection() Cell = np.array(Cell) cent = SGData['SGCen'][Cent] M,T = SGData['SGOps'][Opr] for ind in indx: XYZ = np.array(atomData[ind][cx:cx+3]) XYZ = np.inner(M,XYZ)+T if Inv and not SGData['SGFixed']: XYZ = -XYZ XYZ = XYZ+cent+Cell if Force: XYZ,cell = G2spc.MoveToUnitCell(XYZ) Cell += cell if New: atom = copy.copy(atomData[ind]) else: atom = atomData[ind] atom[cx:cx+3] = XYZ atom[css:css+2] = G2spc.SytSym(XYZ,SGData)[:2] OprNum = ((Opr+1)+100*Cent)*(1-2*Inv) if atom[cuia] == 'A': Uij = atom[cuij:cuij+6] U = G2spc.Uij2U(Uij) U = np.inner(np.inner(M,U),M) Uij = G2spc.U2Uij(U) atom[cuij:cuij+6] = Uij if cmx: opNum = G2spc.GetOpNum(OprNum,SGData) mom = np.array(atom[cmx:cmx+3]) atom[cmx:cmx+3] = np.inner(mom,M)*nl.det(M)*SpnFlp[opNum-1] if New: atomData.append(atom) finally: dlg.Destroy() Atoms.ClearSelection() if New: FillAtomsGrid(Atoms) else: Atoms.ForceRefresh() data['Drawing']['Atoms'] = [] UpdateDrawAtoms() G2plt.PlotStructure(G2frame,data) # def AtomRotate(event): # '''Currently not used - Bind commented out below # ''' # Units = {'':np.zeros(3), # 'xy':np.array([[i,j,0] for i in range(3) for j in range(3)])-np.array([1,1,0]), # 'xz':np.array([[i,0,j] for i in range(3) for j in range(3)])-np.array([1,1,0]), # 'yz':np.array([[0,i,j] for i in range(3) for j in range(3)])-np.array([1,1,0]), # 'xyz':np.array([[i,j,k] for i in range(3) for j in range(3) for k in range(3)])-np.array([1,1,1])} # cx,ct,cs,ci = G2mth.getAtomPtrs(data) # indx = getAtomSelections(Atoms,ct-1) # if indx: # generalData = data['General'] # A,B = G2lat.cell2AB(generalData['Cell'][1:7]) # colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())] # cx = colLabels.index('x') # cuia = colLabels.index('I/A') #need to not do aniso atoms - stop with error? or force isotropic? # css = colLabels.index('site sym') # atomData = data['Atoms'] # SGData = generalData['SGData'] # dlg = G2gd.RotationDialog(G2frame) # try: # if dlg.ShowModal() == wx.ID_OK: # M,T,Expand = dlg.GetSelection() # Unit = Units[Expand] # for ind in indx: # XYZ = np.array(atomData[ind][cx:cx+3]) # XYZS = XYZ+Unit # XYZS -= T # XYZS = np.inner(A,XYZS).T #to Cartesian # XYZS = np.inner(M,XYZS).T #rotate # XYZS = np.inner(B,XYZS).T+T #back to crystal & translate # GSASIIpath.IPyBreak() # atomData[ind][cx:cx+3] = XYZ # for unit in Unit: # XYZ = np.copy(np.array(atomData[ind][cx:cx+3])) # XYZ += unit # XYZ -= T # XYZ = np.inner(A,XYZ) #to Cartesian # XYZ = np.inner(M,XYZ) #rotate # XYZ = np.inner(B,XYZ)+T #back to crystal & translate # if np.all(XYZ>=0.) and np.all(XYZ<1.0): # atomData[ind][cx:cx+3] = XYZ ## atom[css:css+2] = G2spc.SytSym(XYZ,SGData)[:2] # break # finally: # dlg.Destroy() # Atoms.ClearSelection() # Atoms.ForceRefresh() # else: # print "select one or more rows of atoms" # G2frame.ErrorDialog('Select atom',"select one or more atoms then redo") def CollectAtoms(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) Ind = getAtomSelections(Atoms,ct-1) if Ind: choice = ['x=0','y=0','z=0','origin','center'] dlg = wx.SingleChoiceDialog(G2frame,'Atoms closest to:','Select',choice) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection()+1 dlg.Destroy() else: dlg.Destroy() return wx.BeginBusyCursor() data['Atoms'] = G2mth.AtomsCollect(data,Ind,sel) wx.EndBusyCursor() Atoms.ClearSelection() data['Drawing']['Atoms'] = [] OnReloadDrawAtoms(event) FillAtomsGrid(Atoms) def MakeMolecule(event): cx,ct,cs,ci = G2mth.getAtomPtrs(data) indx = getAtomSelections(Atoms,ct-1) DisAglCtls = {} if indx is not None and len(indx) == 1: generalData = data['General'] if 'DisAglCtls' in generalData: DisAglCtls = generalData['DisAglCtls'] dlg = G2G.DisAglDialog(G2frame,DisAglCtls,generalData) if dlg.ShowModal() == wx.ID_OK: DisAglCtls = dlg.GetData() else: dlg.Destroy() return dlg.Destroy() generalData['DisAglCtls'] = DisAglCtls atomData = copy.deepcopy(data['Atoms']) result = G2mth.FindMolecule(indx[0],generalData,atomData) if 'str' in str(type(result)): G2frame.ErrorDialog('Assemble molecule',