Source code for GSASII.GSASIIrmcGUI

# -*- coding: utf-8 -*-
#GSASII - phase data display routines
'''

Routines for Phase/RMC follow. Only the UpdateRMC routine is here. 
All others are in GSASIIphsGUI.py
'''
import os
import wx
import wx.grid as wg
import copy
import time
import shutil

import numpy as np
from . import GSASIIlattice as G2lat
from . import GSASIIspc as G2spc
from . import GSASIIElem as G2elem
from . import GSASIIplot as G2plt
from . import GSASIIdataGUI as G2gd
from . import GSASIImath as G2mth
from . import GSASIIpwd as G2pwd
from . import GSASIIctrlGUI as G2G
from . import GSASIIphsGUI as G2phsG
from . import atmdata

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

try:
    VERY_LIGHT_GREY = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
    WHITE = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
    BLACK = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT)
    RED = wx.Colour(255,0,0)
    WACV = wx.ALIGN_CENTER_VERTICAL
except:
    pass
mapDefault = G2elem.mapDefault
TabSelectionIdDict = {}
# trig functions in degrees
sind = lambda x: np.sin(x*np.pi/180.)
tand = lambda x: np.tan(x*np.pi/180.)
cosd = lambda x: np.cos(x*np.pi/180.)
asind = lambda x: 180.*np.arcsin(x)/np.pi
acosd = lambda x: 180.*np.arccos(x)/np.pi
atan2d = lambda x,y: 180.*np.arctan2(y,x)/np.pi
is_exe = lambda fpath: os.path.isfile(fpath) and os.access(fpath, os.X_OK)
sqt2 = np.sqrt(2.)
sqt3 = np.sqrt(3.)

# previous rigid body selections
prevResId = None
prevVecId = None
prevSpnId = None

GkDelta = chr(0x0394)
Angstr = chr(0x00c5)

RMCmisc = {}
ranDrwDict = {}
ranDrwDict['atomList'] = []
DrawStyleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
#### UpdateRMC GUI ################################################################################
# # fullrmc stuff TODO:
# #  1) need to implement swapping in scripts
# #  2) fullrmc tutorials

[docs] def UpdateRMC(G2frame,data): ''' Present the controls for running fullrmc, RMCProfile or PDFfit ''' global runFile def OnRMCselect(event): G2frame.RMCchoice = RMCsel.GetStringSelection() wx.CallLater(200,UpdateRMC,G2frame,data) def GetAtmChoice(pnl,RMCPdict): Indx = {} def OnAtSel(event): Obj = event.GetEventObject() itype = Indx[Obj.GetId()] tid = RMCPdict['atSeq'].index(Obj.GetStringSelection()) if itype < nTypes: if itype == tid: tid += 1 RMCPdict['atSeq'] = G2lat.SwapItems(RMCPdict['atSeq'],itype,tid) Pairs= [] atSeq = RMCPdict['atSeq'] lenA = len(atSeq) for pair in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA)] for i in range(lenA)]: # for pair in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA) if 'Va' not in atSeq[j]] for i in range(lenA) if 'Va' not in atSeq[i]]: Pairs += pair RMCPdict['Pairs'] = {pairs:[0.0,0.0,0.0] for pairs in Pairs} if RMCPdict['useBVS']: BVSpairs = [] for pair in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i+1,lenA)] for i in range(lenA)]: BVSpairs += pair RMCPdict['BVS'] = {pairs:[0.0,0.0,0.0,0.0] for pairs in BVSpairs} wx.CallAfter(UpdateRMC,G2frame,data) def OnValSel(event): Obj = event.GetEventObject() itype = Indx[Obj.GetId()] RMCPdict['Oxid'][itype][0] = Obj.GetStringSelection() wx.CallAfter(UpdateRMC,G2frame,data) nTypes = len(RMCPdict['aTypes']) atmChoice = wx.FlexGridSizer(nTypes+1,5,5) atmChoice.Add(wx.StaticText(pnl,label='atom ordering: '),0,WACV) for iType in range(nTypes): atChoice = RMCPdict['atSeq'][iType:] atmSel = wx.ComboBox(pnl,choices=atChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) atmSel.SetStringSelection(RMCPdict['atSeq'][iType]) atmSel.Bind(wx.EVT_COMBOBOX,OnAtSel) Indx[atmSel.GetId()] = iType atmChoice.Add(atmSel,0,WACV) if RMCPdict['useBVS']: atmChoice.Add(wx.StaticText(pnl,label='Valence: '),0,WACV) for itype in range(nTypes): valChoice = atmdata.BVSoxid[RMCPdict['atSeq'][itype]] valSel = wx.ComboBox(pnl,choices=valChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) try: valSel.SetStringSelection(RMCPdict['Oxid'][itype][0]) except IndexError: RMCPdict['Oxid'].append([RMCPdict['atSeq'][itype],0.0]) valSel.Bind(wx.EVT_COMBOBOX,OnValSel) Indx[valSel.GetId()] = itype atmChoice.Add(valSel,0,WACV) atmChoice.Add(wx.StaticText(pnl,label='BVS weight: '),0,WACV) for itype in range(nTypes): atmChoice.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['Oxid'][itype],1,xmin=0.),0,WACV) if G2frame.RMCchoice == 'RMCProfile': atmChoice.Add(wx.StaticText(pnl,label='max shift: '),0,WACV) for iType in range(nTypes): atId = RMCPdict['atSeq'][iType] atmChoice.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['aTypes'],atId,xmin=0.,xmax=1.),0,WACV) atmChoice.Add(wx.StaticText(pnl,label='Isotope: '),0,WACV) for iType in range(nTypes): atId = RMCPdict['atSeq'][iType] try: lbl = RMCPdict['Isotope'][atId] except: lbl = '?' atmChoice.Add(wx.StaticText(pnl,label=lbl),0,WACV) return atmChoice def GetSwapSizer(RMCPdict): def OnDelSwap(event): Obj = event.GetEventObject() swap = Indx[Obj.GetId()] del RMCPdict['Swaps'][swap] wx.CallAfter(UpdateRMC,G2frame,data) Indx = {} atChoice = RMCPdict['atSeq'] # if G2frame.RMCchoice == 'fullrmc': # atChoice = atNames swapSizer = wx.FlexGridSizer(6,5,5) swapLabels = [' ','Atom-A','Atom-B',' Swap prob.',' ','delete'] for lab in swapLabels: swapSizer.Add(wx.StaticText(G2frame.FRMC,label=lab),0,WACV) for ifx,swap in enumerate(RMCPdict['Swaps']): swapSizer.Add((20,-1)) for i in [0,1]: if swap[i] not in atChoice: swap[i] = atChoice[0] atmSel = G2G.EnumSelector(G2frame.FRMC,swap,i,atChoice) swapSizer.Add(atmSel,0,WACV) swapSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,swap,2,xmin=0.01,xmax=0.5,size=(50,25)),0,WACV) swapSizer.Add((20,-1)) delBtn = wx.Button(G2frame.FRMC,label='Del',style=wx.BU_EXACTFIT) delBtn.Bind(wx.EVT_BUTTON,OnDelSwap) Indx[delBtn.GetId()] = ifx swapSizer.Add(delBtn,0,WACV) return swapSizer def GetPairSizer(pnl,RMCPdict): pairSizer = wx.FlexGridSizer(len(RMCPdict['Pairs'])+1,5,5) pairSizer.Add((5,5),0) for pair in RMCPdict['Pairs']: pairSizer.Add(wx.StaticText(pnl,label=pair),0,WACV) if G2frame.RMCchoice == 'RMCProfile': pairSizer.Add(wx.StaticText(pnl,label='%14s'%' Hard min: '),0,WACV) for pair in RMCPdict['Pairs']: pairSizer.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['Pairs'][pair],0,xmin=0.,xmax=10.,size=(50,25)),0,WACV) pairSizer.Add(wx.StaticText(pnl,label='%14s'%' Search from: '),0,WACV) elif G2frame.RMCchoice == 'fullrmc': pairSizer.Add(wx.StaticText(pnl,label='%14s'%' Distance min: '),0,WACV) for pair in RMCPdict['Pairs']: pairSizer.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['Pairs'][pair], 1,xmin=0.,xmax=10.,size=(50,25)),0,WACV) pairSizer.Add(wx.StaticText(pnl,label='%14s'%'to: '),0,WACV) for pair in RMCPdict['Pairs']: pairSizer.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['Pairs'][pair],2,xmin=0.,xmax=10.,size=(50,25)),0,WACV) return pairSizer def GetMetaSizer(RMCPdict,metalist): metaSizer = wx.FlexGridSizer(0,2,5,5) for item in metalist: metaSizer.Add(wx.StaticText(G2frame.FRMC,label=' Metadata item: '+item+' '),0,WACV) metaSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['metadata'],item),0,WACV) return metaSizer def SetRestart(invalid,value,tc): RMCPdict['ReStart'] = [True,True] def GetSuperSizer(RMCPdict,Xmax): superSizer = wx.BoxSizer(wx.HORIZONTAL) axes = ['X','Y','Z'] for i,ax in enumerate(axes): superSizer.Add(wx.StaticText(G2frame.FRMC,label=' %s-axis: '%ax),0,WACV) superSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['SuperCell'], i,xmin=1,xmax=Xmax,size=(50,25),OnLeave=SetRestart),0,WACV) return superSizer def FileSizer(RMCPdict): def OnFileSel(event): Obj = event.GetEventObject() fil = Indx[Obj.GetId()] G2frame.OnFileSave(event) dlg = wx.FileDialog(G2frame.FRMC, 'Choose '+fil,G2G.GetImportPath(G2frame), style=wx.FD_OPEN ,wildcard=fil+'(*.*)|*.*') if dlg.ShowModal() == wx.ID_OK: fpath,fName = os.path.split(dlg.GetPath()) if os.path.exists(os.path.join(G2frame.LastGPXdir,fName)): # is there a file by this name in the current directory? RMCPdict['files'][fil][0] = fName else: # nope, copy it # TODO: is G2frame.LastGPXdir the right choice here or # do I want the current working directory (same?) shutil.copy(dlg.GetPath(), os.path.join(G2frame.LastGPXdir,fName)) RMCPdict['files'][fil][0] = fName if not os.path.exists(os.path.join(G2frame.LastGPXdir,fName)): # sanity check print(f'Error: file {fName} not found in .gpx directory ({G2frame.LastGPXdir})') return G2frame.LastImportDir = fpath #set so next file is found in same place dlg.Destroy() RMCPdict['ReStart'][0] = True if G2frame.RMCchoice == 'PDFfit': start = 0 XY = np.empty((1,2)) while XY.shape[0] == 1: try: XY = np.loadtxt(fName,skiprows=start) except ValueError: start += 1 name = 'Ndata' if 'X' in fil: name = 'Xdata' RMCPdict[name]['Datarange'][0] = np.min(XY.T[0]) RMCPdict[name]['Datarange'][1] = np.max(XY.T[0]) RMCPdict[name]['Fitrange'][1] = np.max(XY.T[0]) else: dlg.Destroy() wx.CallAfter(UpdateRMC,G2frame,data) def OnFileFormat(event): Obj = event.GetEventObject() fil = Indx[Obj.GetId()] Fmt = Obj.GetStringSelection() RMCPdict['files'][fil][3] = Fmt if "G(r)" in fil: if 'PDF' in Fmt: RMCPdict['files'][fil][2] = 'G(r)P' else: RMCPdict['files'][fil][2] = 'G(r)' elif "F(Q)" in fil: if "NEUTRON" in fil.upper(): if 'PDF' in Fmt: RMCPdict['files'][fil][2] = 'QF(Q) normalized' else: RMCPdict['files'][fil][2] = 'F(Q)' else: RMCPdict['files'][fil][2] = 'F(Q)' else: RMCPdict['files'][fil][2] = 'S(Q)' def OnPlotBtn(event): Obj = event.GetEventObject() fil = Indx[Obj.GetId()] fileItem = RMCPdict['files'][fil] start = 0 XY = np.empty((1,2)) while XY.shape[0] == 1: try: XY = np.loadtxt(os.path.join(G2frame.LastGPXdir,fileItem[0]),skiprows=start) except ValueError: start += 1 if start > 500: #absurd number of header lines! wx.MessageBox('WARNING: %s has bad data at end;\n RMCProfile may fail to read it'%fileItem[0], style=wx.ICON_ERROR) break Xlab = 'Q' if 'G(R)' in fileItem[2].upper(): Xlab = 'R' G2plt.PlotXY(G2frame,[XY.T[:2],],labelX=Xlab, labelY=fileItem[2],newPlot=True,Title=fileItem[0], lines=True) def OnCorrChk(event): Obj = event.GetEventObject() fil = Indx[Obj.GetId()] RMCPdict['files'][fil][3] = not RMCPdict['files'][fil][3] def OnDelBtn(event): Obj = event.GetEventObject() fil = Indx[Obj.GetId()] RMCPdict['files'][fil][0] = 'Select' RMCPdict['ReStart'][0] = True wx.CallAfter(UpdateRMC,G2frame,data) def OnRef(event): Obj = event.GetEventObject() name,item = Indx[Obj.GetId()] RMCPdict[name][item][1] = not RMCPdict[name][item][1] def OnRefSel(event): RMCPdict['refinement'] = reftype.GetStringSelection() wx.CallLater(100,UpdateRMC,G2frame,data) def OnDataSel(event): RMCPdict['SeqDataType'] = dataType.GetStringSelection() def OnSeqCopy(event): RMCPdict['SeqCopy'] = not RMCPdict['SeqCopy'] def OnSeqReverse(event): RMCPdict['SeqReverse'] = not RMCPdict['SeqReverse'] # --- FileSizer starts here Indx = {} mainSizer = wx.BoxSizer(wx.VERTICAL) if G2frame.RMCchoice == 'PDFfit': topSizer = wx.BoxSizer(wx.HORIZONTAL) reftype = wx.RadioBox(G2frame.FRMC,label='PDFfit refinement type:',choices=['normal','sequential']) reftype.SetStringSelection(RMCPdict.get('refinement','normal')) reftype.Bind(wx.EVT_RADIOBOX,OnRefSel) topSizer.Add(reftype) if 'seq' in RMCPdict.get('refinement','normal'): dataType = wx.RadioBox(G2frame.FRMC,label='Seq data type:',choices=['X','N']) dataType.SetStringSelection(RMCPdict.get('SeqDataType','X')) dataType.Bind(wx.EVT_RADIOBOX,OnDataSel) topSizer.Add(dataType) endSizer = wx.BoxSizer(wx.VERTICAL) seqcopy = wx.CheckBox(G2frame.FRMC,label=' Copy to next') seqcopy.SetValue(RMCPdict['SeqCopy']) seqcopy.Bind(wx.EVT_CHECKBOX,OnSeqCopy) endSizer.Add(seqcopy) seqreverse = wx.CheckBox(G2frame.FRMC,label=' Reverse processing') seqreverse.SetValue(RMCPdict['SeqReverse']) seqreverse.Bind(wx.EVT_CHECKBOX,OnSeqReverse) endSizer.Add(seqreverse) topSizer.Add(endSizer,0,WACV) mainSizer.Add(topSizer) elif G2frame.RMCchoice == 'fullrmc': topSizer = wx.BoxSizer(wx.HORIZONTAL) topSizer.Add(wx.StaticText(G2frame.FRMC,label=' Select data for processing (files must be 2 columns w/headers preceeded by "#"; edit if needed)')) mainSizer.Add(topSizer) Heads = ['Name','File','type','Plot','Delete'] fileSizer = wx.FlexGridSizer(5,5,5) Formats = ['RMC','GUDRUN','PDFGET'] for head in Heads: fileSizer.Add(wx.StaticText(G2frame.FRMC,label=head),0,WACV) for fil in RMCPdict['files']: fileSizer.Add(wx.StaticText(G2frame.FRMC,label=fil),0,WACV) Rfile = RMCPdict['files'][fil][0] filSel = wx.Button(G2frame.FRMC,label=Rfile) filSel.Bind(wx.EVT_BUTTON,OnFileSel) Indx[filSel.GetId()] = fil fileSizer.Add(filSel,0,WACV) if Rfile and os.path.exists(Rfile): # in case .gpx file is moved away from G(R), F(Q), etc. files #fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['files'][fil],1,size=(50,25)),0,WACV) #patch if len(RMCPdict['files'][fil]) < 4: RMCPdict['files'][fil].append(0) if len(RMCPdict['files'][fil]) < 5: RMCPdict['files'][fil].append(True) #end patch if 'G(r)' in fil: choices = 'G(r)-RMCProfile','G(r)-PDFFIT','g(r)' if type(RMCPdict['files'][fil][3]) is bool: RMCPdict['files'][fil][3] = 0 fmtTyp = G2G.G2ChoiceButton(G2frame.FRMC,choices,RMCPdict['files'][fil],3) elif '(Q)' in fil: choices = 'F(Q)-RMCProfile','S(Q)-PDFFIT' if type(RMCPdict['files'][fil][3]) is bool: RMCPdict['files'][fil][3] = 0 fmtTyp = G2G.G2ChoiceButton(G2frame.FRMC,choices,RMCPdict['files'][fil],3) else: fmtTyp = (-1,-1) fileSizer.Add(fmtTyp,0,WACV) plotBtn = wx.Button(G2frame.FRMC,label='Plot',style=wx.BU_EXACTFIT) plotBtn.Bind(wx.EVT_BUTTON,OnPlotBtn) Indx[plotBtn.GetId()] = fil fileSizer.Add(plotBtn,0,WACV) delBtn = wx.Button(G2frame.FRMC,label='Del',style=wx.BU_EXACTFIT) delBtn.Bind(wx.EVT_BUTTON,OnDelBtn) Indx[delBtn.GetId()] = fil fileSizer.Add(delBtn,0,WACV) if '(Q)' in fil: fileSizer.Add((-1,-1),0) corrChk = wx.CheckBox(G2frame.FRMC,label='Apply sinc convolution? ') corrChk.SetValue(RMCPdict['files'][fil][4]) Indx[corrChk.GetId()] = fil corrChk.Bind(wx.EVT_CHECKBOX,OnCorrChk) fileSizer.Add(corrChk,0,WACV) #fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) elif 'Select' not in Rfile: # file specified, but must not exist RMCPdict['files'][fil][0] = 'Select' # set filSel? fileSizer.Add(wx.StaticText(G2frame.FRMC, label='Warning: file not found.\nWill be removed'),0) fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) else: RMCPdict['files'][fil][0] = 'Select' # set filSel? #fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) fileSizer.Add((-1,-1),0) mainSizer.Add(fileSizer,0) return mainSizer if G2frame.RMCchoice == 'PDFfit' and RMCPdict['refinement'] == 'sequential': def OnAddPDF(event): ''' Add PDF G(r)s while maintaining original sequence ''' usedList = RMCPdict['seqfiles'] PDFlist = [item[1:][0] for item in G2frame.GetFileList('PDF')] PDFdict = dict([item[1:] for item in G2frame.GetFileList('PDF')]) PDFnames = [item for item in PDFdict if item not in [itm[0] for itm in usedList]] dlg = G2G.G2MultiChoiceDialog(G2frame.FRMC,'Add PDF dataset', 'Select G(r) data to use in seq. PDFfit',PDFnames) if dlg.ShowModal() == wx.ID_OK: PDFuse = dlg.GetSelections() for item in PDFuse: pId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,PDFnames[item]) data = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,pId,'PDF Controls')) try: insrt = PDFlist.index(PDFnames[item])-1 RMCPdict['seqfiles'].insert(insrt+1,[PDFnames[item],data]) except ValueError: RMCPdict['seqfiles'].append([PDFnames[item],data]) dlg.Destroy() wx.CallAfter(UpdateRMC,G2frame,data) def OnDelPDF(event): usedList = [item[0] for item in RMCPdict['seqfiles']] dlg = G2G.G2MultiChoiceDialog(G2frame.FRMC,'Delete PDF dataset', 'Select G(r) data to delete frpm seq. PDFfit',usedList) if dlg.ShowModal() == wx.ID_OK: PDFdel = dlg.GetSelections() PDFdel.reverse() for item in PDFdel: del RMCPdict['seqfiles'][item] dlg.Destroy() wx.CallAfter(UpdateRMC,G2frame,data) def OnSetColVal(event): parms = {'Rmin':[0.01,5.0],'Rmax':[5.,30.],'dscale':[0.5,2.0], 'qdamp':[0.0,0.5],'qbroad':[0.0,0.1],'Temp':300} c = event.GetCol() if c >= 0: if c in [3,5,7]: seqGrid.ClearSelection() seqGrid.SelectCol(c,True) if seqGrid.GetColLabelValue(c) != 'refine': return choice = ['Y - vary all','N - vary none',] dlg = wx.SingleChoiceDialog(G2frame,'Select refinement option for '+seqGrid.GetColLabelValue(c-1), 'Refinement controls',choice) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() varib = colLabels[c-1] if sel == 0: for row in range(seqGrid.GetNumberRows()): RMCPdict['seqfiles'][row][1][varib][1]=True else: for row in range(seqGrid.GetNumberRows()): RMCPdict['seqfiles'][row][1][varib][1]=False elif c in [0,1,2,4,6,8]: seqGrid.ClearSelection() seqGrid.SelectCol(c,True) parm = colLabels[c] dlg = G2G.SingleFloatDialog(G2frame,'New value','Enter value for '+parm,0.0,parms[parm]) if dlg.ShowModal() == wx.ID_OK: value = dlg.GetValue() if c in [2,4,6]: for row in range(seqGrid.GetNumberRows()): RMCPdict['seqfiles'][row][1][parm][0] = value elif c == 8: for row in range(seqGrid.GetNumberRows()): RMCPdict['seqfiles'][row][1][parm] = value else: for row in range(seqGrid.GetNumberRows()): RMCPdict['seqfiles'][row][1]['Fitrange'][c] = value wx.CallAfter(UpdateRMC,G2frame,data) def OnSetVal(event): r,c= event.GetRow(),event.GetCol() if c >= 0: if c in [3,5,7]: varib = colLabels[c-1] RMCPdict['seqfiles'][r][1][varib][1] = bool(seqGrid.GetCellValue(r,c)) elif c in [0,1,2,4,6,8]: parm = colLabels[c] if c in [2,4,6]: RMCPdict['seqfiles'][r][1][parm][0] = float(seqGrid.GetCellValue(r,c)) elif c == 8: RMCPdict['seqfiles'][r][1][parm] = float(seqGrid.GetCellValue(r,c)) else: RMCPdict['seqfiles'][r][1]['Fitrange'][c] = float(seqGrid.GetCellValue(r,c)) topSizer = wx.BoxSizer(wx.HORIZONTAL) topSizer.Add(wx.StaticText(G2frame.FRMC,label=' Select data for processing: ')) mainSizer.Add(topSizer) G2frame.GetStatusBar().SetStatusText('NB: All PDFs used in sequential PDFfit must be the same type ("X" or "N") - there is no check',1) if 'seqfiles' not in RMCPdict: RMCPdict['seqfiles'] = [] topSizer = wx.BoxSizer(wx.HORIZONTAL) topSizer.Add(wx.StaticText(G2frame.FRMC,label=' Sequential data list for PDFfit: '),0,WACV) addPDF = wx.Button(G2frame.FRMC,label='Add PDF G(r) data sets') addPDF.Bind(wx.EVT_BUTTON,OnAddPDF) topSizer.Add(addPDF,0,WACV) delPDF = wx.Button(G2frame.FRMC,label='Delete PDF G(r) data sets') delPDF.Bind(wx.EVT_BUTTON,OnDelPDF) topSizer.Add(delPDF,0,WACV) mainSizer.Add(topSizer) table = [[item[1]['Fitrange'][0],item[1]['Fitrange'][1], item[1]['dscale'][0],item[1]['dscale'][1],item[1]['qdamp'][0],item[1]['qdamp'][1], item[1]['qbroad'][0],item[1]['qbroad'][1],item[1].get('Temp',300.)] for item in RMCPdict['seqfiles']] colLabels = ['Rmin','Rmax','dscale','refine','qdamp','refine','qbroad','refine','Temp'] rowLabels = [item[0] for item in RMCPdict['seqfiles']] Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_FLOAT+':10,2', wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL, wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL, wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,wg.GRID_VALUE_FLOAT+':10,2'] seqTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types) seqGrid = G2G.GSGrid(G2frame.FRMC) seqGrid.SetTable(seqTable, True) seqGrid.AutoSizeColumns(True) seqGrid.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, OnSetColVal) seqGrid.Bind(wg.EVT_GRID_CELL_CHANGED, OnSetVal) mainSizer.Add(seqGrid) return mainSizer # begin FileSizer topSizer = wx.BoxSizer(wx.HORIZONTAL) topSizer.Add(wx.StaticText(G2frame.FRMC,label=' Select data for processing: ')) mainSizer.Add(topSizer) # RMCProfile & PDFfit (Normal) Heads = ['Name','File','Format','Weight','Plot','Delete'] fileSizer = wx.FlexGridSizer(6,5,5) Formats = ['RMC','GUDRUN','PDFGET'] for head in Heads: fileSizer.Add(wx.StaticText(G2frame.FRMC,label=head),0,WACV) for fil in RMCPdict['files']: for head in Heads: fileSizer.Add(wx.StaticText(G2frame.FRMC,label=20*'-'),0,WACV) fileSizer.Add(wx.StaticText(G2frame.FRMC,label=fil),0,WACV) Rfile = RMCPdict['files'][fil][0] filSel = wx.Button(G2frame.FRMC,label=Rfile) filSel.Bind(wx.EVT_BUTTON,OnFileSel) Indx[filSel.GetId()] = fil fileSizer.Add(filSel,0,WACV) nform = 3 if 'G(r)' in fil: nform = 4 Name = 'Ndata' if 'Xray' in fil: nform = 1 Name = 'Xdata' if Rfile and os.path.exists(os.path.join(G2frame.LastGPXdir,Rfile)): #incase .gpx file is moved away from G(R), F(Q), etc. files fileFormat = wx.ComboBox(G2frame.FRMC,choices=Formats[:nform],style=wx.CB_DROPDOWN|wx.TE_READONLY) fileFormat.SetStringSelection(RMCPdict['files'][fil][3]) Indx[fileFormat.GetId()] = fil fileFormat.Bind(wx.EVT_COMBOBOX,OnFileFormat) fileSizer.Add(fileFormat,0,WACV) fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['files'][fil],1),0,WACV) plotBtn = wx.Button(G2frame.FRMC,label='Plot?',style=wx.BU_EXACTFIT) plotBtn.Bind(wx.EVT_BUTTON,OnPlotBtn) Indx[plotBtn.GetId()] = fil fileSizer.Add(plotBtn,0,WACV) delBtn = wx.Button(G2frame.FRMC,label='Del',style=wx.BU_EXACTFIT) delBtn.Bind(wx.EVT_BUTTON,OnDelBtn) Indx[delBtn.GetId()] = fil fileSizer.Add(delBtn,0,WACV) else: RMCPdict['files'][fil][0] = 'Select' fileSizer.Add((5,5),0) fileSizer.Add((5,5),0) fileSizer.Add((5,5),0) fileSizer.Add((5,5),0) if 'Select' not in Rfile and 'PDFfit' in G2frame.RMCchoice: fileSizer.Add(wx.StaticText(G2frame.FRMC,label=' R-range (from/to)'),0,WACV) fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict[Name]['Fitrange'],0,xmin=RMCPdict[Name]['Datarange'][0],xmax=3.0),0,WACV) fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict[Name]['Fitrange'],1,xmin=10.0,xmax=RMCPdict[Name]['Datarange'][1]),0,WACV) fileSizer.Add(wx.StaticText(G2frame.FRMC,label=' Scale factor: '),0,WACV) fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict[Name]['dscale'],0,xmin=0.001,xmax=20.0),0,WACV) scaleref = wx.CheckBox(G2frame.FRMC,label='refine') scaleref.SetValue(RMCPdict[Name]['dscale'][1]) Indx[scaleref.GetId()] = [Name,'dscale'] scaleref.Bind(wx.EVT_CHECKBOX,OnRef) fileSizer.Add(scaleref,0,WACV) fileSizer.Add(wx.StaticText(G2frame.FRMC,label=' Qdamp '),0,WACV) fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict[Name]['qdamp'],0,xmin=0.0,xmax=1.0),0,WACV) qdampref = wx.CheckBox(G2frame.FRMC,label='refine') qdampref.SetValue(RMCPdict[Name]['qdamp'][1]) Indx[qdampref.GetId()] = [Name,'qdamp'] qdampref.Bind(wx.EVT_CHECKBOX,OnRef) fileSizer.Add(qdampref,0,WACV) fileSizer.Add(wx.StaticText(G2frame.FRMC,label=' Qbroad '),0,WACV) fileSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict[Name]['qbroad'],0,xmin=0.0,xmax=1.0),0,WACV) qbroadref = wx.CheckBox(G2frame.FRMC,label='refine') qbroadref.SetValue(RMCPdict[Name]['qbroad'][1]) Indx[qbroadref.GetId()] = [Name,'qbroad'] qbroadref.Bind(wx.EVT_CHECKBOX,OnRef) fileSizer.Add(qbroadref,0,WACV) mainSizer.Add(fileSizer,0) return mainSizer def fullrmcSizer(RMCPdict): mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(wx.StaticText(G2frame.FRMC,label= '''* "Atomic Stochastic Modeling & Optimization with fullrmc", B. Aoun, J. Appl. Cryst. 2022, 55(6) 1664-1676, DOI: 10.1107/S1600576722008536; * "Fullrmc, a Rigid Body Reverse Monte Carlo Modeling Package Enabled with Machine Learning and Artificial Intelligence", B. Aoun, Jour. Comp. Chem. (2016), 37, 1102-1111. DOI: 10.1002/jcc.24304; * www.fullrmc.com ''')) # if G2pwd.findfullrmc() is None: # mainSizer.Add(wx.StaticText(G2frame.FRMC, # label="\nsorry, fullrmc not installed or was not located")) # return mainSizer G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_SETUPRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_RUNRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_VIEWRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_ATOMSRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_SUPERRMC,True) #mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' fullrmc big box starting pdb file preparation:'),0) # initialize fullrmc dictionary if needed RMCPdict = data['RMC']['fullrmc'] = data['RMC'].get('fullrmc',{}) # update, if atoms list has been updated Atypes = [atype.split('+')[0].split('-')[0] for atype in data['General']['AtomTypes']] aTypes = dict(zip(Atypes,len(Atypes)*[0.10,])) if len(data['RMC']['fullrmc'].get('aTypes',{})) != len(aTypes): #print('atypes has changed') atSeq = list(aTypes.keys()) lenA = len(atSeq) Pairs= [] for pair in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA) if 'Va' not in atSeq[j]] for i in range(lenA) if 'Va' not in atSeq[i]]: Pairs += pair Pairs = {pairs:[0.0,0.0,0.0] for pairs in Pairs} RMCPdict.update({'aTypes':aTypes,'atSeq':atSeq,'Pairs':Pairs}) RMCPdict['files'] = RMCPdict.get('files', {'Neutron real space data; G(r): ':['Select',1.,'G(r)',0,True], 'Neutron reciprocal space data; S(Q)-1: ':['Select',1.,'F(Q)',0,True], 'Xray real space data; G(r): ':['Select',1.,'G(r)',0,True], 'Xray reciprocal space data; S(Q)-1: ':['Select',1.,'F(Q)',0,True]}) if 'moleculePdb' not in RMCPdict: RMCPdict.update({'moleculePdb':'Select','targetDensity':1.0,'maxRecursion':10000}) if 'Angles' not in RMCPdict: RMCPdict.update({'Angles':[],'Angle Weight':1.e-5,'Bond Weight':1.e-5,'Torsions':[],'Torsion Weight':1.e-5}) for key,val in {'SuperCell':[1,1,1],'Box':[10.,10.,10.],'ReStart':[False,False],'Cycles':1, 'Swaps':[],'useBVS':False,'FitScale':False,'AveCN':[],'FxCN':[], 'min Contact':1.5,'periodicBound':True}.items(): RMCPdict[key] = RMCPdict.get(key,val) def GetSuperSizer(): def ShowRmax(*args,**kwargs): cell = data['General']['Cell'][1:7] bigcell = np.array(cell)*np.array(RMCPdict['SuperCell']+[1,1,1]) bigG = G2lat.cell2Gmat(bigcell)[0] rmax = min([0.5/np.sqrt(G2lat.calc_rDsq2(H,bigG)) for H in np.eye(3)]) rmaxlbl.SetLabel(' Rmax = {:.1f}'.format(rmax)) superSizer = wx.BoxSizer(wx.HORIZONTAL) axes = ['X','Y','Z'] for i,ax in enumerate(axes): superSizer.Add(wx.StaticText(G2frame.FRMC,label=' %s-axis: '%ax),0,WACV) superSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['SuperCell'], i,xmin=1,xmax=20,size=(50,25),OnLeave=ShowRmax),0,WACV) rmaxlbl = wx.StaticText(G2frame.FRMC,label=' Rmax=?') superSizer.Add(rmaxlbl,0,WACV) ShowRmax() return superSizer def GetBoxSizer(): boxSizer = wx.BoxSizer(wx.HORIZONTAL) axes = ['X','Y','Z'] for i,ax in enumerate(axes): boxSizer.Add(wx.StaticText(G2frame.FRMC,label=' %s-axis: '%ax),0,WACV) boxSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['Box'], i,xmin=10.,xmax=50.,size=(50,25)),0,WACV) return boxSizer def OnReStart(event): RMCPdict['ReStart'][0] = not RMCPdict['ReStart'][0] def OnAddSwap(event): RMCPdict['Swaps'].append(['','',0.0,]) wx.CallAfter(UpdateRMC,G2frame,data) def OnPdbButton(event): dlg = wx.FileDialog(G2frame.FRMC, 'Choose molecule pdb file',G2frame.LastGPXdir, style=wx.FD_OPEN ,wildcard='PDB file(*.pdb)|*.pdb') if dlg.ShowModal() == wx.ID_OK: fpath,fName = os.path.split(dlg.GetPath()) RMCPdict['moleculePdb'] = fName pdbButton.SetLabel(fName) def OnAddAngle(event): RMCPdict['Angles'].append(['','','',0.,0.,0.,0.]) wx.CallAfter(UpdateRMC,G2frame,data) # def OnAddTorsion(event): # RMCPdict['Torsions'].append(['','','','',0.,0.,0.,0.,0.,0.]) # wx.CallAfter(,G2frame,data,event) def GetAngleSizer(): def OnDelAngle(event): Obj = event.GetEventObject() angle = Indx[Obj.GetId()] del RMCPdict['Angles'][angle] wx.CallAfter(UpdateRMC,G2frame,data) # def OnAngleAtSel(event): # Obj = event.GetEventObject() # angle,i = Indx[Obj.GetId()] # RMCPdict['Angles'][angle][i] = Obj.GetStringSelection() def SetRestart1(invalid,value,tc): RMCPdict['ReStart'][1] = True Indx = {} atChoice = [atm for atm in RMCPdict['atSeq'] if 'Va' not in atm] angleSizer = wx.GridBagSizer(0,5) fxcnLabels1 = [' ',' ','Central','',None,'angle restraint values (deg)',None,'search distance (A)'] fxcnLabels2 = [' ','Atom-A','Atom','Atom-C','min','max','from','to'] for i in range(8): if fxcnLabels1[i]: cspan=1 coloff = 0 if fxcnLabels1[i-1] is None: cspan=2 coloff = 1 angleSizer.Add(wx.StaticText(G2frame.FRMC,label=fxcnLabels1[i]), (0,i-coloff),(1,cspan)) if fxcnLabels2[i]: angleSizer.Add(wx.StaticText(G2frame.FRMC,wx.ID_ANY, label=fxcnLabels2[i],style=wx.CENTER),(1,i)) row = 1 for ifx,angle in enumerate(RMCPdict['Angles']): row += 1 angleSizer.Add((30,-1),(row,0)) for i in range(3): if angle[i] not in atChoice: angle[i] = atChoice[0] atmSel = G2G.EnumSelector(G2frame.FRMC,angle,i,atChoice) angleSizer.Add(atmSel,(row,1+i)) for i in range(4): if i == 0: xmin,xmax=0.,180. elif i == 2: xmin,xmax=0.1,6. angleSizer.Add( G2G.ValidatedTxtCtrl(G2frame.FRMC,angle,3+i,xmin=xmin,xmax=xmax, OnLeave=SetRestart1,size=(50,25)),(row,4+i)) delBtn = wx.Button(G2frame.FRMC,label='Del',style=wx.BU_EXACTFIT) delBtn.Bind(wx.EVT_BUTTON,OnDelAngle) Indx[delBtn.GetId()] = ifx angleSizer.Add(delBtn,(row,9)) return angleSizer # def GetTorsionSizer(): # def OnDelTorsion(event): # Obj = event.GetEventObject() # angle = Indx[Obj.GetId()] # del RMCPdict['Torsions'][angle] # wx.CallAfter(UpdateRMC,G2frame,data) # def OnTorsionAtSel(event): # Obj = event.GetEventObject() # torsion,i = Indx[Obj.GetId()] # RMCPdict['Torsions'][torsion][i] = Obj.GetStringSelection() # def SetRestart1(invalid,value,tc): # RMCPdict['ReStart'][1] = True # Indx = {} # atChoice = [atm for atm in RMCPdict['atSeq'] if 'Va' not in atm] # torsionSizer = wx.FlexGridSizer(11,5,5) # fxcnLabels = [' ','Atom-A','Atom-B','Atom-C','Atom-D',' min angle1',' max angle1',' min angle2',' max angle2',' min angle3',' max angle3'] # for lab in fxcnLabels: # torsionSizer.Add(wx.StaticText(G2frame.FRMC,label=lab),0,WACV) # for ifx,torsion in enumerate(RMCPdict['Torsions']): # delBtn = wx.Button(G2frame.FRMC,label='Delete') # delBtn.Bind(wx.EVT_BUTTON,OnDelTorsion) # Indx[delBtn.GetId()] = ifx # torsionSizer.Add(delBtn,0,WACV) # for i in [0,1,2,3]: # atmSel = wx.ComboBox(G2frame.FRMC,choices=atChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) # atmSel.SetStringSelection(torsion[i]) # atmSel.Bind(wx.EVT_COMBOBOX,OnTorsionAtSel) # Indx[atmSel.GetId()] = [ifx,i] # torsionSizer.Add(atmSel,0,WACV) # for i in [4,5,6,7,8,9]: # torsionSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,torsion,i,xmin=0.,xmax=360.,OnLeave=SetRestart1,size=(50,25)),0,WACV) # return torsionSizer generalData = data['General'] cx,ct,cs,cia = generalData['AtomPtrs'] #atomData = data['Atoms'] # atNames = [atom[ct-1] for atom in atomData] # ifP1 = False # if generalData['SGData']['SpGrp'] == 'P 1': # ifP1 = True ifBox = False if 'macromolecular' in generalData['Type']: ifBox = True lineSizer = wx.BoxSizer(wx.HORIZONTAL) if ifBox: lineSizer.Add(wx.StaticText(G2frame.FRMC,label=' Big box dimensions, %s:'%Angstr),0,WACV) lineSizer.Add(GetBoxSizer(),0,WACV) # elif ifP1: lineSizer.Add(wx.StaticText(G2frame.FRMC,label=' Lattice multipliers:'),0,WACV) lineSizer.Add(GetSuperSizer(),0,WACV) lineSizer.Add((5,-1)) # Bachir suggests that w/o periodic boundaries, users are likely to use fullrmc wrong #lineSizer.Add(G2G.G2CheckBox(G2frame.FRMC,'Impose periodic boundaries',RMCPdict,'periodicBound'), # 0,WACV) mainSizer.Add(lineSizer,0) if ifBox: molecSizer = wx.BoxSizer(wx.HORIZONTAL) molecSizer.Add(wx.StaticText(G2frame.FRMC,label=' Source molecule file '),0,WACV) pdbButton = wx.Button(G2frame.FRMC,label=RMCPdict['moleculePdb']) pdbButton.Bind(wx.EVT_BUTTON,OnPdbButton) molecSizer.Add(pdbButton,0,WACV) molecSizer.Add(wx.StaticText(G2frame.FRMC,label=' target density, gm/cc '),0,WACV) molecSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'targetDensity',xmin=0.1,size=[60,25]),0,WACV) molecSizer.Add(wx.StaticText(G2frame.FRMC,label=' max tries '),0,WACV) molecSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'maxRecursion',xmin=1000,xmax=1000000,size=[60,25]),0,WACV) mainSizer.Add(molecSizer,0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' fullrmc run file preparation:')) resLine = wx.BoxSizer(wx.HORIZONTAL) resLine.Add(wx.StaticText(G2frame.FRMC,label=' Run '),0,WACV) resLine.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'Cycles',xmin=1,size=[60,25])) resLine.Add(wx.StaticText(G2frame.FRMC, label=' computation cycles of '),0,WACV) RMCPdict['Steps/cycle'] = RMCPdict.get('Steps/cycle',5000) resLine.Add(G2G.EnumSelector(G2frame.FRMC,RMCPdict,'Steps/cycle', ['1K','5K','10K','50K'],[1000,5000,10000,50000]),0,WACV) resLine.Add(wx.StaticText(G2frame.FRMC, label=' steps per cycle'),0,WACV) mainSizer.Add(resLine,0) resLine = wx.BoxSizer(wx.HORIZONTAL) resLine.Add(wx.StaticText(G2frame.FRMC, label=' Restart fullrmc Engine? '),0,WACV) restart = wx.CheckBox(G2frame.FRMC,label='(will clear old result!) ') resLine.Add(restart,0,WACV) restart.SetValue(RMCPdict['ReStart'][0]) restart.Bind(wx.EVT_CHECKBOX,OnReStart) mainSizer.Add(resLine,0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(GetAtmChoice(G2frame.FRMC,RMCPdict),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) swapBox = wx.BoxSizer(wx.HORIZONTAL) swapBox.Add(wx.StaticText(G2frame.FRMC,label='Atom swap probabiities: '),0,WACV) swapAdd = wx.Button(G2frame.FRMC,label='Add',style=wx.BU_EXACTFIT) swapAdd.Bind(wx.EVT_BUTTON,OnAddSwap) swapBox.Add(swapAdd,0,WACV) mainSizer.Add(swapBox,0) if len(RMCPdict['Swaps']): mainSizer.Add(GetSwapSizer(RMCPdict),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(wx.StaticText(G2frame.FRMC,label='Geometry constraints && restraints'),0) distBox = wx.BoxSizer(wx.HORIZONTAL) distBox.Add(wx.StaticText(G2frame.FRMC,label='Distance constraints'),0,WACV) # weights removed for now #distBox.Add(wx.StaticText(G2frame.FRMC,label=', distance weight:'),0,WACV) #distBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'Bond Weight',xmin=0.,xmax=100.,size=(50,25)),0,WACV) distBox.Add(wx.StaticText(G2frame.FRMC,label=' min contact dist: '),0,WACV) distBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'min Contact',xmin=0.,xmax=4.,size=(50,25)),0,WACV) RMCPdict['useBondConstraints'] = RMCPdict.get('useBondConstraints',True) distBox.Add(wx.StaticText(G2frame.FRMC,label=' Use bond constraints? '),0,WACV) distBox.Add(G2G.G2CheckBox(G2frame.FRMC,'',RMCPdict,'useBondConstraints', OnChange=lambda event:UpdateRMC(G2frame,data)),0,WACV) mainSizer.Add(distBox,0) if RMCPdict['useBondConstraints']: mainSizer.Add(GetPairSizer(G2frame.FRMC,RMCPdict),0) mainSizer.Add((-1,10)) angBox = wx.BoxSizer(wx.HORIZONTAL) angBox.Add(wx.StaticText(G2frame.FRMC,label='A-B-C angle restraints'),0,WACV) # weights removed for now #angBox.Add(wx.StaticText(G2frame.FRMC,label=', angle weight:'),0,WACV) #angBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'Angle Weight',xmin=0.,xmax=100.,size=(50,25)),0,WACV) angBox.Add((20,-1)) angAdd = wx.Button(G2frame.FRMC,label='Add',style=wx.BU_EXACTFIT) angAdd.Bind(wx.EVT_BUTTON,OnAddAngle) angBox.Add(angAdd,0,WACV) mainSizer.Add(angBox,0) if len(RMCPdict['Angles']): mainSizer.Add(GetAngleSizer(),0) RMCPdict['Groups'] = RMCPdict.get('Groups',[]) def OnAddGroup(event): index = len(RMCPdict['Groups']) RMCPdict['Groups'].append([]) GroupEditor(index) def OnDelGroup(event): index = event.EventObject.index del RMCPdict['Groups'][index] wx.CallAfter(UpdateRMC,G2frame,data) def OnEdtGroup(event): index = event.EventObject.index GroupEditor(index) def GroupEditor(index): cx,ct,cs,cia = data['General']['AtomPtrs'] atomlbs = [a[ct-1] for a in data['Atoms']] dlg = G2G.G2MultiChoiceDialog(G2frame.FRMC,'Atom Selector', 'Select atoms to include in group',atomlbs,selected=RMCPdict['Groups'][index]) if dlg.ShowModal() == wx.ID_OK: RMCPdict['Groups'][index] = dlg.GetSelections() dlg.Destroy() if len(RMCPdict['Groups'][index]) == 0: del RMCPdict['Groups'][index] wx.CallAfter(UpdateRMC,G2frame,data) if len(RMCPdict['Groups']) == 0: grpAdd = wx.Button(G2frame.FRMC,label='Define atom group',style=wx.BU_EXACTFIT) grpAdd.Bind(wx.EVT_BUTTON,OnAddGroup) mainSizer.Add(grpAdd,0) else: grpBox = wx.BoxSizer(wx.HORIZONTAL) grpBox.Add(wx.StaticText(G2frame.FRMC,label='Atom Groups: '),0,WACV) grpAdd = wx.Button(G2frame.FRMC,label='Add group',style=wx.BU_EXACTFIT) grpAdd.Bind(wx.EVT_BUTTON,OnAddGroup) RMCPdict['GroupMode'] = RMCPdict.get('GroupMode',0) grpBox.Add(grpAdd,0,WACV) grpBox.Add(wx.StaticText(G2frame.FRMC, label=' Group refinement mode: '),0,WACV) grpBox.Add(G2G.EnumSelector(G2frame.FRMC,RMCPdict,'GroupMode', ('Rotate & Translate','Rotate only','Translate only'), [0,1,2]),0,WACV) mainSizer.Add(grpBox,0) for i,g in enumerate(RMCPdict['Groups']): grpBox = wx.BoxSizer(wx.HORIZONTAL) grpBox.Add((20,-1)) grpBox.Add(wx.StaticText(G2frame.FRMC,label='Group #'+str(i+1)),0,WACV) grpBox.Add((4,-1)) grpdel = wx.Button(G2frame.FRMC,label='Del',style=wx.BU_EXACTFIT) grpdel.Bind(wx.EVT_BUTTON,OnDelGroup) grpdel.index = i grpBox.Add(grpdel,0,WACV) grpadd = wx.Button(G2frame.FRMC,label='Edit',style=wx.BU_EXACTFIT) grpadd.Bind(wx.EVT_BUTTON,OnEdtGroup) grpadd.index = i grpBox.Add(grpadd,0,WACV) msg = ' Contains atoms: ' for i,n in enumerate(g): if i+1 == len(g): msg += ' && ' elif i > 0: msg += ', ' msg += str(i) grpBox.Add(wx.StaticText(G2frame.FRMC,label=msg),0,WACV) mainSizer.Add(grpBox,0) RMCPdict['addThermalBroadening'] = RMCPdict.get('addThermalBroadening',False) mainSizer.Add((-1,5)) distBox = wx.BoxSizer(wx.HORIZONTAL) distBox.Add(wx.StaticText(G2frame.FRMC,label=' Add thermal broadening? '),0,WACV) distBox.Add(G2G.G2CheckBox(G2frame.FRMC,'',RMCPdict,'addThermalBroadening', OnChange=lambda event:UpdateRMC(G2frame,data)),0,WACV) if RMCPdict['addThermalBroadening']: distBox.Add((15,-1)) distBox.Add(wx.StaticText(G2frame.FRMC,label='Uiso equiv.'),0,WACV) RMCPdict['ThermalU'] = RMCPdict.get('ThermalU',{}) for atm in RMCPdict['aTypes']: RMCPdict['ThermalU'][atm] = RMCPdict['ThermalU'].get(atm,0.005) distBox.Add(wx.StaticText(G2frame.FRMC,label=' '+atm+':'),0,WACV) distBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['ThermalU'],atm, xmin=0.0001,xmax=0.25,size=(50,25)),0,WACV) mainSizer.Add(distBox,0) if RMCPdict['addThermalBroadening']: mainSizer.Add((-1,5)) # Torsions are difficult to implement. Need to be internal to a unit cell & named with fullrmc # atom labels. Leave this out, at least for now. # torBox = wx.BoxSizer(wx.HORIZONTAL) # torAdd = wx.Button(G2frame.FRMC,label='Add') # torAdd.Bind(wx.EVT_BUTTON,OnAddTorsion) # torBox.Add(torAdd,0,WACV) # torBox.Add(wx.StaticText(G2frame.FRMC,label=' A-B-C-D torsion angle restraints (intracell only), weight: '),0,WACV) # torBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,'Torsion Weight',xmin=0.,xmax=100.,size=(50,25)),0,WACV) # mainSizer.Add(torBox,0) # if len(RMCPdict['Torsions']): # mainSizer.Add(GetTorsionSizer(),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(FileSizer(RMCPdict)) return mainSizer def RMCProfileSizer(RMCPdict): def CheckAtms(Atypes): newAtm = False for atm in Atypes: if atm not in data['RMC']['RMCProfile'].get('aTypes',{}): newAtm = True break for atm in data['RMC']['RMCProfile'].get('aTypes',{}): if atm not in Atypes: newAtm = True break return newAtm mainSizer = wx.BoxSizer(wx.VERTICAL) subSizer = wx.BoxSizer(wx.HORIZONTAL) subSizer.Add((-1,-1),1,wx.EXPAND) subSizer.Add(wx.StaticText(G2frame.FRMC,label='RMCProfile setup'),0,WACV) subSizer.Add((-1,-1),1,wx.EXPAND) mainSizer.Add(subSizer) mainSizer.Add((5,5)) txt = wx.StaticText(G2frame.FRMC,label= f"Please cite: {G2G.GetCite('RMCProfile')}") txt.Wrap(500) mainSizer.Add(txt) mainSizer.Add((5,5)) Atypes = [atype.split('+')[0].split('-')[0] for atype in data['General']['AtomTypes']] aTypes = dict(zip(Atypes,len(Atypes)*[0.10,])) atSeq = list(aTypes.keys()) lenA = len(atSeq) atOxid = [[atmdata.BVSoxid[atm][0],0.001] for atm in atSeq] if CheckAtms(Atypes): oldPairs = data['RMC']['RMCProfile'].get('Pairs',{}) Pairs = {} # for pairs in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA) if 'Va' not in atSeq[j]] for i in range(lenA) if 'Va' not in atSeq[i]]: for pairs in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA)] for i in range(lenA)]: for pair in pairs: if pair in oldPairs: Pairs[pair] = oldPairs[pair] else: Pairs[pair] = [0.0,0.0,0.0] data['RMC']['RMCProfile'].update({'aTypes':aTypes,'atSeq':atSeq,'Pairs':Pairs,'Oxid':atOxid,}) if not data['RMC']['RMCProfile'] or 'metadata' not in RMCPdict: Pairs = {} # for pairs in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA) if 'Va' not in atSeq[j]] for i in range(lenA) if 'Va' not in atSeq[i]]: for pairs in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA)] for i in range(lenA)]: for pair in pairs: Pairs[pair] = [0.0,0.0,0.0] BVSpairs = [] if lenA > 1: # for pair in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA) if 'Va' not in atSeq[j]] for i in range(lenA) if 'Va' not in atSeq[i]]: for pair in [[' %s-%s'%(atSeq[i],atSeq[j]) for j in range(i,lenA)] for i in range(lenA)]: BVSpairs += pair BVS = {pairs:[0.0,0.0,0.0,0.0] for pairs in BVSpairs} files = {'Neutron real space data; G(r): ':['Select',0.05,'G(r)','RMC',], 'Neutron reciprocal space data; F(Q): ':['Select',0.05,'F(Q)','RMC',], 'Neutron reciprocal space data; S(Q): ':['Select',0.05,'S(Q)','RMC',], # 'Xray real space data; G(r): ':['Select',0.01,'G(r)','RMC',], 'Xray reciprocal space data; F(Q): ':['Select',0.01,'F(Q)','RMC',],} runTimes = [10.,1.] metadata = {'title':'none','owner':'no one','date':str(time.ctime()),'temperature':'300K', 'material':'nothing','phase':'vacuum','comment':'none ','source':'nowhere'} data['RMC']['RMCProfile'].update({'SuperCell':[1,1,1],'UseSampBrd':[True,True],'aTypes':aTypes, 'histogram':['',1.0],'files':files,'metadata':metadata,'FitScale':False,'atSeq':atSeq, 'runTimes':runTimes,'ReStart':[False,False],'BVS':BVS,'Oxid':atOxid,'useBVS':False,'Swaps':[], 'AveCN':[],'FxCN':[],'Potentials':{'Angles':[],'Angle search':10.,'Stretch':[],'Pairs':Pairs, 'Stretch search':10.,'Pot. Temp.':300.,'useGPU':False,}}) # data['RMC']['RMCProfile']['aTypes'] = {aTypes[atype] for atype in aTypes if atype in Atypes} data['RMC']['RMCProfile']['Isotope'] = copy.copy(data['General']['Isotope']) data['RMC']['RMCProfile']['Isotopes'] = copy.deepcopy(data['General']['Isotopes']) data['RMC']['RMCProfile']['NoAtoms'] = copy.copy(data['General']['NoAtoms']) RMCPdict = data['RMC']['RMCProfile'] #patches if 'FitScale' not in RMCPdict: RMCPdict['FitScale'] = False if 'useGPU' not in RMCPdict: RMCPdict['useGPU'] = False #end patches def OnHisto(event): RMCPdict['histogram'][0] = histo.GetStringSelection() def OnSize(event): RMCPdict['UseSampBrd'][0] = samSize.GetValue() def OnStrain(event): RMCPdict['UseSampBrd'][1] = strain.GetValue() def OnFitScale(event): RMCPdict['FitScale'] = not RMCPdict['FitScale'] def SetRestart(invalid,value,tc): RMCPdict['ReStart'] = [True,True] def OnUseBVS(event): RMCPdict['useBVS'] = not RMCPdict['useBVS'] wx.CallAfter(UpdateRMC,G2frame,data) def OnAddSwap(event): RMCPdict['Swaps'].append(['','',0.0,]) wx.CallAfter(UpdateRMC,G2frame,data) def OnAddFxCN(event): RMCPdict['FxCN'].append(['','',0.5,2.0,6,1.0,0.00001]) wx.CallAfter(UpdateRMC,G2frame,data) def OnAddAveCN(event): RMCPdict['AveCN'].append(['','',0.5,2.0,6.,0.00001]) wx.CallAfter(UpdateRMC,G2frame,data) def OnAddAnglePot(event): RMCPdict['Potentials']['Angles'].append(['','','',0.,0.,0.,0.]) wx.CallAfter(UpdateRMC,G2frame,data) def OnAddBondPot(event): RMCPdict['Potentials']['Stretch'].append(['','',0.,0.]) wx.CallAfter(UpdateRMC,G2frame,data) def GetTimeSizer(): def OnUseGPU(event): RMCPdict['useGPU'] = not RMCPdict['useGPU'] timeSizer = wx.BoxSizer(wx.HORIZONTAL) timeSizer.Add(wx.StaticText(G2frame.FRMC,label=' Total running time (min): '),0,WACV) timeSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['runTimes'],0,xmin=0.,size=(70,25)),0,WACV) timeSizer.Add(wx.StaticText(G2frame.FRMC,label=' Save interval time (min): '),0,WACV) timeSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['runTimes'],1,xmin=0.1,xmax=20.,size=(50,25)),0,WACV) usegpu = wx.CheckBox(G2frame.FRMC,label=' use GPU?') usegpu.SetValue(RMCPdict['useGPU']) usegpu.Bind(wx.EVT_CHECKBOX,OnUseGPU) timeSizer.Add(usegpu,0,WACV) return timeSizer # def GetSuperSizer(Xmax): # superSizer = wx.BoxSizer(wx.HORIZONTAL) # axes = ['X','Y','Z'] # for i,ax in enumerate(axes): # superSizer.Add(wx.StaticText(G2frame.FRMC,label=' %s-axis: '%ax),0,WACV) # superSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['SuperCell'], # i,xmin=1,xmax=xamx,size=(50,25),OnLeave=SetRestart),0,WACV) # return superSizer def GetBvsSizer(pnl): def OnResetBVS(event): Obj = event.GetEventObject() pair = Indx[Obj.GetId()] pId = [key for key in RMCPdict['BVS']].index(pair)+1 nId = len(RMCPdict['BVS'])+1 dist = G2elem.GetBVS(pair,RMCPdict['atSeq'],RMCPdict['Oxid']) if dist: RMCPdict['BVS'][pair] = [dist,0.37,3.0] bvsCh = bvsSizer.GetChildren() addr = 2*nId+pId bvsCh[addr].Window.SetValue('%6.3f'%dist) bvsCh[addr+nId].Window.SetValue('0.37') bvsCh[addr+2*nId].Window.SetValue('3.00') bvsSizer = wx.FlexGridSizer(len(RMCPdict['BVS'])+1,5,5) bvsSizer.Add((5,5),0) for pair in RMCPdict['BVS']: bvsSizer.Add(wx.StaticText(pnl,label=pair),0,WACV) bvsSizer.Add(wx.StaticText(pnl,label=' Reset:'),0,WACV) for pair in RMCPdict['BVS']: reset = wx.Button(pnl,label='Yes') bvsSizer.Add(reset,0,WACV) reset.Bind(wx.EVT_BUTTON,OnResetBVS) Indx[reset.GetId()] = pair bvsSizer.Add(wx.StaticText(pnl,label=' Bond length:'),0,WACV) for pair in RMCPdict['BVS']: bvsSizer.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['BVS'][pair],0,xmin=0.,xmax=10.,size=(50,25)),0,WACV) bvsSizer.Add(wx.StaticText(pnl,label=' B constant (0.37): '),0,WACV) for pair in RMCPdict['BVS']: bvsSizer.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['BVS'][pair],1,xmin=0.,xmax=10.,size=(50,25)),0,WACV) bvsSizer.Add(wx.StaticText(pnl,label=' Cut off: '),0,WACV) for pair in RMCPdict['BVS']: bvsSizer.Add(G2G.ValidatedTxtCtrl(pnl,RMCPdict['BVS'][pair],2,xmin=0.,xmax=10.,size=(50,25)),0,WACV) return bvsSizer def GetFxcnSizer(): def OnDelFxCN(event): Obj = event.GetEventObject() fxCN = Indx[Obj.GetId()] del RMCPdict['FxCN'][fxCN] wx.CallAfter(UpdateRMC,G2frame,data) def OnFxcnAtSel(event): Obj = event.GetEventObject() ifxCN,i = Indx[Obj.GetId()] RMCPdict['FxCN'][ifxCN][i] = Obj.GetStringSelection() fxcnSizer = wx.FlexGridSizer(8,5,5) atChoice = [atm for atm in RMCPdict['atSeq'] if 'Va' not in atm] fxcnLabels = [' ','Atom-1','Atom-2','min dist','max dist','CN','fraction','weight'] for lab in fxcnLabels: fxcnSizer.Add(wx.StaticText(G2frame.FRMC,label=lab),0,WACV) for ifx,fxCN in enumerate(RMCPdict['FxCN']): delBtn = wx.Button(G2frame.FRMC,label='Delete') delBtn.Bind(wx.EVT_BUTTON,OnDelFxCN) Indx[delBtn.GetId()] = ifx fxcnSizer.Add(delBtn,0,WACV) for i in [0,1]: atmSel = wx.ComboBox(G2frame.FRMC,choices=atChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) atmSel.SetStringSelection(fxCN[i]) atmSel.Bind(wx.EVT_COMBOBOX,OnFxcnAtSel) Indx[atmSel.GetId()] = [ifx,i] fxcnSizer.Add(atmSel,0,WACV) fxcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,2,xmin=0.,xmax=5.,size=(50,25)),0,WACV) fxcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,3,xmin=0.,xmax=5.,size=(50,25)),0,WACV) fxcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,4,xmin=1,xmax=12,size=(50,25)),0,WACV) fxcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,5,xmin=0.,xmax=1.,size=(50,25)),0,WACV) fxcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,6,xmin=0.,size=(50,25)),0,WACV) return fxcnSizer def GetAvcnSizer(): def OnDelAvCN(event): Obj = event.GetEventObject() fxCN = Indx[Obj.GetId()] del RMCPdict['AveCN'][fxCN] wx.CallAfter(UpdateRMC,G2frame,data) def OnAvcnAtSel(event): Obj = event.GetEventObject() ifxCN,i = Indx[Obj.GetId()] RMCPdict['AveCN'][ifxCN][i] = Obj.GetStringSelection() avcnSizer = wx.FlexGridSizer(7,5,5) atChoice = [atm for atm in RMCPdict['atSeq'] if 'Va' not in atm] fxcnLabels = [' ','Atom-1','Atom-2','min dist','max dist','CN','weight'] for lab in fxcnLabels: avcnSizer.Add(wx.StaticText(G2frame.FRMC,label=lab),0,WACV) for ifx,fxCN in enumerate(RMCPdict['AveCN']): delBtn = wx.Button(G2frame.FRMC,label='Delete') delBtn.Bind(wx.EVT_BUTTON,OnDelAvCN) Indx[delBtn.GetId()] = ifx avcnSizer.Add(delBtn,0,WACV) for i in [0,1]: atmSel = wx.ComboBox(G2frame.FRMC,choices=atChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) atmSel.SetStringSelection(fxCN[i]) atmSel.Bind(wx.EVT_COMBOBOX,OnAvcnAtSel) Indx[atmSel.GetId()] = [ifx,i] avcnSizer.Add(atmSel,0,WACV) avcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,2,xmin=0.,xmax=5.,size=(50,25)),0,WACV) avcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,3,xmin=0.,xmax=5.,size=(50,25)),0,WACV) avcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,4,xmin=1.,xmax=12.,size=(50,25)),0,WACV) avcnSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,fxCN,5,xmin=0.,size=(50,25)),0,WACV) return avcnSizer def GetAngleSizer(): def OnDelAngle(event): Obj = event.GetEventObject() angle = Indx[Obj.GetId()] del RMCPdict['Potentials']['Angles'][angle] wx.CallAfter(UpdateRMC,G2frame,data) def OnAngleAtSel(event): Obj = event.GetEventObject() angle,i = Indx[Obj.GetId()] RMCPdict['Potentials']['Angles'][angle][i] = Obj.GetStringSelection() def SetRestart1(invalid,value,tc): RMCPdict['ReStart'][1] = True atChoice = [atm for atm in RMCPdict['atSeq'] if 'Va' not in atm] angleSizer = wx.FlexGridSizer(8,5,5) fxcnLabels = [' ','Atom-A','Atom-B','Atom-C',' ABC angle','AB dist','BC dist','potential'] for lab in fxcnLabels: angleSizer.Add(wx.StaticText(G2frame.FRMC,label=lab),0,WACV) for ifx,angle in enumerate(RMCPdict['Potentials']['Angles']): delBtn = wx.Button(G2frame.FRMC,label='Delete') delBtn.Bind(wx.EVT_BUTTON,OnDelAngle) Indx[delBtn.GetId()] = ifx angleSizer.Add(delBtn,0,WACV) for i in [0,1,2]: atmSel = wx.ComboBox(G2frame.FRMC,choices=atChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) atmSel.SetStringSelection(angle[i]) atmSel.Bind(wx.EVT_COMBOBOX,OnAngleAtSel) Indx[atmSel.GetId()] = [ifx,i] angleSizer.Add(atmSel,0,WACV) angleSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,angle,3,xmin=0.,xmax=180.,OnLeave=SetRestart1,size=(50,25)),0,WACV) angleSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,angle,4,xmin=0.5,xmax=5.,OnLeave=SetRestart1,size=(50,25)),0,WACV) angleSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,angle,5,xmin=0.5,xmax=5.,OnLeave=SetRestart1,size=(50,25)),0,WACV) angleSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,angle,6,xmin=0.,OnLeave=SetRestart1,size=(50,25)),0,WACV) return angleSizer def GetBondSizer(): def OnDelBond(event): Obj = event.GetEventObject() bond = Indx[Obj.GetId()] del RMCPdict['Potentials']['Stretch'][bond] wx.CallAfter(UpdateRMC,G2frame,data) def OnBondAtSel(event): Obj = event.GetEventObject() bond,i = Indx[Obj.GetId()] RMCPdict['Potentials']['Stretch'][bond][i] = Obj.GetStringSelection() def SetRestart1(invalid,value,tc): RMCPdict['ReStart'][1] = True atChoice = [atm for atm in RMCPdict['atSeq'] if 'Va' not in atm] bondSizer = wx.FlexGridSizer(5,5,5) fxcnLabels = [' ','Atom-A','Atom-B',' AB dist','potential'] for lab in fxcnLabels: bondSizer.Add(wx.StaticText(G2frame.FRMC,label=lab),0,WACV) for ifx,bond in enumerate(RMCPdict['Potentials']['Stretch']): delBtn = wx.Button(G2frame.FRMC,label='Delete') delBtn.Bind(wx.EVT_BUTTON,OnDelBond) Indx[delBtn.GetId()] = ifx bondSizer.Add(delBtn,0,WACV) for i in [0,1]: atmSel = wx.ComboBox(G2frame.FRMC,choices=atChoice,style=wx.CB_DROPDOWN|wx.TE_READONLY) atmSel.SetStringSelection(bond[i]) atmSel.Bind(wx.EVT_COMBOBOX,OnBondAtSel) Indx[atmSel.GetId()] = [ifx,i] bondSizer.Add(atmSel,0,WACV) bondSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,bond,2,xmin=0.,xmax=5.,OnLeave=SetRestart1,size=(50,25)),0,WACV) bondSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,bond,3,xmin=0.,size=(50,25)),0,WACV) return bondSizer Indx = {} mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' Enter metadata items:'),0) mainSizer.Add(GetMetaSizer(RMCPdict,['title','owner','material','phase','comment','source',]),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(GetTimeSizer(),0) mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' Lattice multipliers; if changed will force reset of atom positions:'),0) mainSizer.Add(GetSuperSizer(RMCPdict,20),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mSizer = wx.BoxSizer(wx.VERTICAL) mSizer.Add(wx.StaticText(G2frame.FRMC,label='Enter atom settings'),0) mSizer.Add(GetAtmChoice(G2frame.FRMC,RMCPdict),0) mSizer.Add(wx.StaticText(G2frame.FRMC,label=' N.B.: be sure to set cations first && anions last in atom ordering')) mainSizer.Add(mSizer) G2G.HorizontalLine(mainSizer,G2frame.FRMC) swapBox = wx.BoxSizer(wx.HORIZONTAL) swapAdd = wx.Button(G2frame.FRMC,label='Add') swapAdd.Bind(wx.EVT_BUTTON,OnAddSwap) swapBox.Add(swapAdd,0,WACV) swapBox.Add(wx.StaticText(G2frame.FRMC,label=' Atom swap probabilities: '),0,WACV) mainSizer.Add(swapBox,0) if len(RMCPdict['Swaps']): mainSizer.Add(GetSwapSizer(RMCPdict),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mSizer = wx.BoxSizer(wx.VERTICAL) mSizer.Add(wx.StaticText(G2frame.FRMC,label='Enter constraints && restraints via minimum && maximum distances for atom pairs:'),0) mSizer.Add(GetPairSizer(G2frame.FRMC,RMCPdict),0) mainSizer.Add(mSizer) G2G.HorizontalLine(mainSizer,G2frame.FRMC) useBVS = wx.CheckBox(G2frame.FRMC,label=' Use bond valence sum restraints for (set to 0 for non-bonded ones):') useBVS.SetValue(RMCPdict.get('useBVS',False)) useBVS.Bind(wx.EVT_CHECKBOX,OnUseBVS) mainSizer.Add(useBVS,0) if RMCPdict.get('useBVS',False): mSizer = wx.BoxSizer(wx.VERTICAL) mSizer.Add(GetBvsSizer(G2frame.FRMC),0) mainSizer.Add(mSizer) G2G.HorizontalLine(mainSizer,G2frame.FRMC) fxcnBox = wx.BoxSizer(wx.HORIZONTAL) fxcnAdd = wx.Button(G2frame.FRMC,label='Add') fxcnAdd.Bind(wx.EVT_BUTTON,OnAddFxCN) fxcnBox.Add(fxcnAdd,0,WACV) fxcnBox.Add(wx.StaticText(G2frame.FRMC,label=' Fixed coordination number restraint: '),0,WACV) mainSizer.Add(fxcnBox,0) if len(RMCPdict['FxCN']): mainSizer.Add(GetFxcnSizer(),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) avcnBox = wx.BoxSizer(wx.HORIZONTAL) avcnAdd = wx.Button(G2frame.FRMC,label='Add') avcnAdd.Bind(wx.EVT_BUTTON,OnAddAveCN) avcnBox.Add(avcnAdd,0,WACV) avcnBox.Add(wx.StaticText(G2frame.FRMC,label=' Average coordination number restraint: '),0,WACV) mainSizer.Add(avcnBox,0) if len(RMCPdict['AveCN']): mainSizer.Add(GetAvcnSizer(),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) pottempBox = wx.BoxSizer(wx.HORIZONTAL) pottempBox.Add(wx.StaticText(G2frame.FRMC,label=' Potential temperature (K): '),0,WACV) pottempBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['Potentials'],'Pot. Temp.',xmin=0.,xmax=1000.,size=(50,25)),0,WACV) mainSizer.Add(pottempBox,0) bondpotBox = wx.BoxSizer(wx.HORIZONTAL) bondpotAdd = wx.Button(G2frame.FRMC,label='Add') bondpotAdd.Bind(wx.EVT_BUTTON,OnAddBondPot) bondpotBox.Add(bondpotAdd,0,WACV) bondpotBox.Add(wx.StaticText(G2frame.FRMC,label=' A-B stretch potential restraints, search range (%): '),0,WACV) bondpotBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['Potentials'],'Stretch search',xmin=0.,xmax=100.,size=(50,25)),0,WACV) mainSizer.Add(bondpotBox,0) if len(RMCPdict['Potentials']['Stretch']): mainSizer.Add(GetBondSizer(),0) angpotBox = wx.BoxSizer(wx.HORIZONTAL) angpotAdd = wx.Button(G2frame.FRMC,label='Add') angpotAdd.Bind(wx.EVT_BUTTON,OnAddAnglePot) angpotBox.Add(angpotAdd,0,WACV) angpotBox.Add(wx.StaticText(G2frame.FRMC,label=' A-B-C angle potential restraints, search range (%): '),0,WACV) angpotBox.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['Potentials'],'Angle search',xmin=0.,xmax=100.,size=(50,25)),0,WACV) mainSizer.Add(angpotBox,0) if len(RMCPdict['Potentials']['Angles']): mainSizer.Add(GetAngleSizer(),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' Select data:'),0) histograms = data['Histograms'] histNames = list(histograms.keys()) mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' Select one histogram for Bragg processing:'),0) histoSizer = wx.BoxSizer(wx.HORIZONTAL) histo = wx.ComboBox(G2frame.FRMC,choices=histNames,style=wx.CB_DROPDOWN|wx.TE_READONLY) if RMCPdict['histogram'][0] == '': RMCPdict['histogram'][0] = histo.GetStringSelection() histo.SetStringSelection(RMCPdict['histogram'][0]) histo.Bind(wx.EVT_COMBOBOX,OnHisto) histoSizer.Add(histo,0,WACV) histoSizer.Add(wx.StaticText(G2frame.FRMC,label=' Weight '),0,WACV) histoSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['histogram'],1,xmin=0.,xmax=10000.,size=(50,25)),0,WACV) mainSizer.Add(histoSizer,0) samSizer = wx.BoxSizer(wx.HORIZONTAL) samSize = wx.CheckBox(G2frame.FRMC,label=' Use size broadening?') samSize.SetValue(RMCPdict['UseSampBrd'][0]) samSize.Bind(wx.EVT_CHECKBOX,OnSize) strain = wx.CheckBox(G2frame.FRMC,label=' Use mustrain broadening?') strain.SetValue(RMCPdict['UseSampBrd'][1]) strain.Bind(wx.EVT_CHECKBOX,OnStrain) samSizer.Add(samSize,0,WACV) samSizer.Add(strain,0,WACV) fitscale = wx.CheckBox(G2frame.FRMC,label=' Fit scale factors?') fitscale.SetValue(RMCPdict['FitScale']) fitscale.Bind(wx.EVT_CHECKBOX,OnFitScale) samSizer.Add(fitscale,0,WACV) mainSizer.Add(samSizer,0) mainSizer.Add(FileSizer(RMCPdict)) return mainSizer def PDFfitSizer(data): mainSizer = wx.BoxSizer(wx.VERTICAL) Indx = {} def PDFParmSizer(): def OnShape(event): RMCPdict['shape'] = shape.GetValue() wx.CallAfter(UpdateRMC,G2frame,data) parmSizer = wx.FlexGridSizer(3,6,5,5) Names = ['delta1','delta2','sratio','rcut','spdiameter'] Names2 = ['stepcut',] for name in Names: def OnRefine(event): Obj = event.GetEventObject() name = Indx[Obj.GetId()] RMCPdict[name][1] = not RMCPdict[name][1] if name == 'spdiameter' and RMCPdict.get('shape','sphere') != 'sphere': pass else: parmSizer.Add(wx.StaticText(G2frame.FRMC,label=name),0,WACV) if name == 'rcut': parmSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,name,xmin=0.,size=(70,25)),0,WACV) parmSizer.Add((5,5)) continue parmSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict[name],0,xmin=0.,size=(70,25)),0,WACV) refine = wx.CheckBox(G2frame.FRMC,label='Refine') refine.SetValue(RMCPdict[name][1]) refine.Bind(wx.EVT_CHECKBOX,OnRefine) Indx[refine.GetId()] = name parmSizer.Add(refine,0,WACV) parmSizer.Add(wx.StaticText(G2frame.FRMC,label=' Shape'),0,WACV) shape = wx.ComboBox(G2frame.FRMC,choices=['sphere','stepcut'],style=wx.CB_DROPDOWN|wx.TE_READONLY) shape.SetStringSelection(RMCPdict.get('shape','sphere')) shape.Bind(wx.EVT_COMBOBOX,OnShape) parmSizer.Add(shape,0,WACV) if RMCPdict.get('shape','sphere') == 'stepcut': for name in Names2: parmSizer.Add(wx.StaticText(G2frame.FRMC,label=name),0,WACV) parmSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict,name,xmin=0.,size=(70,25)),0,WACV) return parmSizer def OnSpaceGroup(event): # try a lookup on the user-supplied name SpcGp = G2phsG.GetSpGrpfromUser(G2frame.FRMC,SpGrp) SGErr,SGData = G2spc.SpcGroup(SpcGp) if SGErr: text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous'] SGTxt.SetLabel(RMCPdict.get('Target SpGrp','P 1')) msg = 'Space Group Error' Text = '\n'.join(text) wx.MessageBox(Text,caption=msg,style=wx.ICON_EXCLAMATION) else: text,table = G2spc.SGPrint(SGData) RMCPdict['SGData'] = SGData SGTxt.SetLabel(RMCPdict['SGData']['SpGrp']) msg = 'Target Space Group Information' G2G.SGMessageBox(G2frame.FRMC,msg,text,table).Show() G2spc.UpdateSytSym(data) def OnCellRef(event): RMCPdict['cellref'] = not RMCPdict['cellref'] def AtomSizer(): def OnSetVal(event): r,c = event.GetRow(),event.GetCol() if c > 0: strval = atmGrid.GetCellValue(r,c).strip() try: # if strval == '' or ('@' in strval and int(strval.split('@')[-1]) >= 20): if strval == '' or '@' in strval: RMCPdict['AtomConstr'][r][c+1] = strval else: raise ValueError except ValueError: atmGrid.SetCellValue(r,c,RMCPdict['AtomConstr'][r][c+1]) wx.MessageBox('ERROR - atom constraints must be blank or have "@n" with n >= 20', style=wx.ICON_ERROR) wx.CallAfter(UpdateRMC,G2frame,data) def OnUisoRefine(event): RMCPdict['UisoRefine'] = uiso.GetValue() nextP = 80 oType = '' oName = '' for atom in RMCPdict['AtomConstr']: if RMCPdict['UisoRefine'] == 'No': atom[6] = '' elif 'same' in RMCPdict['UisoRefine']: atom[6] = '@81' RMCPdict['AtomVar']['@81'] = 0.005 elif 'type' in RMCPdict['UisoRefine']: if atom[1] != oType: oType = atom[1] nextP += 1 atom[6] = '@%d'%nextP RMCPdict['AtomVar']['@%d'%nextP] = 0.005 elif 'parent' in RMCPdict['UisoRefine']: if atom[0] != oName: oName = atom[0] nextP += 1 atom[6] = '@%d'%nextP RMCPdict['AtomVar']['@%d'%nextP] = 0.005 wx.CallAfter(UpdateRMC,G2frame,data) atmSizer = wx.BoxSizer(wx.VERTICAL) atmSizer.Add(wx.StaticText(G2frame.FRMC,label=' Atom Constraints; enter as e.g. "@n" or "0.5-@n"; n>=20 && "@n" should be at end')) uisoSizer = wx.BoxSizer(wx.HORIZONTAL) uisoSizer.Add(wx.StaticText(G2frame.FRMC,label=' Refine Uiso? '),0,WACV) uiso = wx.ComboBox(G2frame.FRMC,choices=['No','by type','by parent name','all same'],style=wx.CB_DROPDOWN|wx.TE_READONLY) uiso.SetValue(RMCPdict['UisoRefine']) uiso.Bind(wx.EVT_COMBOBOX,OnUisoRefine) uisoSizer.Add(uiso,0,WACV) atmSizer.Add(uisoSizer) table = [item[1:] for item in RMCPdict['AtomConstr']] addCol = False if len(RMCPdict['AtomConstr'][0]) > 6: addCol = True colLabels = ['Type','x constraint','y constraint','z constraint','frac constr','Uiso constr'] rowLabels = [item[0] for item in RMCPdict['AtomConstr']] Types = 6*[wg.GRID_VALUE_STRING,] if addCol: colLabels += ['sym opr',] Types = 7*[wg.GRID_VALUE_STRING,] atmTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types) atmGrid = G2G.GSGrid(G2frame.FRMC) atmGrid.SetTable(atmTable, True,useFracEdit=False) atmGrid.AutoSizeColumns(True) atmGrid.Bind(wg.EVT_GRID_CELL_CHANGED, OnSetVal) atmSizer.Add(atmGrid) return atmSizer def AtomVarSizer(): atomVarSizer = wx.FlexGridSizer(0,8,5,5) for item in RMCPdict['AtomVar']: atomVarSizer.Add(wx.StaticText(G2frame.FRMC,label=item),0,WACV) atomVarSizer.Add(G2G.ValidatedTxtCtrl(G2frame.FRMC,RMCPdict['AtomVar'], item,xmin=-3.,xmax=3.,size=(70,25)),0,WACV) return atomVarSizer txt = wx.StaticText(G2frame.FRMC,label= 'For use of PDFfit, please cite: '+G2G.GetCite('PDFfit2')) txt.Wrap(500) mainSizer.Add(txt) mainSizer.Add((5,5)) if 'PDFfit' not in data['RMC'] or not data['RMC']['PDFfit'] or 'delta1' not in data['RMC']['PDFfit']: if 'PDFfit' not in data['RMC']: data['RMC']['PDFfit'] = {} metadata = {'title':'none','date':str(time.ctime()),'temperature':'300K','doping':0} files = {'Neutron real space data; G(r): ':['Select',0.05,'G(r)','RMC',], 'Xray real space data; G(r): ':['Select',0.01,'G(r)','RMC',],} data['RMC']['PDFfit'].update({'files':files,'ReStart':[False,False],'metadata':metadata, 'delta1':[0.,False],'delta2':[0.,False],'spdiameter':[0.,False],'refinement':'normal', 'sratio':[1.,False],'rcut':0.0,'stepcut':0.0,'shape':'sphere','cellref':False, 'SeqDataType':'X','SeqCopy':True,'SeqReverse':False, 'Xdata':{'dscale':[1.0,False],'Datarange':[0.,30.],'Fitrange':[0.,30.],'qdamp':[0.03,False],'qbroad':[0.,False]}, 'Ndata':{'dscale':[1.0,False],'Datarange':[0.,30.],'Fitrange':[0.,30.],'qdamp':[0.03,False],'qbroad':[0.,False]},}) RMCPdict = data['RMC']['PDFfit'] #patch if 'AtomConstr' not in RMCPdict: #keep this one RMCPdict['AtomConstr'] = [] if 'AtomVar' not in RMCPdict: RMCPdict['AtomVar'] = {} if 'SGData' not in RMCPdict: RMCPdict['SGData'] = G2spc.SpcGroup('P 1')[1] if 'refinement' not in RMCPdict: RMCPdict['refinement'] = 'normal' if 'cellref' not in RMCPdict: RMCPdict['cellref'] = False if 'metadata' not in RMCPdict: RMCPdict['metadata'] = {'title':'none','date':str(time.ctime()),'temperature':'300K','doping':0} if 'SeqDataType' not in RMCPdict: RMCPdict['SeqDataType'] = 'X' if 'SeqCopy' not in RMCPdict: RMCPdict['SeqCopy'] = False RMCPdict['SeqReverse'] = False if 'UisoRefine' not in RMCPdict: RMCPdict['UisoRefine'] = 'No' #end patch Atoms = data['Atoms'] cx,ct,cs,ci = G2mth.getAtomPtrs(data) if not RMCPdict['AtomConstr']: for atom in Atoms: RMCPdict['AtomConstr'].append([atom[ct-1],atom[ct],'','','','','']) else: #update name/type changes for iatm,atom in enumerate(Atoms): RMCPdict['AtomConstr'][iatm][:2] = atom[ct-1:ct+1] mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' Enter metadata items:'),0) mainSizer.Add(GetMetaSizer(RMCPdict,['title','date','temperature','doping']),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) SgSizer = wx.BoxSizer(wx.HORIZONTAL) SgSizer.Add(wx.StaticText(G2frame.FRMC,label=' Target space group: '),0,WACV) mainSizer.Add(wx.StaticText(G2frame.FRMC,label='PDFfit phase structure parameters:')) SpGrp = RMCPdict['SGData']['SpGrp'] SGTxt = wx.Button(G2frame.FRMC,wx.ID_ANY,SpGrp,size=(100,-1)) SGTxt.Bind(wx.EVT_BUTTON,OnSpaceGroup) SgSizer.Add(SGTxt,0,WACV) mainSizer.Add(SgSizer) cellref = wx.CheckBox(G2frame.FRMC,label=' Refine unit cell?') cellref.SetValue(RMCPdict['cellref']) cellref.Bind(wx.EVT_CHECKBOX,OnCellRef) mainSizer.Add(cellref) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(wx.StaticText(G2frame.FRMC,label='PDFfit atom parameters:')) mainSizer.Add(AtomSizer()) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(wx.StaticText(G2frame.FRMC,label='PDFfit starting atom variables:')) G2pwd.GetPDFfitAtomVar(data,RMCPdict) mainSizer.Add(AtomVarSizer()) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(wx.StaticText(G2frame.FRMC,label=' PDFfit phase profile coefficients:')) mainSizer.Add(PDFParmSizer(),0) G2G.HorizontalLine(mainSizer,G2frame.FRMC) mainSizer.Add(FileSizer(RMCPdict)) return mainSizer ####start of UpdateRMC G2frame.GetStatusBar().SetStatusText('',1) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_ATOMSRMC,False) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_SUPERRMC,False) if G2frame.RMCchoice == 'RMCProfile': G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_SETUPRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_RUNRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_VIEWRMC,True) #G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_STOPRMC,False) elif G2frame.RMCchoice == 'fullrmc': G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_SETUPRMC,False) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_RUNRMC,False) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_VIEWRMC,False) #G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_STOPRMC,False) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_ATOMSRMC,True) G2frame.dataWindow.FRMCDataEdit.Enable(G2G.wxID_SUPERRMC,True) try: if G2frame.FRMC.GetSizer(): G2frame.FRMC.GetSizer().Clear(True) except: #wxAssertionError from C++ pass mainSizer = wx.BoxSizer(wx.VERTICAL) if not len(data['Atoms']): mainSizer.Add(wx.StaticText(G2frame.FRMC,label='No atoms found - PDF fitting not possible')) else: runFile = ' ' choice = ['RMCProfile','fullrmc','PDFfit'] topSizer = wx.BoxSizer(wx.HORIZONTAL) RMCsel = wx.RadioBox(G2frame.FRMC,-1,' Select RMC method:',choices=choice) RMCsel.SetStringSelection(G2frame.RMCchoice) RMCsel.Bind(wx.EVT_RADIOBOX, OnRMCselect) topSizer.Add(RMCsel,0) topSizer.Add((20,0)) txt = wx.StaticText(G2frame.FRMC, label='NB: if you change any of the entries below, you must redo the Operations/Setup RMC step above to apply them before doing Operations/Execute') txt.Wrap(250) topSizer.Add(txt,0) mainSizer.Add(topSizer,0) RMCmisc['RMCnote'] = wx.StaticText(G2frame.FRMC) mainSizer.Add(RMCmisc['RMCnote']) G2G.HorizontalLine(mainSizer,G2frame.FRMC) if G2frame.RMCchoice == 'fullrmc': RMCPdict = data['RMC']['fullrmc'] mainSizer.Add(fullrmcSizer(RMCPdict)) elif G2frame.RMCchoice == 'RMCProfile': RMCPdict = data['RMC']['RMCProfile'] mainSizer.Add(RMCProfileSizer(RMCPdict)) else: #PDFfit mainSizer.Add(PDFfitSizer(data)) topSizer = G2frame.dataWindow.topBox topSizer.Clear(True) parent = G2frame.dataWindow.topPanel lbl= f"PDF fitting options {data['General']['Name']!r}"[:60] topSizer.Add(wx.StaticText(parent,label=lbl),0,WACV) topSizer.Add((-1,-1),1,wx.EXPAND) topSizer.Add(G2G.HelpButton(parent,helpIndex=G2frame.dataWindow.helpKey)) wx.CallAfter(G2frame.dataWindow.SetDataSize) G2phsG.SetPhaseWindow(G2frame.FRMC,mainSizer) if G2frame.RMCchoice == 'PDFfit' and not G2phsG.checkPDFfit(G2frame): RMCmisc['RMCnote'].SetLabel('PDFfit may not be installed or operational') elif G2frame.RMCchoice == 'fullrmc' and G2pwd.findfullrmc() is None: msg = ('The fullrmc Python image is not found.'+ ' Do you want it installed for you from '+ 'https://github.com/bachiraoun/fullrmc/tree/master/standalones?'+ '\n\n40-50 Mb (download times vary)') dlg = wx.MessageDialog(G2frame,msg,'Install fullrmc',wx.YES|wx.NO) try: dlg.CenterOnParent() result = dlg.ShowModal() finally: dlg.Destroy() if result == wx.ID_YES: wx.BeginBusyCursor() G2pwd.fullrmcDownload() wx.EndBusyCursor() else: RMCmisc['RMCnote'].SetLabel('Note that fullrmc is not installed or was not located')