Changeset 4421
- Timestamp:
- May 16, 2020 8:55:12 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIIconstrGUI.py
r4400 r4421 22 22 import wx.grid as wg 23 23 import wx.lib.scrolledpanel as wxscroll 24 import wx.lib.gridmovers as gridmovers 24 25 import random as ran 25 26 import numpy as np … … 40 41 import GSASIIspc as G2spc 41 42 import GSASIIpy3 as G2py3 43 import GSASIIphsGUI as G2phG 44 import GSASIIscriptable as G2sc 42 45 VERY_LIGHT_GREY = wx.Colour(235,235,235) 43 46 WACV = wx.ALIGN_CENTER_VERTICAL 47 48 class DragableRBGrid(wg.Grid): 49 '''Simple grid implentation for display of rigid body positions. 50 51 :param parent: frame or panel where grid will be placed 52 :param dict rb: dict with atom labels, types and positions 53 :param function onChange: a callback used every time a value in 54 rb is changed. 55 ''' 56 def __init__(self, parent, rb, onChange=None): 57 #wg.Grid.__init__(self, parent, wx.ID_ANY,size=(-1,200)) 58 wg.Grid.__init__(self, parent, wx.ID_ANY) 59 self.SetTable(RBDataTable(rb,onChange), True) 60 # Enable Row moving 61 gridmovers.GridRowMover(self) 62 self.Bind(gridmovers.EVT_GRID_ROW_MOVE, self.OnRowMove, self) 63 self.SetColSize(0, 60) 64 self.SetColSize(1, 35) 65 self.SetColSize(5, 40) 66 for r in range(len(rb['RBlbls'])): 67 self.SetReadOnly(r,0,isReadOnly=True) 68 self.SetCellEditor(r,2, wg.GridCellFloatEditor()) 69 self.SetCellEditor(r,3, wg.GridCellFloatEditor()) 70 self.SetCellEditor(r,4, wg.GridCellFloatEditor()) 71 72 def OnRowMove(self,evt): 73 'called when a row move needs to take place' 74 frm = evt.GetMoveRow() # Row being moved 75 to = evt.GetBeforeRow() # Before which row to insert 76 self.GetTable().MoveRow(frm,to) 77 78 def completeEdits(self): 79 'complete any outstanding edits' 80 if self.IsCellEditControlEnabled(): # complete any grid edits in progress 81 #if GSASIIpath.GetConfigValue('debug'): print ('Completing grid edit') 82 self.SaveEditControlValue() 83 self.HideCellEditControl() 84 self.DisableCellEditControl() 85 86 class RBDataTable(wg.GridTableBase): 87 '''A Table to support :class:`DragableRBGrid` 88 ''' 89 def __init__(self,rb,onChange): 90 wg.GridTableBase.__init__(self) 91 self.colLabels = ['Label','Type','x','y','z','Select'] 92 self.coords = rb['RBcoords'] 93 self.labels = rb['RBlbls'] 94 self.types = rb['RBtypes'] 95 self.index = rb['RBindex'] 96 self.select = rb['RBselection'] 97 self.onChange = onChange 98 99 # required methods 100 def GetNumberRows(self): 101 return len(self.labels) 102 def GetNumberCols(self): 103 return len(self.colLabels) 104 def IsEmptyCell(self, row, col): 105 return False 106 def GetValue(self, row, col): 107 row = self.index[row] 108 if col == 0: 109 return self.labels[row] 110 elif col == 1: 111 return self.types[row] 112 elif col < 5: 113 return '{:.5f}'.format(self.coords[row][col-2]) 114 elif col == 5: 115 return self.select[row] 116 def SetValue(self, row, col, value): 117 row = self.index[row] 118 if col == 0: 119 self.labels[row] = value 120 elif col == 1: 121 self.types[row] = value 122 elif col < 5: 123 self.coords[row][col-2] = float(value) 124 elif col == 5: 125 self.select[row] = value 126 if self.onChange: 127 self.onChange() 128 # implement boolean for selection 129 def GetTypeName(self, row, col): 130 if col==5: 131 return wg.GRID_VALUE_BOOL 132 else: 133 return wg.GRID_VALUE_STRING 134 def CanGetValueAs(self, row, col, typeName): 135 if col==5 and typeName != wg.GRID_VALUE_BOOL: 136 return False 137 return True 138 139 # Display column & row labels 140 def GetColLabelValue(self, col): 141 return self.colLabels[col] 142 def GetRowLabelValue(self,row): 143 return str(row+1) 144 145 # Implement "row movement" by updating the pointer array 146 def MoveRow(self,frm,to): 147 grid = self.GetView() 148 if grid: 149 move = self.index[frm] 150 del self.index[frm] 151 if frm > to: 152 self.index.insert(to,move) 153 else: 154 self.index.insert(to-1,move) 155 156 # Notify the grid 157 grid.BeginBatch() 158 msg = wg.GridTableMessage( 159 self, wg.GRIDTABLE_NOTIFY_ROWS_DELETED, frm, 1 160 ) 161 grid.ProcessTableMessage(msg) 162 msg = wg.GridTableMessage( 163 self, wg.GRIDTABLE_NOTIFY_ROWS_INSERTED, to, 1 164 ) 165 grid.ProcessTableMessage(msg) 166 grid.EndBatch() 167 if self.onChange: 168 self.onChange() 169 170 def MakeDrawAtom(data,atom): 171 'Convert atom to format needed to draw it' 172 generalData = data['General'] 173 if generalData['Type'] in ['nuclear','faulted',]: 174 atomInfo = [atom[:2]+atom[3:6]+['1',]+['vdW balls',]+ 175 ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0] 176 ct,cs = [1,8] #type & color 177 atNum = generalData['AtomTypes'].index(atom[ct]) 178 atomInfo[cs] = list(generalData['Color'][atNum]) 179 return atomInfo 44 180 45 181 class ConstraintDialog(wx.Dialog): … … 1527 1663 #### Rigid bodies 1528 1664 ################################################################################ 1529 1665 resRBsel = None 1530 1666 def UpdateRigidBodies(G2frame,data): 1531 1667 '''Called when Rigid bodies tree item is selected. … … 1536 1672 'RBIds':{'Vector':[],'Residue':[]}}) #empty/bad dict - fill it 1537 1673 1538 global resList,r bId1674 global resList,resRBsel 1539 1675 Indx = {} 1540 1676 resList = [] … … 1562 1698 G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.VectorBodyMenu) 1563 1699 G2frame.Bind(wx.EVT_MENU, AddVectorRB, id=G2G.wxID_VECTORBODYADD) 1700 G2frame.Bind(wx.EVT_MENU, ExtractPhaseRB, id=G2G.wxID_VECTORBODYIMP) 1701 G2frame.Bind(wx.EVT_MENU, AddVectTrans, id=G2G.wxID_VECTORBODYEXTD) 1702 G2frame.Bind(wx.EVT_MENU, SaveVectorRB, id=G2G.wxID_VECTORBODYSAV) 1703 G2frame.Bind(wx.EVT_MENU, ReadVectorRB, id=G2G.wxID_VECTORBODYRD) 1564 1704 G2frame.Page = [page,'vrb'] 1565 1705 UpdateVectorRB() … … 1567 1707 G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.RigidBodyMenu) 1568 1708 G2frame.Bind(wx.EVT_MENU, AddResidueRB, id=G2G.wxID_RIGIDBODYADD) 1709 G2frame.Bind(wx.EVT_MENU, ExtractPhaseRB, id=G2G.wxID_RIGIDBODYIMP) 1569 1710 G2frame.Bind(wx.EVT_MENU, OnImportRigidBody, id=G2G.wxID_RIGIDBODYIMPORT) 1570 1711 G2frame.Bind(wx.EVT_MENU, OnSaveRigidBody, id=G2G.wxID_RIGIDBODYSAVE) 1571 1712 G2frame.Bind(wx.EVT_MENU, OnDefineTorsSeq, id=G2G.wxID_RESIDUETORSSEQ) #enable only if residue RBs exist? 1713 G2frame.Bind(wx.EVT_MENU, DumpVectorRB, id=G2G.wxID_RESBODYSAV) 1714 G2frame.Bind(wx.EVT_MENU, LoadVectorRB, id=G2G.wxID_RESBODYRD) 1572 1715 G2frame.Page = [page,'rrb'] 1573 1716 UpdateResidueRB() 1717 else: 1718 G2gd.SetDataMenuBar(G2frame) 1719 #G2frame.Page = [page,'rrb'] 1574 1720 1575 1721 def getMacroFile(macName): … … 1626 1772 SaveResidueRB() 1627 1773 1774 def DumpVectorRB(event): 1775 global resRBsel 1776 if resRBsel not in data['Residue']: 1777 return 1778 rbData = data['Residue'][resRBsel] 1779 pth = G2G.GetExportPath(G2frame) 1780 dlg = wx.FileDialog(G2frame, 'Choose file to save residue rigid body', 1781 pth, '', 'RRB files (*.resbody)|*.resbody', 1782 wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) 1783 try: 1784 if dlg.ShowModal() == wx.ID_OK: 1785 filename = dlg.GetPath() 1786 filename = os.path.splitext(filename)[0]+'.resbody' # set extension 1787 fp = open(filename,'w') 1788 fp.write('Name: '+rbData['RBname']+'\n') 1789 fp.write('atNames: ') 1790 for i in rbData['atNames']: 1791 fp.write(str(i)+" ") 1792 fp.write('\n') 1793 for item in rbData['rbSeq']: 1794 fp.write('rbSeq: ') 1795 fp.write('{:d} {:d} {:.1f}: '.format(*item[:3])) 1796 for num in item[3]: 1797 fp.write('{:d} '.format(num)) 1798 fp.write('\n') 1799 for i,sym in enumerate(rbData['rbTypes']): 1800 fp.write("{:3s}".format(sym)) 1801 fp.write('{:8.5f}{:9.5f}{:9.5f} ' 1802 .format(*rbData['rbXYZ'][i])) 1803 fp.write('\n') 1804 fp.close() 1805 print ('Vector rigid body saved to: '+filename) 1806 1807 finally: 1808 dlg.Destroy() 1809 1810 def LoadVectorRB(event): 1811 AtInfo = data['Residue']['AtInfo'] 1812 pth = G2G.GetExportPath(G2frame) 1813 dlg = wx.FileDialog(G2frame, 'Choose file to read vector rigid body', 1814 pth, '', 'RRB files (*.resbody)|*.resbody', 1815 wx.FD_OPEN) 1816 try: 1817 if dlg.ShowModal() == wx.ID_OK: 1818 filename = dlg.GetPath() 1819 filename = os.path.splitext(filename)[0]+'.resbody' # set extension 1820 fp = open(filename,'r') 1821 l = fp.readline().strip() 1822 if 'Name' not in l: 1823 fp.close() 1824 G2frame.ErrorDialog('Read Error', 1825 'File '+filename+' does not start with Name\nFirst line =' 1826 +l+'\ninvalid file',parent=G2frame) 1827 return 1828 name = l.split(':')[1].strip() 1829 line = fp.readline().strip().split(':')[1].split() 1830 atNames = [i for i in line] 1831 types = [] 1832 coords = [] 1833 l = fp.readline().strip() 1834 rbSeq = [] 1835 while 'rbSeq' in l: 1836 tag,vals,lst = l.split(':') 1837 seq = [] 1838 for t,v in zip((int,int,float),vals.split()): 1839 seq.append(t(v)) 1840 seq.append([]) 1841 for num in lst.split(): 1842 seq[-1].append(int(num)) 1843 rbSeq.append(seq) 1844 l = fp.readline().strip() 1845 while l: 1846 nums = l.strip().split() 1847 types.append(nums.pop(0)) 1848 t = types[-1] 1849 if t not in AtInfo: 1850 Info = G2elem.GetAtomInfo(t) 1851 AtInfo[t] = [Info['Drad'],Info['Color']] 1852 coords.append([float(nums.pop(0)) for j in range(3)]) 1853 l = fp.readline().strip() 1854 fp.close() 1855 else: 1856 return 1857 finally: 1858 dlg.Destroy() 1859 coords = np.array(coords) 1860 rbid = ran.randint(0,sys.maxsize) 1861 data['Residue'][rbid] = {'RBname':name, 1862 'rbXYZ': coords, 1863 'rbRef':[0,1,2,False], 1864 'rbTypes':types, 'atNames':atNames, 1865 'useCount':0, 1866 'rbSeq':rbSeq, 'SelSeq':[0,0],} 1867 data['RBIds']['Residue'].append(rbid) 1868 UpdateResidueRB() 1869 1628 1870 def AddVectorRB(event): 1871 'Create a new vector rigid body' 1629 1872 AtInfo = data['Vector']['AtInfo'] 1630 1873 dlg = G2G.MultiIntegerDialog(G2frame,'New Rigid Body',['No. atoms','No. translations'],[1,1]) 1631 1874 if dlg.ShowModal() == wx.ID_OK: 1632 1875 nAtoms,nTrans = dlg.GetValues() 1633 rb Id = ran.randint(0,sys.maxsize)1876 rbid = ran.randint(0,sys.maxsize) 1634 1877 vecMag = [1.0 for i in range(nTrans)] 1635 1878 vecRef = [False for i in range(nTrans)] … … 1638 1881 Info = G2elem.GetAtomInfo('C') 1639 1882 AtInfo['C'] = [Info['Drad'],Info['Color']] 1640 data['Vector'][rb Id] = {'RBname':'UNKRB','VectMag':vecMag,'rbXYZ':np.zeros((nAtoms,3)),1883 data['Vector'][rbid] = {'RBname':'UNKRB','VectMag':vecMag,'rbXYZ':np.zeros((nAtoms,3)), 1641 1884 'rbRef':[0,1,2,False],'VectRef':vecRef,'rbTypes':rbTypes,'rbVect':vecVal,'useCount':0} 1642 data['RBIds']['Vector'].append(rb Id)1885 data['RBIds']['Vector'].append(rbid) 1643 1886 dlg.Destroy() 1887 UpdateVectorRB() 1888 1889 def ExtractPhaseRB(event): 1890 'Extract a rigid body from a file with a phase' 1891 def SetupDrawing(atmData): 1892 '''Add the dicts needed for G2plt.PlotStructure to work to the 1893 reader .Phase object 1894 ''' 1895 generalData = atmData['General'] 1896 generalData['BondRadii'] = [] 1897 1898 G2phG.SetDrawingDefaults(atmData['Drawing']) 1899 atmData['Drawing'].update( 1900 {'oldxy':[0.,0.],'Quaternion':[0.,0.,0.,1.],'cameraPos':150., 1901 'viewDir':[0,0,1],'atomPtrs': [2, 1, 6, 17], 1902 }) 1903 atmData['Drawing']['showRigidBodies'] = False 1904 generalData['Map'] = {'MapType':False, 'rho':[]} 1905 generalData['AtomTypes'] = [] 1906 generalData['BondRadii'] = [] 1907 generalData['AngleRadii'] = [] 1908 generalData['vdWRadii'] = [] 1909 generalData['Color'] = [] 1910 generalData['Isotopes'] = {} 1911 generalData['Isotope'] = {} 1912 cx,ct,cs,cia = generalData['AtomPtrs'] 1913 generalData['Mydir'] = G2frame.dirname 1914 for iat,atom in enumerate(atmData['Atoms']): 1915 atom[ct] = atom[ct].lower().capitalize() #force elem symbol to standard form 1916 if atom[ct] not in generalData['AtomTypes'] and atom[ct] != 'UNK': 1917 Info = G2elem.GetAtomInfo(atom[ct]) 1918 if not Info: 1919 atom[ct] = 'UNK' 1920 continue 1921 atom[ct] = Info['Symbol'] # N.B. symbol might be changed by GetAtomInfo 1922 generalData['AtomTypes'].append(atom[ct]) 1923 generalData['Z'] = Info['Z'] 1924 generalData['Isotopes'][atom[ct]] = Info['Isotopes'] 1925 generalData['BondRadii'].append(Info['Drad']) 1926 generalData['AngleRadii'].append(Info['Arad']) 1927 generalData['vdWRadii'].append(Info['Vdrad']) 1928 if atom[ct] in generalData['Isotope']: 1929 if generalData['Isotope'][atom[ct]] not in generalData['Isotopes'][atom[ct]]: 1930 isotope = list(generalData['Isotopes'][atom[ct]].keys())[-1] 1931 generalData['Isotope'][atom[ct]] = isotope 1932 else: 1933 generalData['Isotope'][atom[ct]] = 'Nat. Abund.' 1934 if 'Nat. Abund.' not in generalData['Isotopes'][atom[ct]]: 1935 isotope = list(generalData['Isotopes'][atom[ct]].keys())[-1] 1936 generalData['Isotope'][atom[ct]] = isotope 1937 generalData['Color'].append(Info['Color']) 1938 if generalData['Type'] == 'magnetic': 1939 if len(landeg) < len(generalData['AtomTypes']): 1940 landeg.append(2.0) 1941 atmData['Drawing']['Atoms'] = [] 1942 for atom in atmData['Atoms']: 1943 atmData['Drawing']['Atoms'].append(MakeDrawAtom(atmData,atom)) 1944 1945 def onCancel(event,page=0): 1946 'complete or bail out from RB define, cleaning up' 1947 G2frame.rbBook.DeletePage(G2frame.rbBook.FindPage(pagename)) 1948 G2frame.rbBook.SetSelection(page) 1949 1950 def Page1(): 1951 '''Show the GUI for first stage of the rigid body with all atoms in 1952 phase in crystal coordinates. Select the atoms to go onto the 1953 next stage 1954 ''' 1955 def ShowSelection(selections): 1956 'respond to change in atom selections' 1957 ct,cs = [1,8] 1958 generalData = rd.Phase['General'] 1959 for i,atom in enumerate(rd.Phase['Drawing']['Atoms']): 1960 if i in selections: 1961 factor = 1 1962 else: 1963 factor = 2.5 1964 atNum = generalData['AtomTypes'].index(atom[ct]) 1965 atom[cs] = list(np.array(generalData['Color'][atNum])//factor) 1966 draw(*drawArgs) 1967 def onPage1OK(event): 1968 '1st section has been completed, move onto next' 1969 G2frame.G2plotNB.Delete(rd.Phase['General']['Name']) 1970 GetCoords(atmsel) 1971 Page2() 1972 1973 SetupDrawing(rd.Phase) # add information to reader object to allow plotting 1974 atomlist = [atom[0] for atom in rd.Phase['Atoms']] 1975 atmsel = list(range(len(rd.Phase['Atoms']))) 1976 # broken -- # why no bonds? 1977 #for atm in rd.Phase['Drawing']['Atoms']: 1978 # atm[6] = 'balls & sticks' 1979 1980 draw,drawArgs = G2plt.PlotStructure(G2frame,rd.Phase,True) 1981 ShowSelection(atmsel) 1982 1983 if G2frame.rbBook.FindPage(pagename) is not None: 1984 G2frame.rbBook.DeletePage(G2frame.rbBook.FindPage(pagename)) 1985 1986 RBImp = wx.ScrolledWindow(G2frame.rbBook) 1987 RBImpPnl = wx.Panel(RBImp) 1988 G2frame.rbBook.AddPage(RBImp,pagename) 1989 G2frame.rbBook.SetSelection(G2frame.rbBook.FindPage(pagename)) 1990 1991 mainSizer = G2G.G2MultiChoiceWindow(RBImpPnl, 1992 'Select atoms to import', 1993 atomlist,atmsel,OnChange=ShowSelection) 1994 1995 # OK/Cancel buttons 1996 btnsizer = wx.StdDialogButtonSizer() 1997 OKbtn = wx.Button(RBImpPnl, wx.ID_OK, 'Continue') 1998 OKbtn.SetDefault() 1999 btnsizer.AddButton(OKbtn) 2000 OKbtn.Bind(wx.EVT_BUTTON,onPage1OK) 2001 btn = wx.Button(RBImpPnl, wx.ID_CANCEL) 2002 btn.Bind(wx.EVT_BUTTON,onCancel) 2003 btnsizer.AddButton(btn) 2004 btnsizer.Realize() 2005 mainSizer.Add(btnsizer,0,wx.ALIGN_CENTER,50) 2006 2007 RBImpPnl.SetSizer(mainSizer,True) 2008 2009 mainSizer.Layout() 2010 Size = mainSizer.GetMinSize() 2011 Size[0] += 40 2012 Size[1] = max(Size[1],G2frame.GetSize()[1]-200) + 20 2013 RBImpPnl.SetSize(Size) 2014 RBImp.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1) 2015 RBImp.Scroll(0,0) 2016 2017 def Page2(): 2018 '''Show the GUI for the second stage, where selected atoms are 2019 now in Cartesian space, manipulate the axes and export selected 2020 atoms to a vector or residue rigid body. 2021 ''' 2022 def UpdateDraw(event=None): 2023 'Called when info changes in grid, replots' 2024 UpdateVectorBody(rbData) 2025 DrawCallback() 2026 2027 def onSetAll(event): 2028 'Set all atoms as selected' 2029 for i in range(len(rd.Phase['RBselection'])): 2030 rd.Phase['RBselection'][i] = True 2031 grid.ForceRefresh() 2032 UpdateDraw() 2033 2034 def onToggle(event): 2035 'Toggles selection state for all atoms' 2036 grid.completeEdits() 2037 for i in range(len(rd.Phase['RBselection'])): 2038 rd.Phase['RBselection'][i] = not rd.Phase['RBselection'][i] 2039 grid.ForceRefresh() 2040 UpdateDraw() 2041 2042 def onSetOrigin(event): 2043 'Resets origin to midpoint between all selected atoms' 2044 grid.completeEdits() 2045 center = np.array([0.,0.,0.]) 2046 count = 0 2047 for i in range(len(rd.Phase['RBselection'])): 2048 if rd.Phase['RBselection'][i]: 2049 count += 1 2050 center += rd.Phase['RBcoords'][i] 2051 if count: 2052 rd.Phase['RBcoords'] -= center/count 2053 grid.ForceRefresh() 2054 UpdateDraw() 2055 2056 def onSetX(event): 2057 grid.completeEdits() 2058 center = np.array([0.,0.,0.]) 2059 count = 0 2060 for i in range(len(rd.Phase['RBselection'])): 2061 if rd.Phase['RBselection'][i]: 2062 count += 1 2063 center += rd.Phase['RBcoords'][i] 2064 if not count: 2065 return 2066 XP = center/count 2067 if np.sqrt(sum(XP**2)) < 0.1: 2068 G2G.G2MessageBox(G2frame, 2069 'The selected atom(s) are too close to the origin', 2070 'near origin') 2071 return 2072 XP /= np.sqrt(np.sum(XP**2)) 2073 Z = np.array((0,0,1.)) 2074 YP = np.cross(Z,XP) 2075 ZP = np.cross(XP,YP) 2076 trans = np.array((XP,YP,ZP)) 2077 # update atoms in place 2078 rd.Phase['RBcoords'][:] = np.inner(trans,rd.Phase['RBcoords']).T 2079 grid.ForceRefresh() 2080 UpdateDraw() 2081 2082 def onSetPlane(event): 2083 '''Compute least-squares plane for selected atoms; 2084 move atoms so that LS plane aligned with x-y plane, 2085 with minimum required change to x 2086 ''' 2087 grid.completeEdits() 2088 #X,Y,Z = rd.Phase['RBcoords'][rd.Phase['RBselection']].T 2089 XYZ = rd.Phase['RBcoords'][rd.Phase['RBselection']] 2090 Z = copy.copy(XYZ[:,2]) 2091 if len(Z) < 3: 2092 G2G.G2MessageBox(G2frame,'A plane requires three or more atoms', 2093 'Need more atoms') 2094 return 2095 XY0 = copy.copy(XYZ) 2096 XY0[:,2] = 1 2097 # solve for ax + bx + z + c = 0 or equivalently ax + bx + c = -z 2098 try: 2099 (a,b,c), resd, rank, sing = nl.lstsq(XY0, -Z) 2100 except: 2101 G2G.G2MessageBox(G2frame, 2102 'Error computing plane; are atoms in a line?', 2103 'Computation error') 2104 return 2105 # new coordinate system is z' (zp, normal to plane = [a,b,1]), 2106 # y' = z' cross x (YP, = [0,1,-b]) 2107 # x' = (z' cross x) cross z' 2108 # this puts XP as close as possible to X with XP & YP in plane 2109 ZP = np.array([a,b,1]) 2110 ZP /= np.sqrt(np.sum(ZP**2)) 2111 YP = np.array([0,1,-b]) 2112 YP /= np.sqrt(np.sum(YP**2)) 2113 XP = np.cross(YP,ZP) 2114 trans = np.array((XP,YP,ZP)) 2115 # update atoms in place 2116 rd.Phase['RBcoords'][:] = np.inner(trans,rd.Phase['RBcoords']).T 2117 grid.ForceRefresh() 2118 UpdateDraw() 2119 2120 def onAddVector(event): 2121 '''Adds selected atoms as a new vector rigid body. 2122 Closes out the importer tab when done. 2123 ''' 2124 grid.completeEdits() 2125 rb = MakeVectorBody(os.path.split(filename)[1]) 2126 UpdateVectorBody(rb,True) 2127 if len(rb['rbTypes']) < 3: return # must have at least 3 atoms 2128 rbid = ran.randint(0,sys.maxsize) 2129 data['Vector'][rbid] = rb 2130 data['RBIds']['Vector'].append(rbid) 2131 AtInfo = data['Vector']['AtInfo'] 2132 for t in rb['rbTypes']: 2133 if t in data['Vector']['AtInfo']: continue 2134 Info = G2elem.GetAtomInfo(t) 2135 data['Vector']['AtInfo'][t] = [Info['Drad'],Info['Color']] 2136 G2frame.G2plotNB.Delete('Rigid body') 2137 onCancel(event,0) 2138 2139 def onAddResidue(event): 2140 '''Adds selected atoms as a new residue rigid body. 2141 Closes out the importer tab when done. 2142 ''' 2143 grid.completeEdits() 2144 name = os.path.split(filename)[1] 2145 rbXYZ = [] 2146 rbTypes = [] 2147 atNames = [] 2148 for i in rd.Phase['RBindex']: 2149 if rd.Phase['RBselection'][i]: 2150 rbXYZ.append(rd.Phase['RBcoords'][i]) 2151 rbTypes.append(rd.Phase['RBtypes'][i]) 2152 atNames.append(rd.Phase['RBlbls'][i]) 2153 if len(rbTypes) < 3: return # must have at least 3 atoms 2154 rbXYZ = np.array(rbXYZ) 2155 rbid = ran.randint(0,sys.maxsize) 2156 data['Residue'][rbid] = {'RBname':name,'rbXYZ':rbXYZ, 2157 'rbTypes':rbTypes,'atNames':atNames,'rbRef':[0,1,2,False], 2158 'rbSeq':[],'SelSeq':[0,0],'useCount':0} 2159 data['RBIds']['Residue'].append(rbid) 2160 AtInfo = data['Residue']['AtInfo'] 2161 for t in rbTypes: 2162 if t in data['Residue']['AtInfo']: continue 2163 Info = G2elem.GetAtomInfo(t) 2164 data['Residue']['AtInfo'][t] = [Info['Drad'],Info['Color']] 2165 2166 print ('Rigid body added') 2167 G2frame.G2plotNB.Delete('Rigid body') 2168 onCancel(event,1) 2169 2170 if G2frame.rbBook.FindPage(pagename) is not None: 2171 G2frame.rbBook.DeletePage(G2frame.rbBook.FindPage(pagename)) 2172 RBImp = wx.ScrolledWindow(G2frame.rbBook) 2173 RBImpPnl = wx.Panel(RBImp) 2174 G2frame.rbBook.AddPage(RBImp,pagename) 2175 G2frame.rbBook.SetSelection(G2frame.rbBook.FindPage(pagename)) 2176 generalData = rd.Phase['General'] 2177 AtInfo = {} 2178 ct = 1 2179 for t in rd.Phase['RBtypes']: 2180 if t in AtInfo: continue 2181 Info = G2elem.GetAtomInfo(t) 2182 AtInfo[t] = [Info['Drad'],Info['Color']] 2183 plotDefaults = {'oldxy':[0.,0.],'Quaternion':[0.,0.,0.,1.],'cameraPos':30.,'viewDir':[0,0,1],} 2184 2185 rd.Phase['RBindex'] = list(range(len(rd.Phase['RBtypes']))) 2186 rd.Phase['RBselection'] = len(rd.Phase['RBtypes']) * [True] 2187 rbData = MakeVectorBody() 2188 DrawCallback = G2plt.PlotRigidBody(G2frame,'Vector', 2189 AtInfo,rbData,plotDefaults) 2190 2191 mainSizer = wx.BoxSizer(wx.HORIZONTAL) 2192 gridSizer = wx.BoxSizer(wx.VERTICAL) 2193 grid = DragableRBGrid(RBImpPnl,rd.Phase,UpdateDraw) 2194 gridSizer.Add(grid) 2195 gridSizer.Add( 2196 wx.StaticText(RBImpPnl,wx.ID_ANY,'Reorder atoms by dragging'), 2197 0,wx.ALL) 2198 mainSizer.Add(gridSizer) 2199 mainSizer.Add((5,5)) 2200 btnSizer = wx.BoxSizer(wx.VERTICAL) 2201 btn = wx.Button(RBImpPnl, wx.ID_OK, 'Set All') 2202 btn.Bind(wx.EVT_BUTTON,onSetAll) 2203 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2204 btn = wx.Button(RBImpPnl, wx.ID_OK, 'Toggle') 2205 btn.Bind(wx.EVT_BUTTON,onToggle) 2206 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2207 btnSizer.Add((-1,15)) 2208 btnSizer.Add( 2209 wx.StaticText(RBImpPnl,wx.ID_ANY,'Reorient using selected\natoms...'), 2210 0,wx.ALL) 2211 btnSizer.Add((-1,5)) 2212 btn = wx.Button(RBImpPnl, wx.ID_OK, 'Set origin') 2213 btn.Bind(wx.EVT_BUTTON,onSetOrigin) 2214 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2215 btn = wx.Button(RBImpPnl, wx.ID_OK, 'Place in xy plane') 2216 btn.Bind(wx.EVT_BUTTON,onSetPlane) 2217 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2218 btn = wx.Button(RBImpPnl, wx.ID_OK, 'Define selection as X') 2219 btn.Bind(wx.EVT_BUTTON,onSetX) 2220 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2221 btnSizer.Add((-1,15)) 2222 btnSizer.Add( 2223 wx.StaticText(RBImpPnl,wx.ID_ANY,'Use selected atoms to\ncreate...'), 2224 0,wx.ALL) 2225 btnSizer.Add((-1,5)) 2226 btn = wx.Button(RBImpPnl, wx.ID_OK, 'a Vector Body') 2227 btn.Bind(wx.EVT_BUTTON,onAddVector) 2228 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2229 btn = wx.Button(RBImpPnl, wx.ID_OK, 'a Residue Body') 2230 btn.Bind(wx.EVT_BUTTON,onAddResidue) 2231 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2232 btn = wx.Button(RBImpPnl, wx.ID_CANCEL) 2233 btn.Bind(wx.EVT_BUTTON,onCancel) 2234 btnSizer.Add((-1,10)) 2235 btnSizer.Add(btn,0,wx.ALIGN_CENTER) 2236 2237 mainSizer.Add(btnSizer) 2238 RBImpPnl.SetSizer(mainSizer,True) 2239 mainSizer.Layout() 2240 Size = mainSizer.GetMinSize() 2241 Size[0] += 40 2242 Size[1] = max(Size[1],G2frame.GetSize()[1]-200) + 20 2243 RBImpPnl.SetSize(Size) 2244 RBImp.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1) 2245 RBImp.Scroll(0,0) 2246 2247 def GetCoords(atmsel): 2248 '''Create orthogonal coordinates for selected atoms. 2249 Place the origin at the center of the body 2250 ''' 2251 atms = rd.Phase['Atoms'] 2252 cell = rd.Phase['General']['Cell'][1:7] 2253 Amat,Bmat = G2lat.cell2AB(cell) 2254 rd.Phase['RBcoords'] = np.array([np.inner(Amat,atms[i][3:6]) for i in atmsel]) 2255 rd.Phase['RBcoords'] -= rd.Phase['RBcoords'].mean(axis=0) # origin to middle 2256 rd.Phase['RBtypes'] = [atms[i][1] for i in atmsel] 2257 rd.Phase['RBlbls'] = [atms[i][0] for i in atmsel] 2258 2259 def UpdateVectorBody(rb,useSelection=False): 2260 '''Put the atoms in order to pass for plotting or for storage as 2261 a vector rigid body. 2262 2263 :param dict rb: rigid body contents created in :func:`MakeVectorBody` 2264 :param bool useSelection: True if the rd.Phase['RBselection'] 2265 values will be used to select which atoms are included in the 2266 rigid body. If False (default) they are included in rb 2267 and are used for plotting. 2268 ''' 2269 coordlist = [] 2270 typeslist = [] 2271 sellist = [] 2272 for i in rd.Phase['RBindex']: 2273 use = True 2274 if useSelection and not rd.Phase['RBselection'][i]: use = False 2275 if use: 2276 coordlist.append(rd.Phase['RBcoords'][i]) 2277 typeslist.append(rd.Phase['RBtypes'][i]) 2278 sellist.append(rd.Phase['RBselection'][i]) 2279 coordlist = np.array(coordlist) 2280 rb['rbXYZ'] = coordlist 2281 rb['rbVect'] = [coordlist] 2282 rb['rbTypes'] = typeslist 2283 if not useSelection: 2284 rb['Selection'] = sellist 2285 elif 'Selection' in rb: 2286 del rb['Selection'] 2287 2288 def MakeVectorBody(name=''): 2289 '''Make the basic vector rigid body dict (w/o coordinates) used for 2290 export and for plotting 2291 ''' 2292 nTrans = 1 2293 vecMag = [1.0] 2294 vecRef = [False] 2295 rb = {'RBname':name,'VectMag':vecMag, 2296 'rbRef':[0,1,2,False],'VectRef':vecRef, 2297 'useCount':0} 2298 UpdateVectorBody(rb) 2299 return rb 2300 2301 # get importer type and a phase file of that type 2302 G2sc.LoadG2fil() 2303 choices = [rd.formatName for rd in G2sc.Readers['Phase']] 2304 dlg = G2G.G2SingleChoiceDialog(G2frame,'Select the format of the file', 2305 'select format',choices) 2306 try: 2307 if dlg.ShowModal() == wx.ID_OK: 2308 col = dlg.GetSelection() 2309 else: 2310 col = None 2311 finally: 2312 dlg.Destroy() 2313 reader = G2sc.Readers['Phase'][col] 2314 2315 choices = reader.formatName + " file (" 2316 w = "" 2317 for extn in reader.extensionlist: 2318 if w != "": w += ";" 2319 w += "*" + extn 2320 choices += w + ")|" + w 2321 #choices += "|zip archive (.zip)|*.zip" 2322 if not reader.strictExtension: 2323 choices += "|any file (*.*)|*.*" 2324 typ = '( type '+reader.formatName+')' 2325 filelist = G2G.GetImportFile(G2frame, 2326 message="Choose phase input file"+typ, 2327 defaultFile="",wildcard=choices,style=wx.FD_OPEN) 2328 if len(filelist) != 1: return 2329 2330 # read in the phase file 2331 filename = filelist[0] 2332 rd = reader 2333 with open(filename, 'Ur') as fp: 2334 rd.ReInitialize() 2335 rd.errors = "" 2336 if not rd.ContentsValidator(filename): # Report error 2337 G2fil.G2Print("Warning: File {} has a validation error".format(filename)) 2338 return 2339 if len(rd.selections) > 1: 2340 print("File {} has {} phases. This is unexpected." 2341 .format(filename,len(rd.selections))) 2342 return 2343 2344 rd.objname = os.path.basename(filename) 2345 try: 2346 flag = rd.Reader(filename) 2347 except: 2348 G2fil.G2Print("Warning: read of file {} failed".format(filename)) 2349 return 2350 2351 pagename = 'Rigid body importer' 2352 Page1() 2353 return 2354 2355 def AddVectTrans(event): 2356 'Add a translation to an existing vector rigid body' 2357 choices = [] 2358 rbIdlist = [] 2359 for rbid in data['RBIds']['Vector']: 2360 if rbid != 'AtInfo': 2361 rbIdlist.append(rbid) 2362 choices.append(data['Vector'][rbid]['RBname']) 2363 if len(choices) == 0: 2364 G2G.G2MessageBox(G2frame,'No Vector Rigid Bodies found', 2365 'No VR Bodies') 2366 return 2367 elif len(choices) == 1: 2368 rbid = rbIdlist[0] 2369 else: 2370 dlg = G2G.G2SingleChoiceDialog(G2frame,'Select the rigid body to save', 2371 'select format',choices) 2372 try: 2373 if dlg.ShowModal() == wx.ID_OK: 2374 rbid = rbIdlist[dlg.GetSelection()] 2375 else: 2376 return 2377 finally: 2378 dlg.Destroy() 2379 data['Vector'][rbid]['VectMag'] += [1.0] 2380 data['Vector'][rbid]['VectRef'] += [False] 2381 nAtoms = len(data['Vector'][rbid]['rbXYZ']) 2382 data['Vector'][rbid]['rbVect'] += [np.zeros((nAtoms,3))] 2383 UpdateVectorRB() 2384 2385 def SaveVectorRB(event): 2386 choices = [] 2387 rbIdlist = [] 2388 for rbid in data['RBIds']['Vector']: 2389 if rbid != 'AtInfo': 2390 rbIdlist.append(rbid) 2391 choices.append(data['Vector'][rbid]['RBname']) 2392 if len(choices) == 0: 2393 G2G.G2MessageBox(G2frame,'No Vector Rigid Bodies found', 2394 'No VR Bodies') 2395 return 2396 elif len(choices) == 1: 2397 rbid = rbIdlist[0] 2398 else: 2399 dlg = G2G.G2SingleChoiceDialog(G2frame,'Select the rigid body to save', 2400 'select format',choices) 2401 try: 2402 if dlg.ShowModal() == wx.ID_OK: 2403 rbid = rbIdlist[dlg.GetSelection()] 2404 else: 2405 return 2406 finally: 2407 dlg.Destroy() 2408 2409 pth = G2G.GetExportPath(G2frame) 2410 dlg = wx.FileDialog(G2frame, 'Choose file to save vector rigid body', 2411 pth, '', 'VRB files (*.vecbody)|*.vecbody', 2412 wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) 2413 try: 2414 if dlg.ShowModal() == wx.ID_OK: 2415 filename = dlg.GetPath() 2416 filename = os.path.splitext(filename)[0]+'.vecbody' # set extension 2417 fp = open(filename,'w') 2418 fp.write('Name: '+data['Vector'][rbid]['RBname']+'\n') 2419 fp.write('Trans: ') 2420 for i in data['Vector'][rbid]['VectMag']: 2421 fp.write(str(i)+" ") 2422 fp.write('\n') 2423 ntrans = len(data['Vector'][rbid]['VectMag']) 2424 for i,sym in enumerate(data['Vector'][rbid]['rbTypes']): 2425 fp.write("{:3s}".format(sym)) 2426 for j in range(ntrans): 2427 fp.write('{:8.5f}{:9.5f}{:9.5f} ' 2428 .format(*data['Vector'][rbid]['rbVect'][j][i])) 2429 fp.write('\n') 2430 fp.close() 2431 print ('Vector rigid body saved to: '+filename) 2432 finally: 2433 dlg.Destroy() 2434 2435 def ReadVectorRB(event): 2436 AtInfo = data['Vector']['AtInfo'] 2437 pth = G2G.GetExportPath(G2frame) 2438 dlg = wx.FileDialog(G2frame, 'Choose file to read vector rigid body', 2439 pth, '', 'VRB files (*.vecbody)|*.vecbody', 2440 wx.FD_OPEN) 2441 try: 2442 if dlg.ShowModal() == wx.ID_OK: 2443 filename = dlg.GetPath() 2444 filename = os.path.splitext(filename)[0]+'.vecbody' # set extension 2445 fp = open(filename,'r') 2446 l = fp.readline().strip() 2447 if 'Name' not in l: 2448 fp.close() 2449 G2frame.ErrorDialog('Read Error', 2450 'File '+filename+' does not start with Name\nFirst line =' 2451 +l+'\ninvalid file',parent=G2frame) 2452 return 2453 name = l.split(':')[1].strip() 2454 trans = fp.readline().strip().split(':')[1].split() 2455 vecMag = [float(i) for i in trans] 2456 ntrans = len(trans) 2457 vecs = [[] for i in range(ntrans)] 2458 types = [] 2459 l = fp.readline().strip() 2460 while l: 2461 nums = l.strip().split() 2462 types.append(nums.pop(0)) 2463 t = types[-1] 2464 if t not in AtInfo: 2465 Info = G2elem.GetAtomInfo(t) 2466 AtInfo[t] = [Info['Drad'],Info['Color']] 2467 for i in range(ntrans): 2468 vecs[i].append([float(nums.pop(0)) for j in range(3)]) 2469 l = fp.readline().strip() 2470 fp.close() 2471 else: 2472 return 2473 finally: 2474 dlg.Destroy() 2475 natoms = len(types) 2476 vecs = [np.array(vecs[i]) for i in range(ntrans)] 2477 rbid = ran.randint(0,sys.maxsize) 2478 data['Vector'][rbid] = {'RBname':name,'VectMag':vecMag, 2479 'rbXYZ':np.zeros((natoms,3)), 2480 'rbRef':[0,1,2,False],'VectRef':ntrans*[False], 2481 'rbTypes':types, 2482 'rbVect':vecs,'useCount':0} 2483 data['RBIds']['Vector'].append(rbid) 1644 2484 UpdateVectorRB() 1645 2485 1646 2486 def AddResidueRB(event): 1647 global r bId2487 global resRBsel 1648 2488 AtInfo = data['Residue']['AtInfo'] 1649 2489 macro = getMacroFile('rigid body') … … 1654 2494 items = macStr.split() 1655 2495 if 'I' == items[0]: 1656 r bId= ran.randint(0,sys.maxsize)2496 resRBsel = ran.randint(0,sys.maxsize) 1657 2497 rbName = items[1] 1658 2498 rbTypes = [] … … 1683 2523 iMove = [int(macStr[i])-1 for i in range(3,nMove+3)] 1684 2524 rbSeq.append([iBeg,iFin,angle,iMove]) 1685 data['Residue'][r bId] = {'RBname':rbName,'rbXYZ':rbXYZ,'rbTypes':rbTypes,2525 data['Residue'][resRBsel] = {'RBname':rbName,'rbXYZ':rbXYZ,'rbTypes':rbTypes, 1686 2526 'atNames':atNames,'rbRef':[nOrig-1,mRef-1,nRef-1,True],'rbSeq':rbSeq, 1687 2527 'SelSeq':[0,0],'useCount':0} 1688 data['RBIds']['Residue'].append(r bId)2528 data['RBIds']['Residue'].append(resRBsel) 1689 2529 print ('Rigid body '+rbName+' added') 1690 2530 macStr = macro.readline() … … 1693 2533 1694 2534 def ImportResidueRB(): 1695 global r bId2535 global resRBsel 1696 2536 AtInfo = data['Residue']['AtInfo'] 1697 2537 text,ext = getTextFile() 1698 2538 if not text: 1699 2539 return 1700 r bId= ran.randint(0,sys.maxsize)2540 resRBsel = ran.randint(0,sys.maxsize) 1701 2541 rbTypes = [] 1702 2542 rbXYZ = [] … … 1758 2598 Mat = G2mth.getRBTransMat(X,Y) 1759 2599 rbXYZ = np.inner(Mat,rbXYZ).T 1760 data['Residue'][r bId] = {'RBname':'UNKRB','rbXYZ':rbXYZ,'rbTypes':rbTypes,2600 data['Residue'][resRBsel] = {'RBname':'UNKRB','rbXYZ':rbXYZ,'rbTypes':rbTypes, 1761 2601 'atNames':atNames,'rbRef':[0,1,2,False],'rbSeq':[],'SelSeq':[0,0],'useCount':0} 1762 data['RBIds']['Residue'].append(r bId)2602 data['RBIds']['Residue'].append(resRBsel) 1763 2603 print ('Rigid body UNKRB added') 1764 2604 text.close() … … 1766 2606 1767 2607 def SaveResidueRB(): 1768 global r bId2608 global resRBsel 1769 2609 pth = G2G.GetExportPath(G2frame) 1770 2610 dlg = wx.FileDialog(G2frame, 'Choose PDB file for Atom XYZ', pth, '', … … 1773 2613 if dlg.ShowModal() == wx.ID_OK: 1774 2614 filename = dlg.GetPath() 1775 # make sure extension is .pkslst 1776 filename = os.path.splitext(filename)[0]+'.pdb' 2615 filename = os.path.splitext(filename)[0]+'.pdb' # make extension .pdb 1777 2616 File = open(filename,'w') 1778 rbData = data['Residue'][r bId]2617 rbData = data['Residue'][resRBsel] 1779 2618 for iat,xyz in enumerate(rbData['rbXYZ']): 1780 2619 File.write('ATOM %6d %-4s%3s 1 %8.3f%8.3f%8.3f 1.00 0.00 %2s\n'%( … … 1824 2663 1825 2664 def OnDefineTorsSeq(event): 1826 global r bId1827 rbData = data['Residue'][r bId]2665 global resRBsel 2666 rbData = data['Residue'][resRBsel] 1828 2667 if not len(rbData): 1829 2668 return … … 1860 2699 return 1861 2700 SetStatusLine(' You may use e.g. "c60" or "s60" for a vector entry') 1862 def rbNameSizer(rb Id,rbData):2701 def rbNameSizer(rbid,rbData): 1863 2702 1864 2703 def OnRBName(event): … … 1869 2708 def OnDelRB(event): 1870 2709 Obj = event.GetEventObject() 1871 rb Id = Indx[Obj.GetId()]1872 if rb Id in data['Vector']:1873 del data['Vector'][rb Id]1874 data['RBIds']['Vector'].remove(rb Id)2710 rbid = Indx[Obj.GetId()] 2711 if rbid in data['Vector']: 2712 del data['Vector'][rbid] 2713 data['RBIds']['Vector'].remove(rbid) 1875 2714 rbData['useCount'] -= 1 1876 2715 wx.CallAfter(UpdateVectorRB) 1877 1878 2716 def OnPlotRB(event): 1879 2717 Obj = event.GetEventObject() 1880 Obj.SetValue(False)1881 2718 G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,rbData,plotDefaults) 1882 2719 … … 1885 2722 0,wx.ALIGN_CENTER_VERTICAL) 1886 2723 RBname = wx.TextCtrl(VectorRBDisplay,-1,rbData['RBname']) 1887 Indx[RBname.GetId()] = rb Id2724 Indx[RBname.GetId()] = rbid 1888 2725 RBname.Bind(wx.EVT_TEXT_ENTER,OnRBName) 1889 2726 RBname.Bind(wx.EVT_KILL_FOCUS,OnRBName) 1890 2727 nameSizer.Add(RBname,0,wx.ALIGN_CENTER_VERTICAL) 1891 2728 nameSizer.Add((5,0),) 1892 plotRB = wx.CheckBox(VectorRBDisplay,-1,'Plot?') 1893 Indx[plotRB.GetId()] = rbId 1894 plotRB.Bind(wx.EVT_CHECKBOX,OnPlotRB) 2729 plotRB = wx.Button(VectorRBDisplay,wx.ID_ANY,'Plot', 2730 style=wx.BU_EXACTFIT) 2731 plotRB.Bind(wx.EVT_BUTTON, OnPlotRB) 2732 Indx[plotRB.GetId()] = rbid 1895 2733 nameSizer.Add(plotRB,0,wx.ALIGN_CENTER_VERTICAL) 1896 2734 nameSizer.Add((5,0),) 1897 2735 if not rbData['useCount']: 1898 delRB = wx.CheckBox(VectorRBDisplay,-1,'Delete?') 1899 Indx[delRB.GetId()] = rbId 1900 delRB.Bind(wx.EVT_CHECKBOX,OnDelRB) 2736 delRB = wx.Button(VectorRBDisplay,wx.ID_ANY,"Delete", 2737 style=wx.BU_EXACTFIT) 2738 delRB.Bind(wx.EVT_BUTTON, OnDelRB) 2739 Indx[delRB.GetId()] = rbid 1901 2740 nameSizer.Add(delRB,0,wx.ALIGN_CENTER_VERTICAL) 1902 2741 return nameSizer 1903 2742 1904 def rbRefAtmSizer(rb Id,rbData):2743 def rbRefAtmSizer(rbid,rbData): 1905 2744 1906 2745 def OnRefSel(event): … … 1909 2748 sel = Obj.GetValue() 1910 2749 rbData['rbRef'][iref] = atNames.index(sel) 1911 FillRefChoice(rb Id,rbData)2750 FillRefChoice(rbid,rbData) 1912 2751 1913 2752 refAtmSizer = wx.BoxSizer(wx.HORIZONTAL) … … 1923 2762 'Orientation reference atoms A-B-C: '),0,wx.ALIGN_CENTER_VERTICAL) 1924 2763 for i in range(3): 1925 choices = [atNames[j] for j in refChoice[rb Id][i]]2764 choices = [atNames[j] for j in refChoice[rbid][i]] 1926 2765 refSel = wx.ComboBox(VectorRBDisplay,-1,value='', 1927 2766 choices=choices,style=wx.CB_READONLY|wx.CB_DROPDOWN) … … 1932 2771 return refAtmSizer 1933 2772 1934 def rbVectMag(rb Id,imag,rbData):2773 def rbVectMag(rbid,imag,rbData): 1935 2774 1936 2775 def OnRBVectorMag(event): 1937 2776 event.Skip() 1938 2777 Obj = event.GetEventObject() 1939 rb Id,imag = Indx[Obj.GetId()]2778 rbid,imag = Indx[Obj.GetId()] 1940 2779 try: 1941 2780 val = float(Obj.GetValue()) … … 1947 2786 Obj.SetValue('%8.4f'%(val)) 1948 2787 wx.CallAfter(UpdateVectorRB,VectorRB.GetScrollPos(wx.VERTICAL)) 1949 G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,data['Vector'][rb Id],plotDefaults)2788 G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,data['Vector'][rbid],plotDefaults) 1950 2789 1951 2790 def OnRBVectorRef(event): 1952 2791 Obj = event.GetEventObject() 1953 rb Id,imag = Indx[Obj.GetId()]2792 rbid,imag = Indx[Obj.GetId()] 1954 2793 rbData['VectRef'][imag] = Obj.GetValue() 1955 2794 … … 1958 2797 0,wx.ALIGN_CENTER_VERTICAL) 1959 2798 magValue = wx.TextCtrl(VectorRBDisplay,-1,'%8.4f'%(rbData['VectMag'][imag])) 1960 Indx[magValue.GetId()] = [rb Id,imag]2799 Indx[magValue.GetId()] = [rbid,imag] 1961 2800 magValue.Bind(wx.EVT_TEXT_ENTER,OnRBVectorMag) 1962 2801 magValue.Bind(wx.EVT_KILL_FOCUS,OnRBVectorMag) … … 1966 2805 magref.SetValue(rbData['VectRef'][imag]) 1967 2806 magref.Bind(wx.EVT_CHECKBOX,OnRBVectorRef) 1968 Indx[magref.GetId()] = [rb Id,imag]2807 Indx[magref.GetId()] = [rbid,imag] 1969 2808 magSizer.Add(magref,0,wx.ALIGN_CENTER_VERTICAL) 1970 2809 return magSizer 1971 2810 1972 def rbVectors(rb Id,imag,mag,XYZ,rbData):2811 def rbVectors(rbid,imag,mag,XYZ,rbData): 1973 2812 1974 2813 def TypeSelect(event): … … 1996 2835 except ValueError: 1997 2836 pass 1998 G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,data['Vector'][rb Id],plotDefaults)2837 G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,data['Vector'][rbid],plotDefaults) 1999 2838 wx.CallAfter(UpdateVectorRB,VectorRB.GetScrollPos(wx.VERTICAL)) 2000 2839 … … 2017 2856 vecGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, TypeSelect) 2018 2857 attr = wx.grid.GridCellAttr() 2858 attr.IncRef() 2019 2859 attr.SetEditor(G2G.GridFractionEditor(vecGrid)) 2020 2860 for c in range(3): 2861 attr.IncRef() 2021 2862 vecGrid.SetColAttr(c, attr) 2022 2863 for row in range(vecTable.GetNumberRows()): … … 2030 2871 return vecSizer 2031 2872 2032 def FillRefChoice(rb Id,rbData):2873 def FillRefChoice(rbid,rbData): 2033 2874 choiceIds = [i for i in range(len(rbData['rbTypes']))] 2034 2875 … … 2036 2877 for i in range(3): 2037 2878 choiceIds.remove(rbRef[i]) 2038 refChoice[rb Id] = [choiceIds[:],choiceIds[:],choiceIds[:]]2879 refChoice[rbid] = [choiceIds[:],choiceIds[:],choiceIds[:]] 2039 2880 for i in range(3): 2040 refChoice[rb Id][i].append(rbRef[i])2041 refChoice[rb Id][i].sort()2881 refChoice[rbid][i].append(rbRef[i]) 2882 refChoice[rbid][i].sort() 2042 2883 2043 2884 if VectorRB.GetSizer(): VectorRB.GetSizer().Clear(True) 2044 2885 VectorRBSizer = wx.BoxSizer(wx.VERTICAL) 2045 for rbId in data['RBIds']['Vector']: 2046 if rbId != 'AtInfo': 2047 rbData = data['Vector'][rbId] 2048 FillRefChoice(rbId,rbData) 2049 VectorRBSizer.Add(rbNameSizer(rbId,rbData),0) 2050 VectorRBSizer.Add(rbRefAtmSizer(rbId,rbData),0) 2886 first = True 2887 for rbid in data['RBIds']['Vector']: 2888 if rbid != 'AtInfo': 2889 rbData = data['Vector'][rbid] 2890 FillRefChoice(rbid,rbData) 2891 if not first: 2892 G2G.HorizontalLine(VectorRBSizer,VectorRBDisplay) 2893 VectorRBSizer.Add(rbNameSizer(rbid,rbData),0) 2894 VectorRBSizer.Add(rbRefAtmSizer(rbid,rbData),0) 2051 2895 XYZ = np.array([[0.,0.,0.] for Ty in rbData['rbTypes']]) 2052 2896 for imag,mag in enumerate(rbData['VectMag']): 2053 2897 XYZ += mag*rbData['rbVect'][imag] 2054 VectorRBSizer.Add(rbVectMag(rb Id,imag,rbData),0)2055 VectorRBSizer.Add(rbVectors(rb Id,imag,mag,XYZ,rbData),0)2898 VectorRBSizer.Add(rbVectMag(rbid,imag,rbData),0) 2899 VectorRBSizer.Add(rbVectors(rbid,imag,mag,XYZ,rbData),0) 2056 2900 VectorRBSizer.Add((5,5),0) 2057 data['Vector'][rbId]['rbXYZ'] = XYZ 2901 data['Vector'][rbid]['rbXYZ'] = XYZ 2902 first = False 2058 2903 VectorRBSizer.Layout() 2059 2904 VectorRBDisplay.SetSizer(VectorRBSizer,True) … … 2068 2913 '''Draw the contents of the Residue Rigid Body tab for Rigid Bodies tree entry 2069 2914 ''' 2070 global r bId2071 def rbNameSizer(rb Id,rbData):2915 global resRBsel 2916 def rbNameSizer(rbid,rbData): 2072 2917 2073 2918 def OnDelRB(event): 2074 2919 Obj = event.GetEventObject() 2075 rb Id = Indx[Obj.GetId()]2076 if rb Id in data['Residue']:2077 del data['Residue'][rb Id]2078 data['RBIds']['Residue'].remove(rb Id)2920 rbid = Indx[Obj.GetId()] 2921 if rbid in data['Residue']: 2922 del data['Residue'][rbid] 2923 data['RBIds']['Residue'].remove(rbid) 2079 2924 wx.CallAfter(UpdateResidueRB) 2080 2925 2081 2926 def OnStripH(event): 2082 2927 Obj = event.GetEventObject() 2083 rb Id = Indx[Obj.GetId()]2084 if rb Id in data['Residue']:2928 rbid = Indx[Obj.GetId()] 2929 if rbid in data['Residue']: 2085 2930 newNames = [] 2086 2931 newTypes = [] … … 2099 2944 def OnPlotRB(event): 2100 2945 Obj = event.GetEventObject() 2101 Obj.SetValue(False)2102 2946 G2plt.PlotRigidBody(G2frame,'Residue',AtInfo,rbData,plotDefaults) 2103 2947 … … 2108 2952 nameSizer.Add(G2G.ValidatedTxtCtrl(ResidueRBDisplay,rbData,'RBname'),0,WACV) 2109 2953 nameSizer.Add((5,0),) 2110 plotRB = wx.CheckBox(ResidueRBDisplay,-1,'Plot?') 2111 Indx[plotRB.GetId()] = rbId 2112 plotRB.Bind(wx.EVT_CHECKBOX,OnPlotRB) 2954 plotRB = wx.Button(ResidueRBDisplay,wx.ID_ANY,'Plot', 2955 style=wx.BU_EXACTFIT) 2956 plotRB.Bind(wx.EVT_BUTTON, OnPlotRB) 2957 Indx[plotRB.GetId()] = rbid 2113 2958 nameSizer.Add(plotRB,0,wx.ALIGN_CENTER_VERTICAL) 2114 2959 nameSizer.Add((5,0),) 2115 2960 if not rbData['useCount']: 2116 delRB = wx.CheckBox(ResidueRBDisplay,-1,'Delete?') 2117 Indx[delRB.GetId()] = rbId 2118 delRB.Bind(wx.EVT_CHECKBOX,OnDelRB) 2961 delRB = wx.Button(ResidueRBDisplay,wx.ID_ANY,"Delete", 2962 style=wx.BU_EXACTFIT) 2963 delRB.Bind(wx.EVT_BUTTON, OnDelRB) 2964 Indx[delRB.GetId()] = rbid 2119 2965 nameSizer.Add(delRB,0,wx.ALIGN_CENTER_VERTICAL) 2120 2966 if 'H' in rbData['rbTypes']: 2121 stripH = wx.CheckBox(ResidueRBDisplay,-1,'Strip H-atoms?') 2122 Indx[stripH.GetId()] = rbId 2123 stripH.Bind(wx.EVT_CHECKBOX,OnStripH) 2967 stripH = wx.Button(ResidueRBDisplay,wx.ID_ANY, 2968 "Strip H-atoms", 2969 style=wx.BU_EXACTFIT) 2970 stripH.Bind(wx.EVT_BUTTON, OnStripH) 2971 Indx[stripH.GetId()] = rbid 2124 2972 nameSizer.Add(stripH,0,wx.ALIGN_CENTER_VERTICAL) 2125 2973 return nameSizer 2126 2974 2127 def rbResidues(rb Id,rbData):2975 def rbResidues(rbid,rbData): 2128 2976 2129 2977 def TypeSelect(event): 2130 2978 AtInfo = data['Residue']['AtInfo'] 2131 2979 r,c = event.GetRow(),event.GetCol() 2132 if vecGrid.GetColLabelValue(c) == 'Type':2980 if resGrid.GetColLabelValue(c) == 'Type': 2133 2981 PE = G2elemGUI.PickElement(G2frame,oneOnly=True) 2134 2982 if PE.ShowModal() == wx.ID_OK: … … 2139 2987 AtInfo[El] = [Info['Drad']['Color']] 2140 2988 rbData['rbTypes'][r] = El 2141 vecGrid.SetCellValue(r,c,El)2989 resGrid.SetCellValue(r,c,El) 2142 2990 PE.Destroy() 2143 2991 … … 2146 2994 if r >= 0 and (0 <= c < 3): 2147 2995 try: 2148 val = float( vecGrid.GetCellValue(r,c))2996 val = float(resGrid.GetCellValue(r,c)) 2149 2997 rbData['rbXYZ'][r][c] = val 2150 2998 except ValueError: … … 2154 3002 r,c = event.GetRow(),event.GetCol() 2155 3003 if c < 0: #only row clicks 2156 for vecgrid in resList:2157 vecgrid.ClearSelection()2158 vecGrid.SelectRow(r,True)3004 for iGrid in resList: 3005 iGrid.ClearSelection() 3006 resGrid.SelectRow(r,True) 2159 3007 2160 3008 def OnRefSel(event): 2161 2162 3009 Obj = event.GetEventObject() 2163 3010 iref,res,jref = Indx[Obj.GetId()] … … 2167 3014 G2G.G2MessageBox(G2frame,'You should not select an H-atom for rigid body orientation') 2168 3015 rbData['rbRef'][iref] = ind 2169 FillRefChoice(rb Id,rbData)3016 FillRefChoice(rbid,rbData) 2170 3017 for i,ref in enumerate(RefObjs[jref]): 2171 ref.SetItems([atNames[j] for j in refChoice[rb Id][i]])3018 ref.SetItems([atNames[j] for j in refChoice[rbid][i]]) 2172 3019 ref.SetValue(atNames[rbData['rbRef'][i]]) 2173 3020 rbXYZ = rbData['rbXYZ'] … … 2199 3046 rowLabels.append(str(ivec)) 2200 3047 vecTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types) 2201 vecGrid = G2G.GSGrid(ResidueRBDisplay)2202 Indx[ vecGrid.GetId()] = rbId2203 resList.append( vecGrid)2204 vecGrid.SetTable(vecTable, True)3048 resGrid = G2G.GSGrid(ResidueRBDisplay) 3049 Indx[resGrid.GetId()] = rbid 3050 resList.append(resGrid) 3051 resGrid.SetTable(vecTable, True) 2205 3052 if 'phoenix' in wx.version(): 2206 vecGrid.Bind(wg.EVT_GRID_CELL_CHANGED, ChangeCell)3053 resGrid.Bind(wg.EVT_GRID_CELL_CHANGED, ChangeCell) 2207 3054 else: 2208 vecGrid.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)2209 vecGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, TypeSelect)2210 vecGrid.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)3055 resGrid.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell) 3056 resGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, TypeSelect) 3057 resGrid.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect) 2211 3058 attr = wx.grid.GridCellAttr() 2212 attr.SetEditor(G2G.GridFractionEditor(vecGrid)) 3059 attr.IncRef() 3060 attr.SetEditor(G2G.GridFractionEditor(resGrid)) 2213 3061 for c in range(3): 2214 vecGrid.SetColAttr(c, attr) 3062 attr.IncRef() 3063 resGrid.SetColAttr(c, attr) 2215 3064 for row in range(vecTable.GetNumberRows()): 2216 3065 for col in range(5): 2217 vecGrid.SetCellStyle(row,col,VERY_LIGHT_GREY,True)2218 vecGrid.AutoSizeColumns(False)3066 resGrid.SetCellStyle(row,col,VERY_LIGHT_GREY,True) 3067 resGrid.AutoSizeColumns(False) 2219 3068 vecSizer = wx.BoxSizer() 2220 vecSizer.Add( vecGrid)3069 vecSizer.Add(resGrid) 2221 3070 2222 3071 refAtmSizer = wx.BoxSizer(wx.HORIZONTAL) … … 2232 3081 refObj = [0,0,0] 2233 3082 for i in range(3): 2234 choices = [atNames[j] for j in refChoice[rb Id][i]]3083 choices = [atNames[j] for j in refChoice[rbid][i]] 2235 3084 refSel = wx.ComboBox(ResidueRBDisplay,-1,value='', 2236 3085 choices=choices,style=wx.CB_READONLY|wx.CB_DROPDOWN) 2237 3086 refSel.SetValue(atNames[rbRef[i]]) 2238 3087 refSel.Bind(wx.EVT_COMBOBOX, OnRefSel) 2239 Indx[refSel.GetId()] = [i, vecGrid,len(RefObjs)]3088 Indx[refSel.GetId()] = [i,resGrid,len(RefObjs)] 2240 3089 refObj[i] = refSel 2241 3090 refAtmSizer.Add(refSel,0,wx.ALIGN_CENTER_VERTICAL) … … 2247 3096 return mainSizer 2248 3097 2249 def SeqSizer(angSlide,rbId,iSeq,Seq,atNames):3098 def Add2SeqSizer(seqSizer,angSlide,rbid,iSeq,Seq,atNames): 2250 3099 2251 3100 def ChangeAngle(event): 2252 3101 event.Skip() 2253 3102 Obj = event.GetEventObject() 2254 rb Id,Seq = Indx[Obj.GetId()][:2]3103 rbid,Seq = Indx[Obj.GetId()][:2] 2255 3104 val = Seq[2] 2256 3105 try: … … 2260 3109 pass 2261 3110 Obj.SetValue('%8.2f'%(val)) 2262 G2plt.PlotRigidBody(G2frame,'Residue',AtInfo,data['Residue'][rb Id],plotDefaults)3111 G2plt.PlotRigidBody(G2frame,'Residue',AtInfo,data['Residue'][rbid],plotDefaults) 2263 3112 2264 3113 def OnRadBtn(event): 2265 3114 Obj = event.GetEventObject() 2266 3115 Seq,iSeq,angId = Indx[Obj.GetId()] 2267 data['Residue'][rb Id]['SelSeq'] = [iSeq,angId]3116 data['Residue'][rbid]['SelSeq'] = [iSeq,angId] 2268 3117 angSlide.SetValue(int(100*Seq[2])) 2269 3118 2270 3119 def OnDelBtn(event): 2271 3120 Obj = event.GetEventObject() 2272 rb Id,Seq = Indx[Obj.GetId()]2273 data['Residue'][rb Id]['rbSeq'].remove(Seq)3121 rbid,Seq = Indx[Obj.GetId()] 3122 data['Residue'][rbid]['rbSeq'].remove(Seq) 2274 3123 wx.CallAfter(UpdateResidueRB) 2275 3124 2276 seqSizer = wx.FlexGridSizer(0,5,2,2)2277 seqSizer.AddGrowableCol(3,0)2278 3125 iBeg,iFin,angle,iMove = Seq 2279 ang = wx.TextCtrl(ResidueRBDisplay,-1,'%8.2f'%(angle),size=(50,20)) 3126 ang = wx.TextCtrl(ResidueRBDisplay,wx.ID_ANY, 3127 '%8.2f'%(angle),size=(70,-1),style=wx.TE_PROCESS_ENTER) 2280 3128 if not iSeq: 2281 radBt = wx.RadioButton(ResidueRBDisplay,-1,'',style=wx.RB_GROUP) 2282 data['Residue'][rbId]['SelSeq'] = [iSeq,ang.GetId()] 3129 radBt = wx.RadioButton(ResidueRBDisplay,wx.ID_ANY, 3130 '',style=wx.RB_GROUP) 3131 data['Residue'][rbid]['SelSeq'] = [iSeq,ang.GetId()] 3132 radBt.SetValue(True) 2283 3133 else: 2284 radBt = wx.RadioButton(ResidueRBDisplay, -1,'')3134 radBt = wx.RadioButton(ResidueRBDisplay,wx.ID_ANY,'') 2285 3135 radBt.Bind(wx.EVT_RADIOBUTTON,OnRadBtn) 2286 3136 seqSizer.Add(radBt) 2287 delBt = wx.RadioButton(ResidueRBDisplay,-1,'') 2288 delBt.Bind(wx.EVT_RADIOBUTTON,OnDelBtn) 3137 delBt = wx.Button(ResidueRBDisplay,wx.ID_ANY,'Del', 3138 style=wx.BU_EXACTFIT) 3139 delBt.Bind(wx.EVT_BUTTON,OnDelBtn) 2289 3140 seqSizer.Add(delBt) 2290 bond = wx.TextCtrl(ResidueRBDisplay,-1,'%s %s'%(atNames[iBeg],atNames[iFin]),size=(50,20)) 3141 bond = wx.StaticText(ResidueRBDisplay,wx.ID_ANY, 3142 '%s %s'%(atNames[iBeg],atNames[iFin]),size=(50,20)) 2291 3143 seqSizer.Add(bond,0,wx.ALIGN_CENTER_VERTICAL) 2292 3144 Indx[radBt.GetId()] = [Seq,iSeq,ang.GetId()] 2293 Indx[delBt.GetId()] = [rb Id,Seq]2294 Indx[ang.GetId()] = [rb Id,Seq,ang]3145 Indx[delBt.GetId()] = [rbid,Seq] 3146 Indx[ang.GetId()] = [rbid,Seq,ang] 2295 3147 ang.Bind(wx.EVT_TEXT_ENTER,ChangeAngle) 2296 3148 ang.Bind(wx.EVT_KILL_FOCUS,ChangeAngle) … … 2299 3151 for i in iMove: 2300 3152 atms += ' %s,'%(atNames[i]) 2301 moves = wx.TextCtrl(ResidueRBDisplay,-1,atms[:-1],size=(200,20)) 3153 moves = wx.StaticText(ResidueRBDisplay,wx.ID_ANY, 3154 atms[:-1],size=(200,20)) 2302 3155 seqSizer.Add(moves,1,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.RIGHT) 2303 3156 return seqSizer … … 2325 3178 return slideSizer,angSlide 2326 3179 2327 def FillRefChoice(rb Id,rbData):3180 def FillRefChoice(rbid,rbData): 2328 3181 choiceIds = [i for i in range(len(rbData['atNames']))] 2329 3182 for seq in rbData['rbSeq']: … … 2339 3192 except ValueError: 2340 3193 pass 2341 refChoice[rb Id] = [choiceIds[:],choiceIds[:],choiceIds[:]]3194 refChoice[rbid] = [choiceIds[:],choiceIds[:],choiceIds[:]] 2342 3195 for i in range(3): 2343 refChoice[rb Id][i].append(rbRef[i])2344 refChoice[rb Id][i].sort()3196 refChoice[rbid][i].append(rbRef[i]) 3197 refChoice[rbid][i].sort() 2345 3198 2346 3199 def OnSelect(event): 2347 global rbId 2348 rbname = rbchoice[select.GetSelection()] 2349 rbId = RBnames[rbname] 3200 global resRBsel 3201 sel = select.GetSelection() 3202 if sel == 0: return # 1st entry is blank 3203 rbname = rbchoice[sel-1] 3204 resRBsel = RBnames[rbname] 2350 3205 wx.CallLater(100,UpdateResidueRB) 2351 3206 … … 2374 3229 if len(RBnames) > 1: 2375 3230 selSizer = wx.BoxSizer(wx.HORIZONTAL) 2376 selSizer.Add(wx.StaticText(ResidueRBDisplay,label=' Select residue to view:'),0) 3231 selSizer.Add(wx.StaticText(ResidueRBDisplay, 3232 label=' Select residue to view:'),0) 2377 3233 rbchoice.sort() 2378 select = wx.ComboBox(ResidueRBDisplay,choices= rbchoice)3234 select = wx.ComboBox(ResidueRBDisplay,choices=['']+rbchoice) 2379 3235 select.Bind(wx.EVT_COMBOBOX,OnSelect) 2380 3236 selSizer.Add(select,0) 2381 3237 ResidueRBSizer.Add(selSizer,0) 2382 try: 2383 if not rbId: 2384 rbId = RBnames[rbchoice[0]] 2385 except NameError: 2386 rbId = RBnames[rbchoice[0]] 2387 rbData = data['Residue'][rbId] 2388 FillRefChoice(rbId,rbData) 2389 ResidueRBSizer.Add(rbNameSizer(rbId,rbData),0) 2390 ResidueRBSizer.Add(rbResidues(rbId,rbData),0) 2391 ResidueRBSizer.Add((5,5),0) 2392 if rbData['rbSeq']: 3238 if resRBsel not in data['RBIds']['Residue']: 3239 resRBsel = RBnames[rbchoice[0]] 3240 rbData = data['Residue'][resRBsel] 3241 FillRefChoice(resRBsel,rbData) 3242 ResidueRBSizer.Add(rbNameSizer(resRBsel,rbData),0) 3243 ResidueRBSizer.Add(rbResidues(resRBsel,rbData),0) 3244 if len(rbData['rbSeq']): 3245 ResidueRBSizer.Add((-1,15),0) 2393 3246 slideSizer,angSlide = SlideSizer() 2394 if len(rbData['rbSeq']): 2395 ResidueRBSizer.Add(wx.StaticText(ResidueRBDisplay,-1, 2396 'Sel Del Bond Angle Riding atoms'), 2397 0,wx.ALIGN_CENTER_VERTICAL) 2398 for iSeq,Seq in enumerate(rbData['rbSeq']): 2399 ResidueRBSizer.Add(SeqSizer(angSlide,rbId,iSeq,Seq,rbData['atNames'])) 2400 if rbData['rbSeq']: 3247 seqSizer = wx.FlexGridSizer(0,5,4,8) 3248 for lbl in 'Sel','','Bond','Angle','Riding atoms': 3249 seqSizer.Add(wx.StaticText(ResidueRBDisplay,wx.ID_ANY,lbl)) 3250 ResidueRBSizer.Add(seqSizer) 3251 # for iSeq,Seq in enumerate(rbData['rbSeq']): 3252 # ResidueRBSizer.Add(SeqSizer(angSlide,resRBsel,iSeq,Seq,rbData['atNames'])) 3253 for iSeq,Seq in enumerate(rbData['rbSeq']): 3254 Add2SeqSizer(seqSizer,angSlide,resRBsel,iSeq,Seq,rbData['atNames']) 2401 3255 ResidueRBSizer.Add(slideSizer,) 2402 3256 -
trunk/GSASIIctrlGUI.py
r4410 r4421 36 36 a filter to select choices and buttons to make selection 37 37 of multiple items more simple. 38 :class:`G2MultiChoiceWindow` Similar to :class:`G2MultiChoiceDialog` but provides 39 a sizer that can be placed in a frame or panel. 38 40 :class:`G2SingleChoiceDialog` Dialog similar to wx.SingleChoiceDialog, but provides 39 41 a filter to help search through choices. … … 1039 1041 def HorizontalLine(sizer,parent): 1040 1042 '''Draws a horizontal line as wide as the window. 1041 This shows up on the Mac as a very thin line, no matter what I do1042 1043 ''' 1043 line = wx.StaticLine(parent, size=(-1,3), style=wx.LI_HORIZONTAL) 1044 if sys.platform == "darwin": 1045 line = wx.StaticLine(parent, size=(-1,1), style=wx.LI_HORIZONTAL) 1046 line.SetBackgroundColour((128,128,128)) 1047 else: 1048 line = wx.StaticLine(parent, size=(-1,3), style=wx.LI_HORIZONTAL) 1044 1049 sizer.Add(line, 0, wx.EXPAND|wx.ALIGN_CENTER|wx.ALL, 5) 1045 1050 … … 1737 1742 self.OKbtn.Enable(True) 1738 1743 1744 ############################################### Multichoice in a sizer with set all, toggle & filter options 1745 class G2MultiChoiceWindow(wx.BoxSizer): 1746 '''Creates a sizer similar to G2MultiChoiceDialog except that 1747 buttons are added to set all choices and to toggle all choices. This 1748 is placed in a sizer, so that it can be used in a frame or panel. 1749 1750 :param parent: reference to parent frame/panel 1751 :param str title: heading above list of choices 1752 :param list ChoiceList: a list of choices where one more will be selected 1753 :param list SelectList: a list of selected choices 1754 :param bool toggle: If True (default) the toggle and select all buttons 1755 are displayed 1756 :param bool monoFont: If False (default), use a variable-spaced font; 1757 if True use a equally-spaced font. 1758 :param bool filterBox: If True (default) an input widget is placed on 1759 the window and only entries matching the entered text are shown. 1760 :param function OnChange: a reference to a callable object, that 1761 is called each time any a choice is changed. Default is None which 1762 will not be called. 1763 :param list OnChangeArgs: a list of arguments to be supplied to function 1764 OnChange. The default is a null list. 1765 :returns: the name of the created sizer 1766 ''' 1767 def __init__(self, parent, title, ChoiceList, SelectList, toggle=True, 1768 monoFont=False, filterBox=True, 1769 OnChange=None, OnChangeArgs=[]): 1770 self.SelectList = SelectList 1771 self.ChoiceList = ['%4d) %s'%(i,item) for i,item in enumerate(ChoiceList)] # numbered list of choices (list of str values) 1772 self.frm = parent 1773 self.Selections = len(self.ChoiceList) * [False,] # selection status for each choice (list of bools) 1774 self.filterlist = range(len(self.ChoiceList)) # list of the choice numbers that have been filtered (list of int indices) 1775 self.Stride = 1 1776 self.OnChange = OnChange 1777 self.OnChangeArgs = OnChangeArgs 1778 # fill frame 1779 wx.BoxSizer.__init__(self,wx.VERTICAL) 1780 # fill the sizer 1781 Sizer = self 1782 topSizer = wx.BoxSizer(wx.HORIZONTAL) 1783 topSizer.Add(wx.StaticText(self.frm,wx.ID_ANY,title,size=(-1,35)), 1784 1,wx.ALL|wx.EXPAND|WACV,1) 1785 if filterBox: 1786 self.timer = wx.Timer() 1787 self.timer.Bind(wx.EVT_TIMER,self.Filter) 1788 topSizer.Add(wx.StaticText(self.frm,wx.ID_ANY,'Name \nFilter: '),0,wx.ALL|WACV,1) 1789 self.filterBox = wx.TextCtrl(self.frm, wx.ID_ANY, size=(80,-1),style=wx.TE_PROCESS_ENTER) 1790 self.filterBox.Bind(wx.EVT_TEXT,self.onChar) 1791 self.filterBox.Bind(wx.EVT_TEXT_ENTER,self.Filter) 1792 topSizer.Add(self.filterBox,0,wx.ALL|WACV,0) 1793 Sizer.Add(topSizer,0,wx.ALL|wx.EXPAND,8) 1794 self.settingRange = False 1795 self.rangeFirst = None 1796 self.clb = wx.CheckListBox(self.frm, wx.ID_ANY, (30,30), wx.DefaultSize, self.ChoiceList) 1797 self.clb.Bind(wx.EVT_CHECKLISTBOX,self.OnCheck) 1798 if monoFont: 1799 font1 = wx.Font(self.clb.GetFont().GetPointSize(), 1800 wx.MODERN, wx.NORMAL, wx.NORMAL, False) 1801 self.clb.SetFont(font1) 1802 Sizer.Add(self.clb,1,wx.LEFT|wx.RIGHT|wx.EXPAND,10) 1803 Sizer.Add((-1,10)) 1804 # set/toggle buttons 1805 if toggle: 1806 tSizer = wx.BoxSizer(wx.HORIZONTAL) 1807 tSizer.Add(wx.StaticText(self.frm,label=' Apply stride:'),0,WACV) 1808 numbs = [str(i+1) for i in range(9)]+[str(2*i+10) for i in range(6)] 1809 self.stride = wx.ComboBox(self.frm,value='1',choices=numbs,style=wx.CB_READONLY|wx.CB_DROPDOWN) 1810 self.stride.Bind(wx.EVT_COMBOBOX,self.OnStride) 1811 tSizer.Add(self.stride,0,WACV) 1812 Sizer.Add(tSizer,0,wx.LEFT,12) 1813 tSizer = wx.BoxSizer(wx.HORIZONTAL) 1814 setBut = wx.Button(self.frm,wx.ID_ANY,'Set All') 1815 setBut.Bind(wx.EVT_BUTTON,self._SetAll) 1816 tSizer.Add(setBut) 1817 togBut = wx.Button(self.frm,wx.ID_ANY,'Toggle All') 1818 togBut.Bind(wx.EVT_BUTTON,self._ToggleAll) 1819 tSizer.Add(togBut) 1820 self.rangeBut = wx.ToggleButton(self.frm,wx.ID_ANY,'Set Range') 1821 self.rangeBut.Bind(wx.EVT_TOGGLEBUTTON,self.SetRange) 1822 tSizer.Add(self.rangeBut) 1823 Sizer.Add(tSizer,0,wx.LEFT,12) 1824 tSizer = wx.BoxSizer(wx.HORIZONTAL) 1825 self.rangeCapt = wx.StaticText(self.frm,wx.ID_ANY,'') 1826 tSizer.Add(self.rangeCapt,1,wx.EXPAND,1) 1827 Sizer.Add(tSizer,0,wx.LEFT,12) 1828 self.SetSelections(self.SelectList) 1829 1830 def OnStride(self,event): 1831 self.Stride = int(self.stride.GetValue()) 1832 1833 def SetRange(self,event): 1834 '''Respond to a press of the Set Range button. Set the range flag and 1835 the caption next to the button 1836 ''' 1837 self.settingRange = self.rangeBut.GetValue() 1838 if self.settingRange: 1839 self.rangeCapt.SetLabel('Select range start') 1840 else: 1841 self.rangeCapt.SetLabel('') 1842 self.rangeFirst = None 1843 1844 def GetSelections(self): 1845 'Returns a list of the indices for the selected choices' 1846 # update self.Selections with settings for displayed items 1847 for i in range(len(self.filterlist)): 1848 self.Selections[self.filterlist[i]] = self.clb.IsChecked(i) 1849 # return all selections, shown or hidden 1850 return [i for i in range(len(self.Selections)) if self.Selections[i]] 1851 1852 def SetSelections(self,selList): 1853 '''Sets the selection indices in selList as selected. Resets any previous 1854 selections for compatibility with wx.MultiChoiceDialog. Note that 1855 the state for only the filtered items is shown. 1856 1857 :param list selList: indices of items to be selected. These indices 1858 are referenced to the order in self.ChoiceList 1859 ''' 1860 self.Selections = len(self.ChoiceList) * [False,] # reset selections 1861 for sel in selList: 1862 self.Selections[sel] = True 1863 self._ShowSelections() 1864 1865 def _ShowSelections(self): 1866 'Show the selection state for displayed items' 1867 if 'phoenix' in wx.version(): 1868 self.clb.SetCheckedItems( 1869 [i for i in range(len(self.filterlist)) if self.Selections[self.filterlist[i]]] 1870 ) # Note anything previously checked will be cleared. 1871 else: 1872 self.clb.SetChecked( 1873 [i for i in range(len(self.filterlist)) if self.Selections[self.filterlist[i]]] 1874 ) # Note anything previously checked will be cleared. 1875 if self.OnChange: 1876 self.OnChange(self.GetSelections(),*self.OnChangeArgs) 1877 self.SelectList.clear() 1878 for i,val in enumerate(self.Selections): 1879 if val: self.SelectList.append(i) 1880 1881 def _SetAll(self,event): 1882 'Set all viewed choices on' 1883 if 'phoenix' in wx.version(): 1884 self.clb.SetCheckedItems(range(0,len(self.filterlist),self.Stride)) 1885 else: 1886 self.clb.SetChecked(range(0,len(self.filterlist),self.Stride)) 1887 self.stride.SetValue('1') 1888 self.Stride = 1 1889 self.GetSelections() # record current selections 1890 self._ShowSelections() 1891 1892 def _ToggleAll(self,event): 1893 'flip the state of all viewed choices' 1894 for i in range(len(self.filterlist)): 1895 self.clb.Check(i,not self.clb.IsChecked(i)) 1896 self.GetSelections() # record current selections 1897 self._ShowSelections() 1898 1899 def onChar(self,event): 1900 'Respond to keyboard events in the Filter box' 1901 if self.timer.IsRunning(): 1902 self.timer.Stop() 1903 self.timer.Start(1000,oneShot=True) 1904 if event: event.Skip() 1905 1906 def OnCheck(self,event): 1907 '''for CheckListBox events; if Set Range is in use, this sets/clears all 1908 entries in range between start and end according to the value in start. 1909 Repeated clicks on the start change the checkbox state, but do not trigger 1910 the range copy. 1911 The caption next to the button is updated on the first button press. 1912 ''' 1913 if self.settingRange: 1914 id = event.GetInt() 1915 if self.rangeFirst is None: 1916 name = self.clb.GetString(id) 1917 self.rangeCapt.SetLabel(name+' to...') 1918 self.rangeFirst = id 1919 elif self.rangeFirst == id: 1920 pass 1921 else: 1922 for i in range(min(self.rangeFirst,id), max(self.rangeFirst,id)+1,self.Stride): 1923 self.clb.Check(i,self.clb.IsChecked(self.rangeFirst)) 1924 self.rangeBut.SetValue(False) 1925 self.rangeCapt.SetLabel('') 1926 self.settingRange = False 1927 self.rangeFirst = None 1928 self.GetSelections() # record current selections 1929 self._ShowSelections() 1930 1931 def Filter(self,event): 1932 '''Read text from filter control and select entries that match. Called by 1933 Timer after a delay with no input or if Enter is pressed. 1934 ''' 1935 if self.timer.IsRunning(): 1936 self.timer.Stop() 1937 self.GetSelections() # record current selections 1938 txt = self.filterBox.GetValue() 1939 self.clb.Clear() 1940 1941 self.filterlist = [] 1942 if txt: 1943 txt = txt.lower() 1944 ChoiceList = [] 1945 for i,item in enumerate(self.ChoiceList): 1946 if item.lower().find(txt) != -1: 1947 ChoiceList.append(item) 1948 self.filterlist.append(i) 1949 else: 1950 self.filterlist = range(len(self.ChoiceList)) 1951 ChoiceList = self.ChoiceList 1952 self.clb.AppendItems(ChoiceList) 1953 self._ShowSelections() 1954 1739 1955 def SelectEdit1Var(G2frame,array,labelLst,elemKeysLst,dspLst,refFlgElem): 1740 1956 '''Select a variable from a list, then edit it and select histograms -
trunk/GSASIIdataGUI.py
r4412 r4421 3772 3772 def OnAddPhase(self,event): 3773 3773 'Add a new, empty phase to the tree. Called by Data/Add Phase menu' 3774 self.CheckNotebook() 3774 3775 if not GetGPXtreeItemId(self,self.root,'Phases'): 3775 3776 sub = self.GPXtree.AppendItem(parent=self.root,text='Phases') … … 5426 5427 self.ResidueRBMenu = wx.Menu(title='') 5427 5428 self.ResidueRBMenu.Append(G2G.wxID_RIGIDBODYIMPORT,'Import XYZ','Import rigid body XYZ from file') 5428 self.ResidueRBMenu.Append(G2G.wxID_RIGIDBODYSAVE,'Save PDB','Save rigid body to PDB file') 5429 self.ResidueRBMenu.Append(G2G.wxID_RESIDUETORSSEQ,'Define sequence','Define torsion sequence') 5429 G2G.Define_wxId('wxID_RIGIDBODYIMP') 5430 self.ResidueRBMenu.Append(G2G.wxID_RIGIDBODYIMP,'Extract from file', 5431 'Extract rigid body from phase file') 5432 self.ResidueRBMenu.Append(G2G.wxID_RIGIDBODYSAVE,'Save as PDB','Save rigid body to PDB file') 5433 self.ResidueRBMenu.Append(G2G.wxID_RESIDUETORSSEQ,'Define torsion','Define torsion sequence') 5430 5434 self.ResidueRBMenu.Append(G2G.wxID_RIGIDBODYADD,'Import residues','Import residue rigid bodies from macro file') 5435 G2G.Define_wxId('wxID_RESBODYSAV') 5436 self.ResidueRBMenu.Append(G2G.wxID_RESBODYSAV,'Save rigid body','Write a rigid body to a file') 5437 G2G.Define_wxId('wxID_RESBODYRD') 5438 self.ResidueRBMenu.Append(G2G.wxID_RESBODYRD,'Read rigid body','Read a rigid body from a file') 5431 5439 self.RigidBodyMenu.Append(menu=self.ResidueRBMenu, title='Edit Residue Body') 5432 5440 self.PostfillDataMenu() … … 5437 5445 self.VectorRBEdit.Append(G2G.wxID_VECTORBODYADD,'Add rigid body','Add vector rigid body') 5438 5446 self.VectorBodyMenu.Append(menu=self.VectorRBEdit, title='Edit Vector Body') 5447 G2G.Define_wxId('wxID_VECTORBODYIMP') 5448 self.VectorRBEdit.Append(G2G.wxID_VECTORBODYIMP,'Extract from file', 5449 'Extract rigid body from phase file') 5450 G2G.Define_wxId('wxID_VECTORBODYSAV') 5451 self.VectorRBEdit.Append(G2G.wxID_VECTORBODYSAV,'Save rigid body','Write a rigid body to a file') 5452 G2G.Define_wxId('wxID_VECTORBODYRD') 5453 self.VectorRBEdit.Append(G2G.wxID_VECTORBODYRD,'Read rigid body','Read a rigid body from a file') 5454 G2G.Define_wxId('wxID_VECTORBODYEXTD') 5455 self.VectorRBEdit.Append(G2G.wxID_VECTORBODYEXTD,'Add translation', 5456 'Add translation to existing rigid body') 5439 5457 self.PostfillDataMenu() 5440 5458 … … 8386 8404 if grid.IsCellEditControlEnabled(): # complete any grid edits in progress 8387 8405 if GSASIIpath.GetConfigValue('debug'): print ('Completing grid edit in%s'%str(grid)) 8406 grid.SaveEditControlValue() 8407 # not sure if the next two things do anything 8388 8408 grid.HideCellEditControl() 8389 8409 grid.DisableCellEditControl() -
trunk/GSASIIlattice.py
r4415 r4421 19 19 The "*A* tensor" terms are defined as 20 20 :math:`A = (\\begin{matrix} G_{11} & G_{22} & G_{33} & 2G_{12} & 2G_{13} & 2G_{23}\\end{matrix})` and *A* can be used in this fashion: 21 :math:`d^* = \sqrt {A_ 1 h^2 + A_2 k^2 + A_3 l^2 + A_4 hk + A_5 hl + A_6kl}`, where21 :math:`d^* = \sqrt {A_0 h^2 + A_1 k^2 + A_2 l^2 + A_3 hk + A_4 hl + A_5 kl}`, where 22 22 *d* is the d-spacing, and :math:`d^*` is the reciprocal lattice spacing, 23 :math:`Q = 2 \\pi d^* = 2 \\pi / d` 23 :math:`Q = 2 \\pi d^* = 2 \\pi / d`. 24 Note that GSAS-II variables ``p::Ai`` (``i``=0,1,...5) and ``p`` is a phase number are 25 used for the *Ai* values. See :func:`A2cell`, :func:`cell2A` for interconversion between A and 26 unit cell parameters; :func:`cell2Gmat` :func:`Gmat2cell` for G and cell parameters. 27 28 When the hydrostatic/elastic strain coefficients (*Dij*, :math:`D_{ij}`) are used, they are added to the 29 *A* tensor terms (Ai, :math:`A_{i}`) so that A is redefined 30 :math:`A = (\\begin{matrix} A_{0} + D_{11} & A_{1} + D_{22} & A_{2} + D_{33} & A_{3} + 2D_{12} & A_{4} + 2D_{13} & A_{5} + 2D_{23}\\end{matrix})`. See :func:`cellDijFill`. 31 Note that GSAS-II variables ``p:h:Dij`` (``i``,``j``=1,2,3) and ``p`` is a phase number 32 and ``h`` a histogram number are used for the *Dij* values. 24 33 ''' 25 34 ########### SVN repository information ################### -
trunk/GSASIImath.py
r4415 r4421 935 935 936 936 def getAtomXYZ(atoms,cx): 937 ''' default doc string938 939 :param type name: description940 941 :returns: type name: description942 937 '''Create an array of fractional coordinates from the atoms list 938 939 :param list atoms: atoms object as found in tree 940 :param int cx: offset to where coordinates are found 941 942 :returns: np.array with shape (n,3) 943 943 ''' 944 944 XYZ = [] -
trunk/GSASIIplot.py
r4419 r4421 9703 9703 s = 1 9704 9704 selected = rbData.get('Selection') 9705 if len(XYZ) != len(rbData['rbTypes']): # H atoms have been removed 9706 return 9705 9707 for iat,atom in enumerate(XYZ): 9706 9708 if selected: -
trunk/GSASIIscriptable.py
r4411 r4421 1787 1787 1788 1788 :param list ImageReaderlist: list of Reader objects for images 1789 :param object ImageReaderlist: list of Reader objects for images1790 :param imageRef: A reference to the desired image . Either the Image1791 tree name (str), the image's index (int) or1789 :param object proj: references a :class:`G2Project` project 1790 :param imageRef: A reference to the desired image in the project. 1791 Either the Image tree name (str), the image's index (int) or 1792 1792 a image object (:class:`G2Image`) 1793 1793
Note: See TracChangeset
for help on using the changeset viewer.