Changeset 1138
- Timestamp:
- Nov 7, 2013 12:12:55 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASII.py
r1128 r1138 556 556 Id = self.PatternTree.AppendItem(parent=self.root, 557 557 text='HKLF '+HistName) 558 self.PatternTree.SetItemPyData(Id,[{'wtFactor':1.0,'Dummy':False},rd.RefDict]) 558 valuesdict = { 559 'wtFactor':1.0, 560 'Dummy':False, 561 'ranId':ran.randint(0,sys.maxint), 562 } 563 self.PatternTree.SetItemPyData(Id,[valuesdict,rd.RefDict]) 559 564 Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters') 560 565 self.PatternTree.SetItemPyData(Sub,rd.Parameters) … … 980 985 Tmin = min(rd.powderdata[0]) 981 986 Tmax = max(rd.powderdata[0]) 982 self.PatternTree.SetItemPyData(Id,[{'wtFactor':1.0,'Dummy':False},rd.powderdata]) 987 valuesdict = { 988 'wtFactor':1.0, 989 'Dummy':False, 990 'ranId':ran.randint(0,sys.maxint), 991 } 992 rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday 993 self.PatternTree.SetItemPyData(Id,[valuesdict,rd.powderdata]) 983 994 self.PatternTree.SetItemPyData( 984 995 self.PatternTree.AppendItem(Id,text='Comments'), … … 1093 1104 Id = self.PatternTree.AppendItem(parent=self.root, 1094 1105 text='PWDR '+inp[0]) 1095 self.PatternTree.SetItemPyData(Id,[{'wtFactor':1.0,'Dummy':True},rd.powderdata]) 1106 valuesdict = { 1107 'wtFactor':1.0, 1108 'Dummy':True, 1109 'ranId':ran.randint(0,sys.maxint), 1110 } 1111 self.PatternTree.SetItemPyData(Id,[valuesdict,rd.powderdata]) 1096 1112 self.PatternTree.SetItemPyData( 1097 1113 self.PatternTree.AppendItem(Id,text='Comments'), … … 1737 1753 def GetData(self): 1738 1754 return self.data 1739 1740 class ConstraintDialog(wx.Dialog): 1741 '''Window to edit Constraint values 1742 ''' 1743 def __init__(self,parent,title,text,data,separator='*'): 1744 wx.Dialog.__init__(self,parent,-1,title, 1745 pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) 1746 self.data = data 1747 panel = wx.Panel(self) 1748 mainSizer = wx.BoxSizer(wx.VERTICAL) 1749 topLabl = wx.StaticText(panel,-1,text) 1750 mainSizer.Add((10,10),1) 1751 mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10) 1752 mainSizer.Add((10,10),1) 1753 dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2) 1754 for id,item in enumerate(self.data[:-1]): 1755 lbl = item[1] 1756 if lbl[-1] != '=': lbl += ' ' + separator + ' ' 1757 name = wx.StaticText(panel,-1,lbl,size=wx.Size(200,20), 1758 style=wx.ALIGN_RIGHT) 1759 scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER) 1760 scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange) 1761 scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange) 1762 dataGridSizer.Add(name,0,wx.LEFT,10) 1763 dataGridSizer.Add(scale,0,wx.RIGHT,10) 1764 mainSizer.Add(dataGridSizer,0,wx.EXPAND) 1765 OkBtn = wx.Button(panel,-1,"Ok") 1766 OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) 1767 cancelBtn = wx.Button(panel,-1,"Cancel") 1768 cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) 1769 btnSizer = wx.BoxSizer(wx.HORIZONTAL) 1770 btnSizer.Add((20,20),1) 1771 btnSizer.Add(OkBtn) 1772 btnSizer.Add((20,20),1) 1773 btnSizer.Add(cancelBtn) 1774 btnSizer.Add((20,20),1) 1775 1776 mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) 1777 panel.SetSizer(mainSizer) 1778 panel.Fit() 1779 self.Fit() 1780 self.CenterOnParent() 1781 1782 def OnNameChange(self,event): 1783 self.data[-1] = self.name.GetValue() 1784 1785 def OnScaleChange(self,event): 1786 id = event.GetId() 1787 value = self.FindWindowById(id).GetValue() 1788 try: 1789 self.data[id][0] = float(value) 1790 self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0])) 1791 except ValueError: 1792 if value and '-' not in value[0]: 1793 print 'bad input - numbers only' 1794 self.FindWindowById(id).SetValue('0.000') 1795 1796 def OnOk(self,event): 1797 parent = self.GetParent() 1798 parent.Raise() 1799 self.EndModal(wx.ID_OK) 1800 1801 def OnCancel(self,event): 1802 parent = self.GetParent() 1803 parent.Raise() 1804 self.EndModal(wx.ID_CANCEL) 1805 1806 def GetData(self): 1807 return self.data 1808 1755 1809 1756 def OnPwdrSum(self,event): 1810 1757 'Sum together powder data(?)' … … 1886 1833 if Id: 1887 1834 Sample = G2pdG.SetDefaultSample() 1888 self.PatternTree.SetItemPyData(Id,[{'wtFactor':1.0,'Dummy':False},[np.array(Xsum),np.array(Ysum),np.array(Wsum), 1835 valuesdict = { 1836 'wtFactor':1.0, 1837 'Dummy':False, 1838 'ranId':ran.randint(0,sys.maxint), 1839 } 1840 self.PatternTree.SetItemPyData(Id,[valuesdict,[np.array(Xsum),np.array(Ysum),np.array(Wsum), 1889 1841 np.array(YCsum),np.array(YBsum),np.array(YDsum)]]) 1890 1842 self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments) … … 2457 2409 PWDRdata['Sample Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Sample Parameters')) 2458 2410 PWDRdata['Reflection Lists'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Reflection Lists')) 2459 if 'ranId' not in PWDRdata['Sample Parameters']: 2460 PWDRdata['Sample Parameters']['ranId'] = ran.randint(0,sys.maxint) 2461 PWDRdata['ranId'] = PWDRdata['Sample Parameters']['ranId'] 2411 if 'ranId' not in PWDRdata: # patch, add a random Id 2412 PWDRdata['ranId'] = ran.randint(0,sys.maxint) 2413 if 'ranId' not in PWDRdata['Sample Parameters']: # I hope this becomes obsolete at some point 2414 PWDRdata['Sample Parameters']['ranId'] = PWDRdata['ranId'] 2462 2415 return PWDRdata 2463 2416 … … 2483 2436 2484 2437 def GetPhaseData(self): 2485 '''Returns a list of defined phases. Used only in GSASIIgrid 2486 Note routine :meth:`GSASIIstruct.GetPhaseData` also exists. 2438 '''Returns a dict with defined phases. 2439 Note routine :func:`GSASIIstrIO.GetPhaseData` also exists to 2440 get same info from GPX file. 2487 2441 ''' 2488 2442 phaseData = {} … … 2490 2444 sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases') 2491 2445 else: 2492 print 'no phases to be refined'2493 return2446 print 'no phases found in GetPhaseData' 2447 sub = None 2494 2448 if sub: 2495 2449 item, cookie = self.PatternTree.GetFirstChild(sub) … … 2500 2454 phaseData[phaseName]['ranId'] = ran.randint(0,sys.maxint) 2501 2455 item, cookie = self.PatternTree.GetNextChild(sub, cookie) 2502 return phaseData 2456 return phaseData 2457 2458 def GetPhaseNames(self): 2459 '''Returns a list of defined phases. 2460 Note routine :func:`GSASIIstrIO.GetPhaseNames` also exists to 2461 get same info from GPX file. 2462 ''' 2463 phaseNames = [] 2464 if G2gd.GetPatternTreeItemId(self,self.root,'Phases'): 2465 sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases') 2466 else: 2467 print 'no phases found in GetPhaseNames' 2468 sub = None 2469 if sub: 2470 item, cookie = self.PatternTree.GetFirstChild(sub) 2471 while item: 2472 phase = self.PatternTree.GetItemText(item) 2473 phaseNames.append(phase) 2474 item, cookie = self.PatternTree.GetNextChild(sub, cookie) 2475 return phaseNames 2476 2477 def GetHistogramNames(self,hType): 2478 """ Returns a list of histogram names found in the GSASII data tree 2479 Note routine :func:`GSASIIstrIO.GetHistogramNames` also exists to 2480 get same info from GPX file. 2481 2482 :param str hType: list of histogram types 2483 :return: list of histogram names 2484 2485 """ 2486 HistogramNames = [] 2487 if self.PatternTree.GetCount(): 2488 item, cookie = self.PatternTree.GetFirstChild(self.root) 2489 while item: 2490 name = self.PatternTree.GetItemText(item) 2491 if name[:4] in hType: 2492 HistogramNames.append(name) 2493 item, cookie = self.PatternTree.GetNextChild(self.root, cookie) 2494 2495 return HistogramNames 2496 2503 2497 2504 2498 def GetUsedHistogramsAndPhasesfromTree(self): 2505 2499 ''' Returns all histograms that are found in any phase 2506 and any phase that uses a histogram 2507 :returns: two dicts: 2500 and any phase that uses a histogram. 2501 This also assigns numbers to used phases and histograms by the 2502 order they appear in the file. 2503 Note routine :func:`GSASIIstrIO.GetUsedHistogramsAndPhasesfromTree` also exists to 2504 get same info from GPX file. 2505 2506 :returns: (Histograms,Phases) 2508 2507 2509 2508 * Histograms = dictionary of histograms as {name:data,...} 2510 2509 * Phases = dictionary of phases that use histograms 2511 2510 ''' 2512 phaseData = self.GetPhaseData()2513 if not phaseData:2514 return {},{}2515 2511 Histograms = {} 2516 2512 Phases = {} 2513 phaseNames = self.GetPhaseNames() 2514 phaseData = self.GetPhaseData() 2515 histoList = self.GetHistogramNames(['PWDR','HKLF']) 2516 2517 2517 for phase in phaseData: 2518 2518 Phase = phaseData[phase] 2519 2519 if Phase['Histograms']: 2520 2520 if phase not in Phases: 2521 pId = phaseNames.index(phase) 2522 Phase['pId'] = pId 2521 2523 Phases[phase] = Phase 2522 2524 for hist in Phase['Histograms']: 2523 if hist not in Histograms: 2525 if 'Use' not in Phase['Histograms'][hist]: #patch: add Use flag as True 2526 Phase['Histograms'][hist]['Use'] = True 2527 if hist not in Histograms and Phase['Histograms'][hist]['Use']: 2524 2528 item = G2gd.GetPatternTreeItemId(self,self.root,hist) 2525 if 'PWDR' in hist[:4]: 2526 Histograms[hist] = self.GetPWDRdatafromTree(item) 2527 elif 'HKLF' in hist[:4]: 2528 Histograms[hist] = self.GetHKLFdatafromTree(item) 2529 #future restraint, etc. histograms here 2529 if item: 2530 if 'PWDR' in hist[:4]: 2531 Histograms[hist] = self.GetPWDRdatafromTree(item) 2532 elif 'HKLF' in hist[:4]: 2533 Histograms[hist] = self.GetHKLFdatafromTree(item) 2534 hId = histoList.index(hist) 2535 Histograms[hist]['hId'] = hId 2536 else: # would happen if a referenced histogram were renamed or deleted 2537 print('For phase "'+str(phase)+ 2538 '" unresolved reference to histogram "'+str(hist)+'"') 2530 2539 return Histograms,Phases 2531 2540 -
trunk/GSASIIIO.py
r1131 r1138 715 715 # 716 716 def ProjFileOpen(G2frame): 717 'Read a GSAS-II project file '717 'Read a GSAS-II project file and load into the G2 data tree' 718 718 file = open(G2frame.GSASprojectfile,'rb') 719 719 print 'load from file: ',G2frame.GSASprojectfile … … 731 731 Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text=datum[0]) 732 732 if 'PWDR' in datum[0]: 733 G2frame.PatternTree.SetItemPyData(Id,datum[1][:3]) #temp. trim off junk 733 if 'ranId' not in datum[1][0]: # patch: add random Id if not present 734 datum[1][0]['ranId'] = ran.randint(0,sys.maxint) 735 G2frame.PatternTree.SetItemPyData(Id,datum[1][:3]) #temp. trim off junk (patch?) 736 elif datum[0].startswith('HKLF'): 737 if 'ranId' not in datum[1][0]: # patch: add random Id if not present 738 datum[1][0]['ranId'] = ran.randint(0,sys.maxint) 739 G2frame.PatternTree.SetItemPyData(Id,datum[1]) 734 740 else: 735 741 G2frame.PatternTree.SetItemPyData(Id,datum[1]) … … 751 757 G2frame.imageDefault = Data 752 758 file.close() 753 print 'project load successful'759 print('project load successful') 754 760 G2frame.NewPlot = True 755 761 except: … … 783 789 finally: 784 790 wx.EndBusyCursor() 785 print 'project save successful'791 print('project save successful') 786 792 787 793 def SaveIntegration(G2frame,PickId,data): … … 847 853 G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Index Peak List'),[]) 848 854 G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Unit Cells List'),[]) 849 G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Reflection Lists'),{}) 850 G2frame.PatternTree.SetItemPyData(Id,[[''],[np.array(X),np.array(Y),np.array(W),np.zeros(N),np.zeros(N),np.zeros(N)]]) 855 G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Reflection Lists'),{}) 856 valuesdict = { 857 'wtFactor':1.0, 858 'Dummy':False, 859 'ranId':ran.randint(0,sys.maxint), 860 } 861 G2frame.PatternTree.SetItemPyData( 862 Id,[valuesdict, 863 [np.array(X),np.array(Y),np.array(W),np.zeros(N),np.zeros(N),np.zeros(N)]]) 851 864 G2frame.PatternTree.SelectItem(Id) 852 865 G2frame.PatternTree.Expand(Id) … … 1978 1991 # old GPX file from before pre-constraint varyList is saved 1979 1992 print ' *** Old refinement: Please use Calculate/Refine to redo ***' 1980 raise Exception(' *** CIF creationaborted ***')1993 raise Exception(' *** Export aborted ***') 1981 1994 else: 1982 1995 varyList = list(varyList) -
trunk/GSASIIconstrGUI.py
r1077 r1138 18 18 import wx 19 19 import wx.grid as wg 20 import wx.lib.scrolledpanel as wxscroll 20 21 import time 21 22 import random as ran … … 31 32 import GSASIIgrid as G2gd 32 33 import GSASIIplot as G2plt 34 import GSASIIobj as G2obj 33 35 VERY_LIGHT_GREY = wx.Colour(235,235,235) 34 36 … … 95 97 parent.Raise() 96 98 self.EndModal(wx.ID_CANCEL) 99 100 class ConstraintDialog(wx.Dialog): 101 '''Window to edit Constraint values 102 ''' 103 def __init__(self,parent,title,text,data,separator='*',varname="",varyflag=False): 104 wx.Dialog.__init__(self,parent,-1,'Edit '+title, 105 pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) 106 self.data = data[:] 107 self.newvar = [varname,varyflag] 108 panel = wx.Panel(self) 109 mainSizer = wx.BoxSizer(wx.VERTICAL) 110 topLabl = wx.StaticText(panel,-1,text) 111 mainSizer.Add((10,10),1) 112 mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10) 113 mainSizer.Add((10,10),1) 114 dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=3,hgap=2,vgap=2) 115 self.OkBtn = wx.Button(panel,wx.ID_OK) 116 for id in range(len(self.data)): 117 lbl1 = lbl = str(self.data[id][1]) 118 if lbl[-1] != '=': lbl1 = lbl + ' ' + separator + ' ' 119 name = wx.StaticText(panel,wx.ID_ANY,lbl1, 120 style=wx.ALIGN_RIGHT) 121 scale = G2gd.ValidatedTxtCtrl(panel,self.data[id],0, 122 typeHint=float, 123 OKcontrol=self.DisableOK) 124 dataGridSizer.Add(name,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,5) 125 dataGridSizer.Add(scale,0,wx.RIGHT,3) 126 if ':' in lbl: 127 dataGridSizer.Add( 128 wx.StaticText(panel,-1,G2obj.fmtVarDescr(lbl)), 129 0,wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,3) 130 else: 131 dataGridSizer.Add((-1,-1)) 132 if title == 'New Variable': 133 name = wx.StaticText(panel,wx.ID_ANY,"New variable's\nname (optional)", 134 style=wx.ALIGN_CENTER) 135 scale = G2gd.ValidatedTxtCtrl(panel,self.newvar,0, 136 typeHint=str,notBlank=False) 137 dataGridSizer.Add(name,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,5) 138 dataGridSizer.Add(scale,0,wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,3) 139 self.refine = wx.CheckBox(panel,label='Refine?') 140 self.refine.SetValue(self.newvar[1]==True) 141 self.refine.Bind(wx.EVT_CHECKBOX, self.OnCheckBox) 142 dataGridSizer.Add(self.refine,0,wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,3) 143 144 mainSizer.Add(dataGridSizer,0,wx.EXPAND) 145 self.OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) 146 self.OkBtn.SetDefault() 147 cancelBtn = wx.Button(panel,wx.ID_CANCEL) 148 cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) 149 btnSizer = wx.BoxSizer(wx.HORIZONTAL) 150 btnSizer.Add((20,20),1) 151 btnSizer.Add(self.OkBtn) 152 btnSizer.Add((20,20),1) 153 btnSizer.Add(cancelBtn) 154 btnSizer.Add((20,20),1) 155 156 mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) 157 panel.SetSizer(mainSizer) 158 panel.Fit() 159 self.Fit() 160 self.CenterOnParent() 161 162 def DisableOK(self,setting): 163 if setting: 164 self.OkBtn.Enable() 165 else: 166 self.OkBtn.Disable() 167 168 def OnCheckBox(self,event): 169 self.newvar[1] = self.refine.GetValue() 170 171 def OnOk(self,event): 172 parent = self.GetParent() 173 parent.Raise() 174 self.EndModal(wx.ID_OK) 175 176 def OnCancel(self,event): 177 parent = self.GetParent() 178 parent.Raise() 179 self.EndModal(wx.ID_CANCEL) 180 181 def GetData(self): 182 return self.data 97 183 98 184 ################################################################################ … … 108 194 if 'Global' not in data: #patch 109 195 data['Global'] = [] 110 Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree() 111 rigidbodyDict = G2frame.PatternTree.GetItemPyData( 196 # DEBUG code ######################################## 197 #import GSASIIconstrGUI 198 #reload(GSASIIconstrGUI) 199 #reload(G2obj) 200 #reload(G2stIO) 201 #import GSASIIstrMain 202 #reload(GSASIIstrMain) 203 #reload(G2mv) 204 #reload(G2gd) 205 ################################################### 206 Histograms,Phases = G2obj.IndexAllIds(G2frame) 207 ################################################################################## 208 # patch: convert old-style (str) variables in constraints to G2VarObj objects 209 for key,value in data.items(): 210 j = 0 211 for cons in value: 212 #print cons # DEBUG 213 for i in range(len(cons[:-3])): 214 if type(cons[i][1]) is str: 215 cons[i][1] = G2obj.G2VarObj(cons[i][1]) 216 j += 1 217 if j: 218 print str(key) + ': '+str(j)+' variable(s) strings converted to objects' 219 ################################################################################## 220 rigidbodyDict = G2frame.PatternTree.GetItemPyData( 112 221 G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies')) 113 222 rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]}) … … 152 261 histList.sort() 153 262 Indx = {} 154 scope = {} #filled out later155 263 G2frame.Page = [0,'phs'] 156 157 def GetPHlegends(Phases,Histograms):158 plegend = '\n In p::name'159 hlegend = '\n In :h:name'160 phlegend = '\n In p:h:name'161 glegend = '\n In ::name'162 for phase in Phases:163 plegend += '\n p:: = '+str(Phases[phase]['pId'])+':: for '+phase164 count = 0165 for histogram in Phases[phase]['Histograms']:166 if count < 3:167 phlegend += '\n p:h: = '+str(Phases[phase]['pId'])+':'+str(Histograms[histogram]['hId'])+': for '+phase+' in '+histogram168 else:169 phlegend += '\n ... etc.'170 break171 count += 1172 count = 0173 for histogram in Histograms:174 if count < 3:175 hlegend += '\n :h: = :'+str(Histograms[histogram]['hId'])+': for '+histogram176 else:177 hlegend += '\n ... etc.'178 break179 count += 1180 return plegend,hlegend,phlegend,glegend181 264 182 265 def FindEquivVarb(name,nameList): 266 'Creates a list of variables appropriate to constrain with name' 183 267 outList = [] 184 268 phlist = [] … … 205 289 if keys[2] in namelist and item != name: 206 290 outList.append(item) 207 if items[1]:208 for key in phlist:209 outList.append(key+':all:'+items[2])210 291 return outList 211 292 212 293 def SelectVarbs(page,FrstVarb,varList,legend,constType): 213 '''Select variables used in Constraints after one variable has 214 been selected which determines the appropriate variables to be 215 used here. Then creates the constraint and adds it to the 216 constraints list. 217 Called from OnAddEquivalence, OnAddFunction & OnAddConstraint 294 '''Select variables used in constraints after one variable has 295 been selected. This routine determines the appropriate variables to be 296 used based on the one that has been selected and asks for more to be added. 297 298 It then creates the constraint and adds it to the constraints list. 299 300 Called from OnAddEquivalence, OnAddFunction & OnAddConstraint (all but 301 OnAddHold) 302 303 :param list page: defines calling page -- type of variables to be used 304 :parm GSASIIobj.G2VarObj FrstVarb: reference to first selected variable 305 :param list varList: list of other appropriate variables to select from 306 :param str legend: header for selection dialog 307 :param str constType: type of constraint to be generated 308 :returns: a constraint, as defined in 309 :ref:`GSASIIobj <Constraint_definitions_table>` 218 310 ''' 219 #future - add 'all:all:name', '0:all:name', etc. to the varList 311 atchoice = ["("+i+") "+G2obj.fmtVarDescr(i) for i in varList] 312 meaning = G2obj.getDescr(FrstVarb.name) 313 if not meaning: 314 meaning = "(no definition found!)" 315 l = str(FrstVarb).split(':') 316 # make lists of phases & histograms to iterate over 317 phaselist = [l[0]] 318 if l[0]: 319 phaselbl = ['phase #'+l[0]] 320 if len(Phases) > 1: 321 phaselist += ['all'] 322 phaselbl += ['all phases'] 323 else: 324 phaselbl = [''] 325 histlist = [l[1]] 326 if l[1]: 327 histlbl = ['histogram #'+l[1]] 328 if len(Histograms) > 1: 329 histlist += ['all'] 330 histlbl += ['all histograms'] 331 typ = Histograms[G2obj.LookupHistName(l[1])[0]]['Instrument Parameters'][0]['Type'][1] 332 i = 0 333 for hist in Histograms: 334 if Histograms[hist]['Instrument Parameters'][0]['Type'][1] == typ: i += 1 335 if i > 1: 336 histlist += ['all='+typ] 337 histlbl += ['all '+typ+' histograms'] 338 else: 339 histlbl = [''] 340 # make a list of equivalent parameter names 341 nameList = [FrstVarb.name] 342 for var in varList: 343 nam = var.split(":")[2] 344 if nam not in nameList: nameList += [nam] 345 # add "wild-card" names to the list of variables 220 346 if page[1] == 'phs': 221 atchoice = [item+' for '+phaseAtNames[item] for item in varList] 222 if 'RB' not in FrstVarb: 223 atchoice += [FrstVarb+' for all'] 224 atchoice += [FrstVarb+' for all '+atype for atype in TypeList] 225 dlg = wx.MultiChoiceDialog(G2frame,'Select more variables:'+legend, 226 'Constrain '+FrstVarb+' and...',atchoice) 347 if 'RB' in FrstVarb.name: 348 pass 349 elif FrstVarb.atom is None: 350 for nam in nameList: 351 for ph,plbl in zip(phaselist,phaselbl): 352 if plbl: plbl = 'For ' + plbl 353 var = ph+"::"+nam 354 if var == str(FrstVarb) or var in varList: continue 355 varList += [var] 356 atchoice += ['('+var+') '+plbl+": "+meaning] 357 else: 358 for nam in nameList: 359 for ph,plbl in zip(phaselist,phaselbl): 360 if plbl: plbl = ' in ' + plbl 361 for atype in ['']+TypeList: 362 if atype: 363 albl = "For "+atype+" atoms" 364 akey = "all="+atype 365 else: 366 albl = "For all atoms" 367 akey = "all" 368 var = ph+"::"+nam+":"+akey 369 if var == str(FrstVarb) or var in varList: continue 370 varList += [var] 371 atchoice += ['('+var+') '+albl+plbl+": "+meaning] 372 elif page[1] == 'hap': 373 for nam in nameList: 374 for ph,plbl in zip(phaselist,phaselbl): 375 if plbl: plbl = 'For ' + plbl 376 for hst,hlbl in zip(histlist,histlbl): 377 if hlbl: 378 if plbl: 379 hlbl = ' in ' + hlbl 380 else: 381 hlbl = 'For ' + hlbl 382 var = ph+":"+hst+":"+nam 383 if var == str(FrstVarb) or var in varList: continue 384 varList += [var] 385 atchoice += ['('+var+') '+plbl+hlbl+": "+meaning] 386 elif page[1] == 'hst': 387 for nam in nameList: 388 for hst,hlbl in zip(histlist,histlbl): 389 if hlbl: 390 hlbl = 'For ' + hlbl 391 var = ":"+hst+":"+nam 392 if var == str(FrstVarb) or var in varList: continue 393 varList += [var] 394 atchoice += ['('+var+') '+hlbl+": "+meaning] 395 elif page[1] == 'glb': 396 pass 227 397 else: 228 dlg = wx.MultiChoiceDialog(G2frame,'Select more variables:'+legend, 229 'Constrain '+FrstVarb+' and...',varList) 230 varbs = [FrstVarb,] 231 if dlg.ShowModal() == wx.ID_OK: 232 sel = dlg.GetSelections() 233 try: 234 for x in sel: 235 if ':all:' in varList[x]: #a histogram 'all' - supercedes any individual selection 236 varbs = [FrstVarb,] 237 items = varList[x].split(':') 238 for item in varList: 239 if items[0] == item.split(':')[0] and ':all:' not in item: 240 varbs.append(item) 241 break 242 else: 243 varbs.append(varList[x]) 244 except IndexError: # one of the 'all' chosen - supercedes any individual selection 245 varbs = [FrstVarb,] 246 Atypes = [] 247 for x in sel: 248 item = atchoice[x] 249 if 'all' in item: 250 Atypes.append(item.split('all')[1].strip()) 251 if '' in Atypes: 252 varbs += varList 398 raise Exception, 'Unknown constraint page '+ page[1] 399 if len(atchoice): 400 dlg = wx.MultiChoiceDialog( 401 G2frame.dataFrame,legend, 402 'Constrain '+str(FrstVarb)+' with...',atchoice) 403 dlg.SetSize((625,250)) 404 dlg.CenterOnParent() 405 res = dlg.ShowModal() 406 Selections = dlg.GetSelections()[:] 407 dlg.Destroy() 408 if res != wx.ID_OK: return [] 409 if len(Selections) == 0: 410 dlg = wx.MessageDialog( 411 G2frame.dataFrame, 412 'No variables were selected to include with '+str(FrstVarb), 413 'No variables') 414 dlg.CenterOnParent() 415 dlg.ShowModal() 416 dlg.Destroy() 417 return [] 418 else: 419 dlg = wx.MessageDialog( 420 G2frame.dataFrame, 421 'There are no appropriate variables to include with '+str(FrstVarb), 422 'No variables') 423 dlg.CenterOnParent() 424 dlg.ShowModal() 425 dlg.Destroy() 426 return [] 427 # now process the variables provided by the user 428 varbs = [str(FrstVarb),] # list of selected variables 429 for sel in Selections: 430 var = varList[sel] 431 # phase(s) included 432 l = var.split(':') 433 if l[0] == "all": 434 phlist = [str(Phases[phase]['pId']) for phase in Phases] 435 else: 436 phlist = [l[0]] 437 # histogram(s) included 438 if l[1] == "all": 439 hstlist = [str(Histograms[hist]['hId']) for hist in Histograms] 440 elif '=' in l[1]: 441 htyp = l[1].split('=')[1] 442 hstlist = [str(Histograms[hist]['hId']) for hist in Histograms if 443 Histograms[hist]['Instrument Parameters'][0]['Type'][1] == htyp] 444 else: 445 hstlist = [l[1]] 446 if len(l) == 3: 447 for ph in phlist: 448 for hst in hstlist: 449 var = ph + ":" + hst + ":" + l[2] 450 if var in varbs: continue 451 varbs.append(var) 452 else: # constraints with atoms 453 if l[3] == "all": 454 for ph in phlist: 455 key = G2obj.LookupPhaseName(l[0])[0] 456 for hst in hstlist: # should be blank 457 for iatm,at in enumerate(Phases[key]['Atoms']): 458 var = ph + ":" + hst + ":" + l[2] + ":" + str(iatm) 459 if var in varbs: continue 460 varbs.append(var) 461 elif '=' in l[3]: 462 for ph in phlist: 463 key = G2obj.LookupPhaseName(l[0])[0] 464 cx,ct,cs,cia = Phases[key]['General']['AtomPtrs'] 465 for hst in hstlist: # should be blank 466 atyp = l[3].split('=')[1] 467 for iatm,at in enumerate(Phases[key]['Atoms']): 468 if at[ct] != atyp: continue 469 var = ph + ":" + hst + ":" + l[2] + ":" + str(iatm) 470 if var in varbs: continue 471 varbs.append(var) 253 472 else: 254 for item in varList: 255 if phaseAtTypes[item] in Atypes: 256 varbs.append(item) 257 dlg.Destroy() 258 if len(varbs) > 1: 473 for ph in phlist: 474 key = G2obj.LookupPhaseName(l[0])[0] 475 for hst in hstlist: # should be blank 476 var = ph + ":" + hst + ":" + l[2] + ":" + l[3] 477 if var in varbs: continue 478 varbs.append(var) 479 if len(varbs) >= 1 or 'constraint' in constType: 480 constr = [[1.0,FrstVarb]] 481 for item in varbs[1:]: 482 constr += [[1.0,G2obj.G2VarObj(item)]] 259 483 if 'equivalence' in constType: 260 constr = [[1.0,FrstVarb]] 261 for item in varbs[1:]: 262 constr += [[1.0,item]] 263 return [constr+[None,None,'e']] # list of equivalent variables & mults 484 return [constr+[None,None,'e']] 264 485 elif 'function' in constType: 265 constr = map(list,zip([1.0 for i in range(len(varbs))],varbs)) 266 return [constr+[None,False,'f']] #just one constraint 267 else: #'constraint' 268 constr = map(list,zip([1.0 for i in range(len(varbs))],varbs)) 269 return [constr+[1.0,None,'c']] #just one constraint - default sum to one 486 return [constr+[None,False,'f']] 487 elif 'constraint' in constType: 488 return [constr+[1.0,None,'c']] 489 else: 490 raise Exception,'Unknown constraint type: '+str(constType) 491 else: 492 dlg = wx.MessageDialog( 493 G2frame.dataFrame, 494 'There are no selected variables to include with '+str(FrstVarb), 495 'No variables') 496 dlg.CenterOnParent() 497 dlg.ShowModal() 498 dlg.Destroy() 270 499 return [] 271 500 … … 277 506 Since the varylist is not available, no warning messages 278 507 should be generated. 279 Returns True if constraint should be added 508 509 :returns: True if constraint should be added 280 510 ''' 281 511 allcons = [] … … 303 533 Since the varylist is not available, no warning messages 304 534 should be generated. 305 Returns True if the edit should be retained 535 536 :returns: True if the edit should be retained 306 537 ''' 307 538 allcons = [] … … 322 553 return True 323 554 555 def PageSelection(page): 556 'Decode page reference' 557 if page[1] == "phs": 558 vartype = "phase" 559 varList = phaseList 560 constrDictEnt = 'Phase' 561 elif page[1] == "hap": 562 vartype = "Histogram*Phase" 563 varList = hapList 564 constrDictEnt = 'HAP' 565 elif page[1] == "hst": 566 vartype = "Histogram" 567 varList = histList 568 constrDictEnt = 'Hist' 569 elif page[1] == "glb": 570 vartype = "Global" 571 varList = globalList 572 constrDictEnt = 'Global' 573 else: 574 raise Exception,'Should not happen!' 575 return vartype,varList,constrDictEnt 576 324 577 def OnAddHold(event): 325 ''' add a Hold constraint'''326 for phase in Phases: 327 Phase = Phases[phase]328 Atoms = Phase['Atoms']329 constr = []578 '''Create a new Hold constraint 579 580 Hold constraints allows the user to select one variable (the list of available 581 variables depends on which tab is currently active). 582 ''' 330 583 page = G2frame.Page 331 choice = scope[page[1]] 332 if page[1] == 'phs': 333 atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]] 334 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice) 335 else: 336 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2]) 584 vartype,varList,constrDictEnt = PageSelection(page) 585 title1 = "Hold "+vartype+" variable" 586 if not varList: 587 G2frame.ErrorDialog('No variables','There are no variables of type '+vartype, 588 parent=G2frame.dataFrame) 589 return 590 varListlbl = ["("+i+") "+G2obj.fmtVarDescr(i) for i in varList] 591 legend = "Select variables to hold (Will not be varied, even if vary flag is set)" 592 dlg = G2gd.G2MultiChoiceDialog( 593 G2frame.dataFrame, 594 legend,title1,varListlbl,toggle=False,size=(625,250)) 595 dlg.CenterOnParent() 337 596 if dlg.ShowModal() == wx.ID_OK: 338 sel = dlg.GetSelection() 339 FrstVarb = choice[2][sel] 340 newcons = [[[0.0,FrstVarb],None,None,'h']] 341 if CheckAddedConstraint(newcons): 342 data[choice[3]] += newcons 597 for sel in dlg.GetSelections(): 598 Varb = varList[sel] 599 VarObj = G2obj.G2VarObj(Varb) 600 newcons = [[[0.0,VarObj],None,None,'h']] 601 if CheckAddedConstraint(newcons): 602 data[constrDictEnt] += newcons 343 603 dlg.Destroy() 344 choice[4]()604 OnPageChanged(None) 345 605 346 606 def OnAddEquivalence(event): 347 607 '''add an Equivalence constraint''' 348 constr = []349 608 page = G2frame.Page 350 choice = scope[page[1]] 351 if page[1] == 'phs': 352 atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]] 353 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice) 354 else: 355 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2]) 356 if dlg.ShowModal() == wx.ID_OK: 357 sel = dlg.GetSelection() 358 FrstVarb = choice[2][sel] 359 moreVarb = FindEquivVarb(FrstVarb,choice[2]) 360 newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'equivalence') 361 if len(newcons) > 0: 362 if CheckAddedConstraint(newcons): 363 data[choice[3]] += newcons 364 dlg.Destroy() 365 choice[4]() 609 vartype,varList,constrDictEnt = PageSelection(page) 610 title1 = "Setup equivalent "+vartype+" variables" 611 title2 = "Select additional "+vartype+" variable(s) to be equivalent with " 612 if not varList: 613 G2frame.ErrorDialog('No variables','There are no variables of type '+vartype, 614 parent=G2frame.dataFrame) 615 return 616 varListlbl = ["("+i+") "+G2obj.fmtVarDescr(i) for i in varList] 617 legend = "Select variables to make equivalent (only one of the variables will be varied when all are set to be varied)" 618 GetAddVars(page,title1,title2,varList,varListlbl,constrDictEnt,'equivalence') 366 619 367 620 def OnAddFunction(event): 368 621 '''add a Function (new variable) constraint''' 369 constr = []370 622 page = G2frame.Page 371 choice = scope[page[1]] 372 if page[1] == 'phs': 373 atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]] 374 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice) 375 else: 376 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2]) 377 if dlg.ShowModal() == wx.ID_OK: 378 sel = dlg.GetSelection() 379 FrstVarb = choice[2][sel] 380 moreVarb = FindEquivVarb(FrstVarb,choice[2]) 381 newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'function') 382 if len(newcons) > 0: 383 if CheckAddedConstraint(newcons): 384 data[choice[3]] += newcons 385 dlg.Destroy() 386 choice[4]() 623 vartype,varList,constrDictEnt = PageSelection(page) 624 title1 = "Setup new variable based on "+vartype+" variables" 625 title2 = "Include additional "+vartype+" variable(s) to be included with " 626 if not varList: 627 G2frame.ErrorDialog('No variables','There are no variables of type '+vartype, 628 parent=G2frame.dataFrame) 629 return 630 varListlbl = ["("+i+") "+G2obj.fmtVarDescr(i) for i in varList] 631 legend = "Select variables to include in a new variable (the new variable will be varied when all included variables are varied)" 632 GetAddVars(page,title1,title2,varList,varListlbl,constrDictEnt,'function') 387 633 388 634 def OnAddConstraint(event): 389 635 '''add a constraint equation to the constraints list''' 390 constr = []391 636 page = G2frame.Page 392 choice = scope[page[1]] 393 if page[1] == 'phs': 394 atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]] 395 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice) 396 else: 397 dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2]) 637 vartype,varList,constrDictEnt = PageSelection(page) 638 title1 = "Setup constraint on "+vartype+" variables" 639 title2 = "Select additional "+vartype+" variable(s) to include in constraint with " 640 if not varList: 641 G2frame.ErrorDialog('No variables','There are no variables of type '+vartype, 642 parent=G2frame.dataFrame) 643 return 644 varListlbl = ["("+i+") "+G2obj.fmtVarDescr(i) for i in varList] 645 legend = "Select variables to include in a constraint equation (the values will be constrainted to equal a specified constant)" 646 GetAddVars(page,title1,title2,varList,varListlbl,constrDictEnt,'constraint') 647 648 def GetAddVars(page,title1,title2,varList,varListlbl,constrDictEnt,constType): 649 '''Get the variables to be added for OnAddEquivalence, OnAddFunction, 650 and OnAddConstraint. Then create and check the constraint. 651 ''' 652 dlg = wx.SingleChoiceDialog(G2frame.dataFrame,'Select 1st variable:',title1,varListlbl) 653 dlg.SetSize((625,250)) 654 dlg.CenterOnParent() 398 655 if dlg.ShowModal() == wx.ID_OK: 399 656 sel = dlg.GetSelection() 400 FrstVarb = choice[2][sel] 401 moreVarb = FindEquivVarb(FrstVarb,choice[2]) 402 newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'constraint') 657 FrstVarb = varList[sel] 658 VarObj = G2obj.G2VarObj(FrstVarb) 659 moreVarb = FindEquivVarb(FrstVarb,varList) 660 newcons = SelectVarbs(page,VarObj,moreVarb,title2+FrstVarb,constType) 403 661 if len(newcons) > 0: 404 662 if CheckAddedConstraint(newcons): 405 data[c hoice[3]] += newcons663 data[constrDictEnt] += newcons 406 664 dlg.Destroy() 407 choice[4]()665 OnPageChanged(None) 408 666 409 def ConstSizer(name,pageDisplay): 410 '''This creates a sizer displaying all of the constraints entered 667 def MakeConstraintsSizer(name,pageDisplay): 668 '''Creates a sizer displaying all of the constraints entered of 669 the specified type. 670 671 :param str name: the type of constraints to be displayed ('HAP', 672 'Hist', 'Phase', or 'Global') 673 :param wx.Panel pageDisplay: parent panel for sizer 674 :returns: wx.Sizer created by method 411 675 ''' 412 constSizer = wx.FlexGridSizer(1, 4,0,0)676 constSizer = wx.FlexGridSizer(1,5,0,0) 413 677 maxlen = 70 # characters before wrapping a constraint 414 678 for Id,item in enumerate(data[name]): 679 helptext = "" 415 680 eqString = ['',] 416 if item[-1] == 'h': 417 constSizer.Add((5,5),0) # blank space for edit button 418 typeString = ' FIXED ' 419 eqString[-1] = item[0][1]+' ' 420 elif isinstance(item[-1],str): 681 if item[-1] == 'h': # Hold on variable 682 constSizer.Add((-1,-1),0) # blank space for edit button 683 typeString = 'FIXED' 684 var = str(item[0][1]) 685 varMean = G2obj.fmtVarDescr(var) 686 eqString[-1] = var +' ' 687 helptext = "Prevents variable:\n"+ var + " ("+ varMean + ")\nfrom being changed" 688 elif isinstance(item[-1],str): # not true on original-style (2011?) constraints 421 689 constEdit = wx.Button(pageDisplay,-1,'Edit',style=wx.BU_EXACTFIT) 422 690 constEdit.Bind(wx.EVT_BUTTON,OnConstEdit) 423 constSizer.Add(constEdit ) # edit button691 constSizer.Add(constEdit,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER,1) # edit button 424 692 Indx[constEdit.GetId()] = [Id,name] 425 693 if item[-1] == 'f': 694 helptext = "A new variable is created from a linear combination of the following variables:" 426 695 for term in item[:-3]: 696 var = str(term[1]) 427 697 if len(eqString[-1]) > maxlen: 428 698 eqString.append(' ') … … 434 704 eqString[-1] += ' - ' 435 705 m = abs(m) 436 eqString[-1] += '%.3f*%s '%(m,term[1]) 437 typeString = ' NEWVAR ' 706 eqString[-1] += '%.3f*%s '%(m,var) 707 varMean = G2obj.fmtVarDescr(var) 708 helptext += "\n" + var + " ("+ varMean + ")" 709 typeString = 'NEWVAR' 438 710 eqString[-1] += ' = New Variable ' 439 711 elif item[-1] == 'c': 712 helptext = "The following variables constrained to equal a constant:" 440 713 for term in item[:-3]: 714 var = str(term[1]) 441 715 if len(eqString[-1]) > maxlen: 442 716 eqString.append(' ') … … 446 720 else: 447 721 eqString[-1] += ' - ' 448 eqString[-1] += '%.3f*%s '%(abs(term[0]),term[1]) 449 typeString = ' CONSTR ' 722 eqString[-1] += '%.3f*%s '%(abs(term[0]),var) 723 varMean = G2obj.fmtVarDescr(var) 724 helptext += "\n" + var + " ("+ varMean + ")" 725 typeString = 'CONST' 450 726 eqString[-1] += ' = %.3f'%(item[-3])+' ' 451 727 elif item[-1] == 'e': 728 helptext = "The following variables are set to be equivalent, noting multipliers:" 452 729 for term in item[:-3]: 730 var = str(term[1]) 453 731 if term[0] == 0: term[0] = 1.0 454 732 if len(eqString[-1]) > maxlen: 455 733 eqString.append(' ') 456 734 if eqString[-1] == '': 457 eqString[-1] += '%s '%(term[1])735 eqString[-1] += var+' ' 458 736 first = term[0] 459 737 else: 460 eqString[-1] += ' = %.3f*%s '%(first/term[0],term[1]) 461 typeString = ' EQUIV ' 738 eqString[-1] += ' = %.3f*%s '%(first/term[0],var) 739 varMean = G2obj.fmtVarDescr(var) 740 helptext += "\n" + var + " ("+ varMean + ")" 741 typeString = 'EQUIV' 462 742 else: 463 743 print 'Unexpected constraint',item 744 464 745 else: 465 746 print 'Removing old-style constraints' … … 469 750 constDel.Bind(wx.EVT_BUTTON,OnConstDel) 470 751 Indx[constDel.GetId()] = [Id,name] 471 constSizer.Add(constDel ) # delete button472 constSizer.Add(wx.StaticText(pageDisplay,-1,typeString),0,wx.ALIGN_CENTER_VERTICAL)473 EqSizer = wx.BoxSizer(wx.VERTICAL)474 for s in eqString:475 EqSizer.Add(wx.StaticText(pageDisplay,-1,s),0,wx.ALIGN_CENTER_VERTICAL)476 constSizer.Add(EqSizer,0,wx.ALIGN_CENTER_VERTICAL)477 # if item[-1] == 'f':478 # constRef = wx.CheckBox(pageDisplay,-1,label=' Refine?')479 # constRef.SetValue(item[-2])480 # constRef.Bind(wx.EVT_CHECKBOX,OnConstRef)481 # Indx[constRef.GetId()] = item482 # constSizer.Add(constRef)483 # else:484 # constSizer.Add((5,5),0)752 constSizer.Add(constDel,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER,1) # delete button 753 if helptext: 754 ch = G2gd.HelpButton(pageDisplay,helptext) 755 constSizer.Add(ch,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER,1) 756 else: 757 constSizer.Add((-1,-1)) 758 constSizer.Add(wx.StaticText(pageDisplay,-1,typeString),0,wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER|wx.RIGHT|wx.LEFT,3) 759 if len(eqString) > 1: 760 Eq = wx.BoxSizer(wx.VERTICAL) 761 for s in eqString: 762 Eq.Add(wx.StaticText(pageDisplay,-1,s),0,wx.ALIGN_CENTER_VERTICAL) 763 else: 764 Eq = wx.StaticText(pageDisplay,-1,eqString[0]) 765 constSizer.Add(Eq,1,wx.ALIGN_CENTER_VERTICAL) 485 766 return constSizer 486 767 487 # def OnConstRef(event):488 # Obj = event.GetEventObject()489 # Indx[Obj.GetId()][-2] = Obj.GetValue()490 491 768 def OnConstDel(event): 769 'Delete a constraint' 492 770 Obj = event.GetEventObject() 493 771 Id,name = Indx[Obj.GetId()] … … 496 774 497 775 def OnConstEdit(event): 498 '''Called to edit an individual contraint by the Edit button''' 776 '''Called to edit an individual contraint in response to a 777 click on its Edit button 778 ''' 499 779 Obj = event.GetEventObject() 500 780 Id,name = Indx[Obj.GetId()] 501 sep = '*'502 781 if data[name][Id][-1] == 'f': 503 items = data[name][Id][:-3] +[[],]782 items = data[name][Id][:-3] 504 783 constType = 'New Variable' 784 if data[name][Id][-3]: 785 varname = data[name][Id][-3] 786 else: 787 varname = "" 505 788 lbl = 'Enter value for each term in constraint; sum = new variable' 789 dlg = ConstraintDialog(G2frame.dataFrame,constType,lbl,items, 790 varname=varname,varyflag=data[name][Id][-2]) 506 791 elif data[name][Id][-1] == 'c': 507 792 items = data[name][Id][:-3]+[ 508 [data[name][Id][-3],'fixed value ='] ,[]]793 [data[name][Id][-3],'fixed value =']] 509 794 constType = 'Constraint' 510 795 lbl = 'Edit value for each term in constant constraint sum' 796 dlg = ConstraintDialog(G2frame.dataFrame,constType,lbl,items) 511 797 elif data[name][Id][-1] == 'e': 512 items = data[name][Id][:-3] +[[],]798 items = data[name][Id][:-3] 513 799 constType = 'Equivalence' 514 800 lbl = 'The following terms are set to be equal:' 515 sep = '/'801 dlg = ConstraintDialog(G2frame.dataFrame,constType,lbl,items,'/') 516 802 else: 517 803 return 518 dlg = G2frame.ConstraintDialog(G2frame.dataFrame,constType,lbl,items,sep)519 804 try: 805 prev = data[name][Id][:] 520 806 if dlg.ShowModal() == wx.ID_OK: 521 prev = data[name][Id]522 807 result = dlg.GetData() 808 for i in range(len(data[name][Id][:-3])): 809 data[name][Id][i][0] = result[i][0] 523 810 if data[name][Id][-1] == 'c': 524 data[name][Id][:-3] = result[:-2] 525 data[name][Id][-3] = result[-2][0] 526 else: 527 data[name][Id][:-3] = result[:-1] 811 data[name][Id][-3] = str(result[-1][0]) 812 elif data[name][Id][-1] == 'f': 813 # process the variable name to put in global form (::var) 814 varname = str(dlg.newvar[0]).strip().replace(' ','_') 815 if varname.startswith('::'): 816 varname = varname[2:] 817 varname = varname.replace(':',';') 818 if varname: 819 data[name][Id][-3] = '::' + varname 820 else: 821 data[name][Id][-3] = '' 822 data[name][Id][-2] = dlg.newvar[1] 528 823 if not CheckChangedConstraint(): 529 824 data[name][Id] = prev … … 534 829 dlg.Destroy() 535 830 OnPageChanged(None) 536 537 def UpdateHAPConstr(): 538 '''Responds to press on Histogram/Phase Constraints tab, 539 shows constraints in data window''' 540 HAPConstr.DestroyChildren() 541 HAPDisplay = wx.Panel(HAPConstr) 542 HAPSizer = wx.BoxSizer(wx.VERTICAL) 543 HAPSizer.Add((5,5),0) 544 HAPSizer.Add(ConstSizer('HAP',HAPDisplay)) 545 HAPDisplay.SetSizer(HAPSizer,True) 546 Size = HAPSizer.GetMinSize() 547 Size[0] += 40 548 Size[1] = max(Size[1],250) + 20 549 HAPDisplay.SetSize(Size) 550 # scroll bar not working, at least not on Mac 551 HAPConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1) 552 Size[1] = min(Size[1],250) 553 G2frame.dataFrame.setSizePosLeft(Size) 554 555 def UpdateHistConstr(): 556 '''Responds to press on Histogram Constraints tab, 557 shows constraints in data window''' 558 HistConstr.DestroyChildren() 559 HistDisplay = wx.Panel(HistConstr) 560 HistSizer = wx.BoxSizer(wx.VERTICAL) 561 HistSizer.Add((5,5),0) 562 HistSizer.Add(ConstSizer('Hist',HistDisplay)) 563 HistDisplay.SetSizer(HistSizer,True) 564 Size = HistSizer.GetMinSize() 565 Size[0] += 40 566 Size[1] = max(Size[1],250) + 20 567 HistDisplay.SetSize(Size) 568 HistConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1) 569 Size[1] = min(Size[1],250) 570 G2frame.dataFrame.setSizePosLeft(Size) 571 572 def UpdatePhaseConstr(): 573 '''Responds to press on Phase Constraint tab, 574 shows constraints in data window''' 575 PhaseConstr.DestroyChildren() 576 PhaseDisplay = wx.Panel(PhaseConstr) 577 PhaseSizer = wx.BoxSizer(wx.VERTICAL) 578 PhaseSizer.Add((5,5),0) 579 PhaseSizer.Add(ConstSizer('Phase',PhaseDisplay)) 580 PhaseDisplay.SetSizer(PhaseSizer,True) 581 Size = PhaseSizer.GetMinSize() 582 Size[0] += 40 583 Size[1] = max(Size[1],250) + 20 584 PhaseDisplay.SetSize(Size) 585 PhaseConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1) 586 Size[1] = min(Size[1],250) 587 G2frame.dataFrame.setSizePosLeft(Size) 588 589 def UpdateGlobalConstr(): 590 '''Responds to press on Global Constraint tab, 591 shows constraints in data window''' 592 GlobalConstr.DestroyChildren() 593 GlobalDisplay = wx.Panel(GlobalConstr) 594 GlobalSizer = wx.BoxSizer(wx.VERTICAL) 595 GlobalSizer.Add((5,5),0) 596 GlobalSizer.Add(ConstSizer('Global',GlobalDisplay)) 597 GlobalDisplay.SetSizer(GlobalSizer,True) 598 Size = GlobalSizer.GetMinSize() 599 Size[0] += 40 600 Size[1] = max(Size[1],250) + 20 601 GlobalDisplay.SetSize(Size) 602 GlobalConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1) 603 Size[1] = min(Size[1],250) 604 G2frame.dataFrame.setSizePosLeft(Size) 605 831 832 def UpdateConstraintPanel(panel,typ): 833 '''Update the contents of the selected Constraint 834 notebook tab. Called in :func:`OnPageChanged` 835 ''' 836 if panel.GetSizer(): panel.GetSizer().Clear(True) # N.B. don't use panel.DestroyChildren() 837 # because it deletes scrollbars on Mac 838 Siz = wx.BoxSizer(wx.VERTICAL) 839 Siz.Add((5,5),0) 840 Siz.Add(MakeConstraintsSizer(typ,panel)) 841 panel.SetSizer(Siz,True) 842 G2frame.dataFrame.SetSize((500,250)) # set frame size here 843 panel.SetAutoLayout(1) 844 panel.SetupScrolling() 845 606 846 def OnPageChanged(event): 847 '''Called when a tab is pressed or when a "select tab" menu button is 848 used (see RaisePage), or to refresh the current tab contents (event=None) 849 ''' 607 850 if event: #page change event! 608 851 page = event.GetSelection() 609 else: 852 else: # called directly, get current page 610 853 page = G2frame.dataDisplay.GetSelection() 611 854 oldPage = G2frame.dataDisplay.ChangeSelection(page) … … 613 856 if text == 'Histogram/Phase constraints': 614 857 G2frame.Page = [page,'hap'] 615 Update HAPConstr()858 UpdateConstraintPanel(HAPConstr,'HAP') 616 859 elif text == 'Histogram constraints': 617 860 G2frame.Page = [page,'hst'] 618 Update HistConstr()861 UpdateConstraintPanel(HistConstr,'Hist') 619 862 elif text == 'Phase constraints': 620 863 G2frame.Page = [page,'phs'] 621 Update PhaseConstr()864 UpdateConstraintPanel(PhaseConstr,'Phase') 622 865 elif text == 'Global constraints': 623 866 G2frame.Page = [page,'glb'] 624 UpdateGlobalConstr() 625 867 UpdateConstraintPanel(GlobalConstr,'Global') 868 869 def RaisePage(event): 870 'Respond to a "select tab" menu button' 871 try: 872 i = (G2gd.wxID_CONSPHASE, 873 G2gd.wxID_CONSHAP, 874 G2gd.wxID_CONSHIST, 875 G2gd.wxID_CONSGLOBAL).index(event.GetId()) 876 G2frame.dataDisplay.SetSelection(i) 877 OnPageChanged(None) 878 except ValueError: 879 print('Unexpected event in RaisePage') 626 880 627 881 def SetStatusLine(text): 628 882 Status.SetStatusText(text) 629 883 630 plegend,hlegend,phlegend,glegend = GetPHlegends(Phases,Histograms)631 scope = {'hst':['Histogram contraints:',hlegend,histList,'Hist',UpdateHistConstr],632 'hap':['Histogram * Phase contraints:',phlegend,hapList,'HAP',UpdateHAPConstr],633 'phs':['Phase contraints:',plegend,phaseList,'Phase',UpdatePhaseConstr],634 'glb':['Global constraints:',glegend,globalList,'Global',UpdateGlobalConstr]}635 884 if G2frame.dataDisplay: 636 885 G2frame.dataDisplay.Destroy() … … 646 895 G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddEquivalence, id=G2gd.wxID_EQUIVADD) 647 896 G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddHold, id=G2gd.wxID_HOLDADD) 648 G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize()) 649 650 PhaseConstr = wx.ScrolledWindow(G2frame.dataDisplay) 897 # tab commands 898 for id in (G2gd.wxID_CONSPHASE, 899 G2gd.wxID_CONSHAP, 900 G2gd.wxID_CONSHIST, 901 G2gd.wxID_CONSGLOBAL): 902 G2frame.dataFrame.Bind(wx.EVT_MENU, RaisePage,id=id) 903 904 G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame) 905 # note that order of pages is hard-coded in RaisePage 906 wxstyle = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER 907 PhaseConstr = wxscroll.ScrolledPanel(G2frame.dataDisplay, wx.ID_ANY,style=wxstyle) 651 908 G2frame.dataDisplay.AddPage(PhaseConstr,'Phase constraints') 652 HAPConstr = wx .ScrolledWindow(G2frame.dataDisplay)909 HAPConstr = wxscroll.ScrolledPanel(G2frame.dataDisplay, wx.ID_ANY,style=wxstyle) 653 910 G2frame.dataDisplay.AddPage(HAPConstr,'Histogram/Phase constraints') 654 HistConstr = wx .ScrolledWindow(G2frame.dataDisplay)911 HistConstr = wxscroll.ScrolledPanel(G2frame.dataDisplay, wx.ID_ANY,style=wxstyle) 655 912 G2frame.dataDisplay.AddPage(HistConstr,'Histogram constraints') 656 GlobalConstr = wx.ScrolledWindow(G2frame.dataDisplay) 657 G2frame.dataDisplay.AddPage(GlobalConstr,'Global constraints') 658 UpdatePhaseConstr() 659 913 GlobalConstr = wxscroll.ScrolledPanel(G2frame.dataDisplay, wx.ID_ANY,style=wxstyle) 914 G2frame.dataDisplay.AddPage(GlobalConstr,'Global constraints') 915 OnPageChanged(None) # show initial page 660 916 G2frame.dataDisplay.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged) 661 917 # validate all the constrants -- should not see any errors here normally … … 856 1112 while 'ATOM' not in txtStr[:6] and 'HETATM' not in txtStr[:6]: 857 1113 txtStr = text.readline() 858 print txtStr1114 #print txtStr 859 1115 items = txtStr.split() 860 1116 while len(items): -
trunk/GSASIIgrid.py
r1128 r1138 118 118 119 119 [ wxID_CONSTRAINTADD,wxID_EQUIVADD,wxID_HOLDADD,wxID_FUNCTADD, 120 ] = [wx.NewId() for item in range(4)] 120 wxID_CONSPHASE, wxID_CONSHIST, wxID_CONSHAP, wxID_CONSGLOBAL, 121 ] = [wx.NewId() for item in range(8)] 121 122 122 123 [ wxID_RESTRAINTADD, wxID_RESTSELPHASE,wxID_RESTDELETE, wxID_RESRCHANGEVAL, … … 279 280 else: 280 281 self.invalid = False 282 self.Bind(wx.EVT_CHAR,self._GetStringValue) 281 283 elif val is None: 282 284 raise Exception,("ValidatedTxtCtrl error: value of "+str(key)+ … … 360 362 elif self.OKcontrol and previousInvalid: 361 363 self.OKcontrol(True) 364 # always store the result 365 if self.CIFinput: # for CIF make results ASCII 366 self.result[self.key] = val.encode('ascii','replace') 367 else: 368 self.result[self.key] = val 369 370 def _GetStringValue(self,event): 371 '''Get string input and store. 372 ''' 373 event.Skip() # process keystroke 374 wx.CallAfter(self._SaveStringValue) 375 376 def _SaveStringValue(self): 377 val = self.GetValue().strip() 362 378 # always store the result 363 379 if self.CIFinput: # for CIF make results ASCII … … 1321 1337 :param str header: Title to place on window frame 1322 1338 :param list ChoiceList: a list of choices where one will be selected 1339 :param bool toggle: If True (default) the toggle and select all buttons 1340 are displayed 1323 1341 1324 1342 :param kw: optional keyword parameters for the wx.Dialog may 1325 be included such as Size [which defaults to `(320,310)`] and1326 Style (which defaults to `wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.CENTRE| wx.OK | wx.CANCEL`);1343 be included such as size [which defaults to `(320,310)`] and 1344 style (which defaults to `wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.CENTRE| wx.OK | wx.CANCEL`); 1327 1345 note that `wx.OK` and `wx.CANCEL` controls 1328 1346 the presence of the eponymous buttons in the dialog. 1329 1347 :returns: the name of the created dialog 1330 1348 ''' 1331 def __init__(self,parent, title, header, ChoiceList, **kw):1349 def __init__(self,parent, title, header, ChoiceList, toggle=True, **kw): 1332 1350 # process keyword parameters, notably Style 1333 1351 options = {'size':(320,310), # default Frame keywords … … 1355 1373 Sizer.Add((-1,10)) 1356 1374 # set/toggle buttons 1357 bSizer = wx.BoxSizer(wx.VERTICAL) 1358 setBut = wx.Button(self,wx.ID_ANY,'Set All') 1359 setBut.Bind(wx.EVT_BUTTON,self._SetAll) 1360 bSizer.Add(setBut,0,wx.ALIGN_CENTER) 1361 bSizer.Add((-1,5)) 1362 togBut = wx.Button(self,wx.ID_ANY,'Toggle All') 1363 togBut.Bind(wx.EVT_BUTTON,self._ToggleAll) 1364 bSizer.Add(togBut,0,wx.ALIGN_CENTER) 1365 Sizer.Add(bSizer,0,wx.LEFT,12) 1375 if toggle: 1376 bSizer = wx.BoxSizer(wx.VERTICAL) 1377 setBut = wx.Button(self,wx.ID_ANY,'Set All') 1378 setBut.Bind(wx.EVT_BUTTON,self._SetAll) 1379 bSizer.Add(setBut,0,wx.ALIGN_CENTER) 1380 bSizer.Add((-1,5)) 1381 togBut = wx.Button(self,wx.ID_ANY,'Toggle All') 1382 togBut.Bind(wx.EVT_BUTTON,self._ToggleAll) 1383 bSizer.Add(togBut,0,wx.ALIGN_CENTER) 1384 Sizer.Add(bSizer,0,wx.LEFT,12) 1366 1385 # OK/Cancel buttons 1367 1386 btnsizer = wx.StdDialogButtonSizer() … … 1852 1871 1853 1872 ################################################################################ 1873 class HelpButton(wx.Button): 1874 '''Create a help button that displays help information. 1875 The text is displayed in a modal message window. 1876 1877 TODO: it might be nice if it were non-modal: e.g. it stays around until 1878 the parent is deleted or the user closes it, but this did not work for 1879 me. 1880 1881 :param parent: the panel which will be the parent of the button 1882 :param str msg: the help text to be displayed 1883 ''' 1884 def __init__(self,parent,msg): 1885 if sys.platform == "darwin": 1886 wx.Button.__init__(self,parent,wx.ID_HELP) 1887 else: 1888 wx.Button.__init__(self,parent,wx.ID_ANY,'?',style=wx.BU_EXACTFIT) 1889 self.Bind(wx.EVT_BUTTON,self._onPress) 1890 self.msg=msg 1891 self.parent = parent 1892 def _onPress(self,event): 1893 'Respond to a button press by displaying the requested text' 1894 dlg = wx.MessageDialog(self.parent,self.msg,'Help info',wx.OK) 1895 dlg.ShowModal() 1896 dlg.Destroy() 1897 ################################################################################ 1854 1898 class MyHtmlPanel(wx.Panel): 1855 1899 '''Defines a panel to display HTML help information, as an alternative to … … 1988 2032 self.ConstraintMenu = wx.MenuBar() 1989 2033 self.PrefillDataMenu(self.ConstraintMenu,helpType='Constraints') 2034 self.ConstraintTab = wx.Menu(title='') 2035 self.ConstraintMenu.Append(menu=self.ConstraintTab, title='Select tab') 2036 for id,txt in ( 2037 (wxID_CONSPHASE,'Phase'), 2038 (wxID_CONSHAP,'Histogram/Phase'), 2039 (wxID_CONSHIST,'Histogram'), 2040 (wxID_CONSGLOBAL,'Global')): 2041 self.ConstraintTab.Append( 2042 id=id, kind=wx.ITEM_NORMAL,text=txt, 2043 help='Select '+txt+' constraint editing tab') 1990 2044 self.ConstraintEdit = wx.Menu(title='') 1991 2045 self.ConstraintMenu.Append(menu=self.ConstraintEdit, title='Edit') … … 1998 2052 self.ConstraintEdit.Append(id=wxID_FUNCTADD, kind=wx.ITEM_NORMAL,text='Add New Var', 1999 2053 help='Add variable composed of existing parameter') 2054 2055 # item = self.ConstraintEdit.Append(id=wx.ID_ANY,kind=wx.ITEM_NORMAL,text='Update GUI') 2056 # def UpdateGSASIIconstrGUI(event): 2057 # import GSASIIconstrGUI 2058 # reload(GSASIIconstrGUI) 2059 # import GSASIIobj 2060 # reload(GSASIIobj) 2061 # self.Bind(wx.EVT_MENU,UpdateGSASIIconstrGUI,id=item.GetId()) 2062 2000 2063 self.PostfillDataMenu() 2001 2064 -
trunk/GSASIImapvars.py
r1046 r1138 221 221 222 222 # prefix for parameter names 223 paramPrefix = "::constr :"223 paramPrefix = "::constr;" 224 224 consNum = 0 # number of the next constraint to be created 225 225 … … 248 248 :returns: two lists of lists: 249 249 250 * a list of grouped contraints where each constraint grouped containts a list of indices for constraint constrDict entries 250 * a list of grouped contraints where each constraint grouped containts a list 251 of indices for constraint constrDict entries 251 252 * a list containing lists of parameter names contained in each group 252 253 … … 284 285 :param list varyList: a list of parameters names that will be varied 285 286 286 :param dict constrDict: a list of dicts defining relationships/constraints (as defined in :func:`GroupConstraints`) 287 288 :param list fixedList: a list of values specifying a fixed value for each dict in constrDict. Values are 289 either strings that can be converted to floats or None if the constraint defines a new parameter rather 287 :param dict constrDict: a list of dicts defining relationships/constraints 288 (as created in :func:`GSASIIstrIO.ProcessConstraints` and 289 documented in :func:`GroupConstraints`) 290 291 :param list fixedList: a list of values specifying a fixed value for each 292 dict in constrDict. Values are either strings that can be converted to 293 floats or ``None`` if the constraint defines a new parameter rather 290 294 than a constant. 291 295 … … 491 495 conflicts or inconsistencies in parameter/variable definitions. 492 496 493 :param list groups: a list of grouped contraints where each constraint grouped containts a list of 494 indices for constraint constrDict entries, created in :func:`GroupConstraints` (returned as 1st value) 495 496 :param list parmlist: a list containing lists of parameter names contained in each group, 497 :param list groups: a list of grouped contraints where each constraint 498 grouped containts a list of indices for constraint constrDict entries, 497 499 created in :func:`GroupConstraints` (returned as 1st value) 498 500 499 :param list varyList: a list of parameters names (strings of form ``<ph>:<hst>:<nam>``) that will be varied 501 :param list parmlist: a list containing lists of parameter names 502 contained in each group, created in :func:`GroupConstraints` 503 (returned as 2nd value) 504 505 :param list varyList: a list of parameters names (strings of form 506 ``<ph>:<hst>:<nam>``) that will be varied 500 507 501 :param dict constrDict: a list of dicts defining relationships/constraints (as defined in :func:`GroupConstraints`) 502 503 :param list fixedList: a list of values specifying a fixed value for each dict in constrDict. Values are 504 either strings that can be converted to floats, float values or None if the constraint defines a new 505 parameter 508 :param dict constrDict: a list of dicts defining relationships/constraints 509 (as defined in :func:`GroupConstraints`) 510 511 :param list fixedList: a list of values specifying a fixed value for each 512 dict in constrDict. Values are either strings that can be converted to 513 floats, float values or None if the constraint defines a new parameter. 506 514 507 :param dict constrDict: a list of dicts defining relationships/constraints 515 :param dict constrDict: a list of dicts defining relationships/constraints. 508 516 509 517 ''' … … 537 545 if mv not in indepVarList: indepVarList.append(mv) 538 546 for v,m in zip(varlist,invmultarr): 539 #if len(s): s += ' & '540 #s += str(v)541 #if m != 1:542 # s += " / " + str(m[0])543 547 if m == 0: zeromult = True 544 548 if v in varyList: … … 551 555 else: 552 556 depVarList.append(v) 553 #print str(mv) + ' is equivalent to parameter(s): '+s554 557 if varied > 0 and varied != len(varlist)+1: 555 558 msg += "\nNot all variables refined in equivalence:\n\t" … … 587 590 msg += '\t'+ s + '\n' 588 591 equivVarList = list(set(indepVarList).union(set(depVarList))) 589 #print 'equivVarList',equivVarList 590 # inboth = set(fixedVarList).intersection(set(equivVarList)) 591 # if len(inboth) > 0: 592 # msg += "\nError! The following variables are used in both Equivalence and Fixed constraints:\n" 593 # s = '' 594 # for var in sorted(inboth): 595 # if s != "": s+= ", " 596 # s += str(var) 597 # msg += '\t'+ s + '\n' 598 # 592 599 593 # scan through parameters in each relationship. Are all varied? If only some are 600 594 # varied, create an error message. … … 616 610 msg += '\nError: parameter '+var+" is Fixed and used in a constraint:\n\t" 617 611 msg += _FormatConstraint(constrDict[rel],fixedList[rel])+"\n" 618 # if var in equivVarList:619 # msg += '\nError: parameter '+var+" is Equivalenced and used in a constraint:\n\t"620 # msg += _FormatConstraint(constrDict[rel],fixedList[rel])+"\n"621 612 if varied > 0 and varied != len(constrDict[rel]): 622 613 msg += "\nNot all variables refined in constraint:\n\t" … … 656 647 varied = 0 657 648 notvaried = '' 658 if len(group) > 0: 649 if len(group) > 0: # get the original equation reference 659 650 rel = group.pop(0) 651 if debug: 652 print rel 653 print fixedList[rel] 654 print constrDict[rel] 660 655 fixedval = fixedList[rel] 661 656 for var in constrDict[rel]: … … 696 691 if debug: # on debug, show what is parsed & generated, semi-readable 697 692 print 50*'-' 698 for group,varlist,multarr,inv,mapvar in zip(groups,parmlist,arrayList,invarrayList,indParmList): 699 print '\n*** relation(s) in group:',group,'\tvars in group:',varlist 700 print 'new parameters:', mapvar 701 print 'Input relationship matrix' 702 print multarr[:len(group)] 703 added = len(group) - len(varlist) 704 if added < 0: 705 print 'added relationship rows' 706 print multarr[added:] 707 print 'Inverse relationship matrix' 708 print inv 693 print VarRemapShow(varyList) 709 694 710 695 def StoreEquivalence(independentVar,dependentList): -
trunk/GSASIIobj.py
r1129 r1138 26 26 Note that the contents of each dict item is a List where each element in the 27 27 list is a :ref:`constraint definition objects <Constraint_definitions_table>`. 28 The constraints in this form are converted in 29 :func:`GSASIIstrIO.ProcessConstraints` to the form used in :mod:`GSASIImapvars` 28 30 29 31 The keys in the Constraints dict are: … … 54 56 single: Data object descriptions; Constraint Definition 55 57 56 Each constraint is defined as a list using a series of terms of form 57 58 :: 59 60 [[<mult1>, <var1>], [<mult2>, <var2>],..., <fixed val>, <vary flag>, <cons type>] 61 62 Where the variable pair list item containing two values [<mult>, <var>], 58 Each constraint is defined as an item in a list. Each constraint is of form:: 59 60 [[<mult1>, <var1>], [<mult2>, <var2>],..., <fixedval>, <varyflag>, <constype>] 61 62 Where the variable pair list item containing two values [<mult>, <var>], where: 63 63 64 64 * <mult> is a multiplier for the constraint (float) 65 * <var> is the name of the variable (str) (or to be implemented a :class:`VarName` object.) 65 * <var> a :class:`G2VarObj` object (previously a str variable name of form 66 'p:h:name[:at]') 66 67 67 68 Note that the last three items in the list play a special role: 68 69 69 * <fixed val> is the fixed value for a constraint equation or is None 70 * <vary flag> is True, False or None and is intended to use to indicate if new variables 70 * <fixedval> is the fixed value for a `constant equation` (``constype=c``) 71 constraint or is None. For a `New variable` (``constype=f``) constraint, 72 a variable name can be specified as a str (but this is not yet used). 73 * <varyflag> is True or False for `New variable` (``constype=f``) constraints 74 or is None. This will be implemented in the future to indicate if these variables 71 75 should be refined. 72 * <cons type> is one of four letters, 'e', 'c', 'h', 'f' that determines the type of constraint.76 * <constype> is one of four letters, 'e', 'c', 'h', 'f' that determines the type of constraint: 73 77 74 78 * 'e' defines a set of equivalent variables. Only the first variable is refined (if the 75 79 appropriate refine flag is set) and and all other equivalent variables in the list 76 are generated from that variable. The vary flag for those variables is ignored. 77 * 'c' defines a constraint equation of form, :math:`m_1 \\times var_1 + m_2 \\times var_2 + ... = c` 78 * 'h' defines a variable to hold (not vary). Any variable on this list is not varied, even if its refinement 79 flag is set. This is of particular value when needing to hold one or more variables in a set such as 80 are generated from that variable, using the appropriate multipliers. 81 * 'c' defines a constraint equation of form, 82 :math:`m_1 \\times var_1 + m_2 \\times var_2 + ... = c` 83 * 'h' defines a variable to hold (not vary). Any variable on this list is not varied, 84 even if its refinement flag is set. Only one [mult,var] pair is allowed in a hold 85 constraint and the mult value is ignored. 86 This is of particular value when needing to hold one or more variables where a 87 single flag controls a set of variables such as, coordinates, 80 88 the reciprocal metric tensor or anisotropic displacement parameter. 81 * 'f' defines a relationship to define a new variableaccording to relationship89 * 'f' defines a new variable (function) according to relationship 82 90 :math:`newvar = m_1 \\times var_1 + m_2 \\times var_2 + ...` 83 91 … … 594 602 key sub-key explanation 595 603 ====================== =============== ==================================================== 596 Data 597 A dict that contains the 604 Data \ A dict that contains the 598 605 reflection table, 599 606 as described in the … … 625 632 hId \ The number assigned to the histogram when 626 633 the project is loaded or edited (can change) 634 ranId \ A random number id for the histogram 635 that does not change 627 636 ====================== =============== ==================================================== 628 637 … … 662 671 663 672 ''' 673 import random as ran 674 import sys 664 675 import GSASIIpath 676 import GSASIImath as G2mth 677 665 678 GSASIIpath.SetVersionNumber("$Revision$") 666 667 def LoadHistogramIDs(histList,idList): 668 '''Save the Id values for a series of histograms''' 669 VarName.IDdict['hists'] = {} 670 for h,i in zip(histList,idList): 671 VarName.IDdict['hists'][i] = h 672 673 def LoadPhaseIDs(self): 674 pass 675 676 class VarName(object): 677 '''Defines a GSAS-II variable either using the phase/atom/histogram 678 unique Id numbers or using a character string that specifies 679 variables by phase/atom/histogram number (which can change). 680 Note that :func:`LoadID` should be used to (re)load the current Ids 681 before creating or later using the VarName object. 682 683 A :class:`VarName` object can be created with a single parameter: 679 PhaseIdLookup = {} 680 '''dict listing phase name and random Id keyed by sequential phase index as a str; 681 best to access this using :func:`LookupPhaseName` 682 ''' 683 PhaseRanIdLookup = {} 684 '''dict listing phase sequential index keyed by phase random Id; 685 best to access this using :func:`LookupPhaseId` 686 ''' 687 HistIdLookup = {} 688 '''dict listing histogram name and random Id, keyed by sequential histogram index as a str; 689 best to access this using :func:`LookupHistName` 690 ''' 691 HistRanIdLookup = {} 692 '''dict listing histogram sequential index keyed by histogram random Id; 693 best to access this using :func:`LookupHistId` 694 ''' 695 AtomIdLookup = {} 696 '''dict listing for each phase index as a str, the atom label and atom random Id, 697 keyed by atom sequential index as a str; 698 best to access this using :func:`LookupAtomLabel` 699 ''' 700 AtomRanIdLookup = {} 701 '''dict listing for each phase the atom sequential index keyed by atom random Id; 702 best to access this using :func:`LookupAtomId` 703 ''' 704 ShortPhaseNames = {} 705 '''a dict containing a possibly shortened and when non-unique numbered 706 version of the phase name. Keyed by the phase sequential index. 707 ''' 708 ShortHistNames = {} 709 '''a dict containing a possibly shortened and when non-unique numbered 710 version of the histogram name. Keyed by the histogram sequential index. 711 ''' 712 713 VarDesc = {} 714 ''' This dictionary lists descriptions for GSAS-II variables, 715 as set in :func:`CompileVarDesc`. See that function for a description 716 for how keys and values are written. 717 ''' 718 719 reVarDesc = {} 720 ''' This dictionary lists descriptions for GSAS-II variables with 721 the same values as :attr:`VarDesc` except that keys have been compiled as 722 regular expressions. Initialized in :func:`CompileVarDesc`. 723 ''' 724 725 def IndexAllIds(G2frame=None,Histograms=None,Phases=None): 726 '''Scan through the used phases & histograms and create an index 727 to the random numbers of phases, histograms and atoms. While doing this, 728 confirm that assigned random numbers are unique -- just in case lightning 729 strikes twice in the same place. 730 731 Note: this code assumes that the atom random Id (ranId) is the last 732 element each atom record. 733 734 TODO: do we need a lookup for rigid body variables? 735 ''' 736 if G2frame: 737 Histograms,phaseDict = G2frame.GetUsedHistogramsAndPhasesfromTree() 738 else: 739 Histograms,phaseDict = Histograms,Phases 740 # process phases and atoms 741 PhaseIdLookup.clear() 742 PhaseRanIdLookup.clear() 743 AtomIdLookup.clear() 744 AtomRanIdLookup.clear() 745 ShortPhaseNames.clear() 746 for Phase in phaseDict: 747 cx,ct,cs,cia = phaseDict[Phase]['General']['AtomPtrs'] 748 ranId = phaseDict[Phase]['ranId'] 749 while ranId in PhaseRanIdLookup: 750 # Found duplicate random Id! note and reassign 751 print ("\n\n*** Phase "+str(Phase)+" has repeated ranId. Fixing.\n") 752 phaseDict[Phase]['ranId'] = ranId = ran.randint(0,sys.maxint) 753 pId = str(phaseDict[Phase]['pId']) 754 PhaseIdLookup[pId] = (Phase,ranId) 755 PhaseRanIdLookup[ranId] = pId 756 shortname = Phase[:10] 757 while shortname in ShortPhaseNames.values(): 758 shortname = Phase[:8] + ' ('+ pId + ')' 759 ShortPhaseNames[pId] = shortname 760 AtomIdLookup[pId] = {} 761 AtomRanIdLookup[pId] = {} 762 for iatm,at in enumerate(phaseDict[Phase]['Atoms']): 763 ranId = at[-1] 764 while ranId in AtomRanIdLookup[pId]: # check for dups 765 print ("\n\n*** Phase "+str(Phase)+" atom "+str(iatm)+" has repeated ranId. Fixing.\n") 766 at[-1] = ranId = ran.randint(0,sys.maxint) 767 AtomRanIdLookup[pId][ranId] = str(iatm) 768 if phaseDict[Phase]['General']['Type'] == 'macromolecular': 769 label = '%s_%s_%s_%s'%(at[ct-1],at[ct-3],at[ct-4],at[ct-2]) 770 else: 771 label = at[ct-1] 772 AtomIdLookup[pId][str(iatm)] = (label,ranId) 773 # process histograms 774 HistIdLookup.clear() 775 HistRanIdLookup.clear() 776 ShortHistNames.clear() 777 for hist in Histograms: 778 ranId = Histograms[hist]['ranId'] 779 while ranId in HistRanIdLookup: 780 # Found duplicate random Id! note and reassign 781 print ("\n\n*** Histogram "+str(hist)+" has repeated ranId. Fixing.\n") 782 Histograms[hist]['ranId'] = ranId = ran.randint(0,sys.maxint) 783 hId = str(Histograms[hist]['hId']) 784 HistIdLookup[hId] = (hist,ranId) 785 HistRanIdLookup[ranId] = hId 786 shortname = hist[:15] 787 while shortname in ShortHistNames.values(): 788 shortname = hist[:11] + ' ('+ hId + ')' 789 ShortHistNames[hId] = shortname 790 791 return Histograms,phaseDict 792 793 def LookupAtomId(pId,ranId): 794 '''Get the atom number from a phase and atom random Id 795 796 :param int/str pId: the sequential number of the phase 797 :param int ranId: the random Id assigned to an atom 798 799 :returns: the index number of the atom (str) 800 ''' 801 if not AtomRanIdLookup: 802 raise Exception,'Error: LookupAtomId called before IndexAllIds was run' 803 if pId is None or pId == '': 804 raise KeyError,'Error: phase is invalid (None or blank)' 805 pId = str(pId) 806 if pId not in AtomRanIdLookup: 807 raise KeyError,'Error: LookupAtomId does not have phase '+pId 808 if ranId not in AtomRanIdLookup[pId]: 809 raise KeyError,'Error: LookupAtomId, ranId '+str(ranId)+' not in AtomRanIdLookup['+pId+']' 810 return AtomRanIdLookup[pId][ranId] 811 812 def LookupAtomLabel(pId,index): 813 '''Get the atom label from a phase and atom index number 814 815 :param int/str pId: the sequential number of the phase 816 :param int index: the index of the atom in the list of atoms 817 818 :returns: the label for the atom (str) and the random Id of the atom (int) 819 ''' 820 if not AtomIdLookup: 821 raise Exception,'Error: LookupAtomLabel called before IndexAllIds was run' 822 if pId is None or pId == '': 823 raise KeyError,'Error: phase is invalid (None or blank)' 824 pId = str(pId) 825 if pId not in AtomIdLookup: 826 raise KeyError,'Error: LookupAtomLabel does not have phase '+pId 827 if index not in AtomIdLookup[pId]: 828 raise KeyError,'Error: LookupAtomLabel, ranId '+str(index)+' not in AtomRanIdLookup['+pId+']' 829 return AtomIdLookup[pId][index] 830 831 def LookupPhaseId(ranId): 832 '''Get the phase number and name from a phase random Id 833 834 :param int ranId: the random Id assigned to a phase 835 :returns: the sequential Id (pId) number for the phase (str) 836 ''' 837 if not PhaseRanIdLookup: 838 raise Exception,'Error: LookupPhaseId called before IndexAllIds was run' 839 if ranId not in PhaseRanIdLookup: 840 raise KeyError,'Error: LookupPhaseId does not have ranId '+str(ranId) 841 return PhaseRanIdLookup[ranId] 842 843 def LookupPhaseName(pId): 844 '''Get the phase number and name from a phase Id 845 846 :param int/str pId: the sequential assigned to a phase 847 :returns: (phase,ranId) where phase is the name of the phase (str) 848 and ranId is the random # id for the phase (int) 849 ''' 850 if not PhaseIdLookup: 851 raise Exception,'Error: LookupPhaseName called before IndexAllIds was run' 852 if pId is None or pId == '': 853 raise KeyError,'Error: phase is invalid (None or blank)' 854 pId = str(pId) 855 if pId not in PhaseIdLookup: 856 raise KeyError,'Error: LookupPhaseName does not have index '+pId 857 return PhaseIdLookup[pId] 858 859 def LookupHistId(ranId): 860 '''Get the histogram number and name from a histogram random Id 861 862 :param int ranId: the random Id assigned to a histogram 863 :returns: the sequential Id (hId) number for the histogram (str) 864 ''' 865 if not HistRanIdLookup: 866 raise Exception,'Error: LookupHistId called before IndexAllIds was run' 867 if ranId not in HistRanIdLookup: 868 raise KeyError,'Error: LookupHistId does not have ranId '+str(ranId) 869 return HistRanIdLookup[ranId] 870 871 def LookupHistName(hId): 872 '''Get the histogram number and name from a histogram Id 873 874 :param int/str hId: the sequential assigned to a histogram 875 :returns: (hist,ranId) where hist is the name of the histogram (str) 876 and ranId is the random # id for the histogram (int) 877 ''' 878 if not HistIdLookup: 879 raise Exception,'Error: LookupHistName called before IndexAllIds was run' 880 if hId is None or hId == '': 881 raise KeyError,'Error: histogram is invalid (None or blank)' 882 hId = str(hId) 883 if hId not in HistIdLookup: 884 raise KeyError,'Error: LookupHistName does not have index '+hId 885 return HistIdLookup[hId] 886 887 def fmtVarDescr(varname): 888 '''Return a string with a more complete description for a GSAS-II variable 889 890 TODO: This will not handle rigid body parameters yet 891 892 :param str name: A full G2 variable name with 2 or 3 893 colons (<p>:<h>:name[:<a>]) 894 895 :returns: a string with the description 896 ''' 684 897 685 :param str varname: a single value can be used to create a :class:`VarName` 686 object. The string must be of form "p:h:var" or "p:h:var:a", where 687 688 * p is the phase number (which may be left blank); 689 * h is the histogram number (which may be left blank); 690 * a is the atom number (which may be left blank in which case the third colon is omitted). 691 692 Alternately, a :class:`VarName` object can be created with exactly four positional parameters: 693 694 :param int phasenum: The number for the phase 695 :param int histnum: The number for the histogram 696 :param str varname: a single value can be used to create a :class:`VarName` 697 :param int atomnum: The number for the atom 898 l = getVarDescr(varname) 899 if not l: 900 return "invalid variable name ("+str(varname)+")!" 901 902 if not l[4]: 903 l[4] = "(variable needs a definition!)" 904 905 s = "" 906 if l[0] is not None and l[1] is not None: # HAP: keep short 907 lbl = ShortPhaseNames.get(l[0],'? #'+str(l[0])) 908 hlbl = ShortHistNames.get(l[1],'? #'+str(l[1])) 909 if hlbl[:4] == 'HKLF': 910 hlbl = 'Xtl='+hlbl[5:] 911 elif hlbl[:4] == 'PWDR': 912 hlbl = 'Pwd='+hlbl[5:] 913 else: 914 hlbl = 'Hist='+hlbl 915 s = "Ph="+str(lbl)+" * "+str(hlbl)+": " 916 elif l[3] is not None: # atom parameter, 917 lbl = ShortPhaseNames.get(l[0],'phase?') 918 try: 919 albl = LookupAtomLabel(l[0],l[3])[0] 920 except KeyError: 921 albl = 'Atom?' 922 s = "Atom "+str(albl)+" in "+str(lbl)+": " 923 elif l[0] is not None: 924 lbl = ShortPhaseNames.get(l[0],'phase?') 925 s = "Phase "+str(lbl)+": " 926 elif l[1] is not None: 927 hlbl = ShortHistNames.get(l[1],'? #'+str(l[1])) 928 if hlbl[:4] == 'HKLF': 929 hlbl = 'Xtl='+hlbl[5:] 930 elif hlbl[:4] == 'PWDR': 931 hlbl = 'Pwd='+hlbl[5:] 932 else: 933 hlbl = 'Hist='+hlbl 934 s = str(hlbl)+": " 935 if not s: 936 s = 'Global: ' 937 s += l[4] 938 return s 939 940 def getVarDescr(varname): 941 '''Return a short description for a GSAS-II variable 942 943 :param str name: A full G2 variable name with 2 or 3 944 colons (<p>:<h>:name[:<a>]) 945 946 :returns: a five element list as [`p`,`h`,`name`,`a`,`description`], 947 where `p`, `h`, `a` are str values or `None`, for the phase number, 948 the histogram number and the atom number; `name` will always be 949 an str; and `description` is str or `None`. 950 If the variable name is incorrectly formed (for example, wrong 951 number of colons), `None` is returned instead of a list. 952 ''' 953 l = varname.split(':') 954 if len(l) == 3: 955 l += [None] 956 if len(l) != 4: 957 return None 958 for i in (0,1,3): 959 if l[i] == "": 960 l[i] = None 961 l += [getDescr(l[2])] 962 return l 698 963 964 def CompileVarDesc(): 965 '''Set the values in the variable description lookup table (:attr:`VarDesc`) 966 into :attr:`reVarDesc`. This is called in :func:`getDescr` so the initialization 967 is always done before use. 968 969 Note that keys may contain regular expressions, where '[xyz]' 970 matches 'x' 'y' or 'z' (equivalently '[x-z]' describes this as range of values). 971 '.*' matches any string. For example:: 972 973 'AUiso':'Atomic isotropic displacement parameter', 974 975 will match variable ``'p::AUiso:a'``. 976 If parentheses are used in the key, the contents of those parentheses can be 977 used in the value, such as:: 978 979 'AU([123][123])':'Atomic anisotropic displacement parameter U\\1', 980 981 will match ``AU11``, ``AU23``,.. and `U11`, `U23` etc will be displayed 982 in the value when used. 983 699 984 ''' 700 985 import re 701 IDdict = {} 702 IDdict['phases'] = {} 703 IDdict['hists'] = {} 704 IDdict['atoms'] = {} 705 # This dictionary lists descriptions for GSAS-II variables. 706 # Note that keys may contain regular expressions, where '[xyz]' 707 # matches 'x' 'y' or 'z' (equivalently '[x-z]' describes this as range of values). 708 # '.*' matches any string 709 VarDesc = { 986 if reVarDesc: return # already done 987 for key,value in { 710 988 # Phase vars (p::<var>) 711 'A [0-5]' : 'Reciprocal metric tensor component',989 'A([0-5])' : 'Reciprocal metric tensor component \\1', 712 990 'Vol' : 'Unit cell volume????', 713 991 # Atom vars (p::<var>:a) 714 'dA [xyz]' : 'change to atomic position',992 'dA([xyz])' : 'change to atomic position \\1', 715 993 'AUiso':'Atomic isotropic displacement parameter', 716 'AU [123][123]':'Atomic anisotropic displacement parameter',717 'A Frac': 'Atomic occupancy parameter',994 'AU([123][123])':'Atomic anisotropic displacement parameter U\\1', 995 'Afrac': 'Atomic occupancy parameter', 718 996 # Hist & Phase (HAP) vars (p:h:<var>) 719 'Bab [AU]': 'Babinet solvent scattering coef.',720 'D [123][123]' : 'Anisotropic strain coef.',997 'Bab([AU])': 'Babinet solvent scattering coef. \\1', 998 'D([123][123])' : 'Anisotropic strain coef. \\1', 721 999 'Extinction' : 'Extinction coef.', 722 1000 'MD' : 'March-Dollase coef.', … … 727 1005 #Histogram vars (:h:<var>) 728 1006 'Absorption' : 'Absorption coef.', 729 'Displace [XY]' : 'Debye-Scherrer sample displacement',1007 'Displace([XY])' : 'Debye-Scherrer sample displacement \\1', 730 1008 'Lam' : 'Wavelength', 731 'Polariz ' : 'Polarization correction',1009 'Polariz\.' : 'Polarization correction', 732 1010 'SH/L' : 'FCJ peak asymmetry correction', 733 1011 'Scale' : 'Histogram scale factor', 734 ' [UVW]' : 'Gaussian instrument broadening',735 ' [XY]' : 'Cauchy instrument broadening',1012 '([UVW])' : 'Gaussian instrument broadening \\1', 1013 '([XY])' : 'Cauchy instrument broadening \\1', 736 1014 'Zero' : 'Debye-Scherrer zero correction', 737 1015 'nDebye' : 'Debye model background corr. terms', 738 'nPeaks' : 'Fixed peak 1016 'nPeaks' : 'Fixed peak background corr. terms', 739 1017 # Global vars (::<var>) 740 } 1018 }.items(): 1019 VarDesc[key] = value 1020 reVarDesc[re.compile(key)] = value 1021 1022 def getDescr(name): 1023 '''Return a short description for a GSAS-II variable 1024 1025 :param str name: The descriptive part of the variable name without colons (:) 1026 1027 :returns: a short description or None if not found 1028 ''' 1029 1030 CompileVarDesc() # compile the regular expressions, if needed 1031 for key in reVarDesc: 1032 m = key.match(name) 1033 if m: 1034 return m.expand(reVarDesc[key]) 1035 return None 1036 1037 def _lookup(dic,key): 1038 '''Lookup a key in a dictionary, where None returns an empty string 1039 but an unmatched key returns a question mark. Used in :class:`G2VarObj` 1040 ''' 1041 if key is None: 1042 return "" 1043 else: 1044 return dic.get(key,'?') 1045 1046 class G2VarObj(object): 1047 '''Defines a GSAS-II variable either using the phase/atom/histogram 1048 unique Id numbers or using a character string that specifies 1049 variables by phase/atom/histogram number (which can change). 1050 Note that :func:`LoadID` should be used to (re)load the current Ids 1051 before creating or later using the G2VarObj object. 1052 1053 A :class:`G2VarObj` object can be created with a single parameter: 1054 1055 :param str varname: a single value can be used to create a :class:`G2VarObj` 1056 object. The string must be of form "p:h:var" or "p:h:var:a", where 1057 1058 * p is the phase number (which may be left blank); 1059 * h is the histogram number (which may be left blank); 1060 * a is the atom number (which may be left blank in which case the third colon is omitted). 1061 1062 Alternately, a :class:`G2VarObj` object can be created with exactly four positional parameters: 1063 1064 :param str/int phasenum: The number for the phase 1065 :param str/int histnum: The number for the histogram 1066 :param str varname: a single value can be used to create a :class:`G2VarObj` 1067 :param str/int atomnum: The number for the atom 1068 1069 ''' 1070 IDdict = {} 1071 IDdict['phases'] = {} 1072 IDdict['hists'] = {} 1073 IDdict['atoms'] = {} 741 1074 def __init__(self,*args): 742 1075 self.phase = None … … 746 1079 if len(args) == 1: 747 1080 lst = args[0].split(':') 748 raise Exception, "Need to look up IDs" 749 self.phase = lst[0] 750 self.histogram = lst[1] 1081 self.phase = PhaseIdLookup.get(lst[0],[None,None])[1] 1082 self.histogram = HistIdLookup.get(lst[1],[None,None])[1] 751 1083 self.name = lst[2] 752 1084 if len(lst) > 3: 753 self.atom = lst[3]1085 self.atom = AtomIdLookup[lst[0]].get(lst[3],[None,None])[1] 754 1086 elif len(args) == 4: 755 self.phase = args[0]756 self.histogram = args[1]1087 self.phase = PhaseIdLookup.get(str(args[0]),[None,None])[1] 1088 self.histogram = HistIdLookup.get(str(args[1]),[None,None])[1] 757 1089 self.name = args[2] 758 self.atom = args[3]1090 self.atom = AtomIdLookup[args[0]].get(str(args[3]),[None,None])[1] 759 1091 else: 760 1092 raise Exception,"Incorrectly called GSAS-II parameter name" 761 1093 1094 #print "DEBUG: created ",self.phase,self.histogram,self.name,self.atom 1095 762 1096 def __str__(self): 763 return self.name() 764 765 def name(self): 766 '''Formats the GSAS-II variable name as a "traditional" string (p:h:<var>:a) 1097 return self.varname() 1098 1099 def varname(self): 1100 '''Formats the GSAS-II variable name as a "traditional" GSAS-II variable 1101 string (p:h:<var>:a) or (p:h:<var>) 767 1102 768 1103 :returns: the variable name as a str 769 1104 ''' 770 def _fmt(val): 771 if val is None: 772 return "" 773 return str(val) 774 return _fmt(self.phase) + ":" + _fmt(self.histogram) + _fmt(self.name) + _fmt(self.atom) 775 1105 ph = _lookup(PhaseRanIdLookup,self.phase) 1106 hist = _lookup(HistRanIdLookup,self.histogram) 1107 s = (ph + ":" + hist + ":" + 1108 str(self.name)) 1109 if self.atom: 1110 if ph in AtomRanIdLookup: 1111 s += ":" + AtomRanIdLookup[ph].get(self.atom,'?') 1112 else: 1113 s += ":?" 1114 return s 1115 776 1116 def __repr__(self): 777 1117 '''Return the detailed contents of the object 778 1118 ''' 779 s = "" 780 if self.phase: 781 s += "Phase: " + str(self.phase) + "; " 782 783 if self.histogram: 784 s += "Histogram: " + str(self.histogram) + "; " 785 786 if self.name: 787 s += "Variable name: " + str(self.name) + "; " 788 789 if self.atom: 790 s += "Atom number: " + str(self.atom) + "; " 791 792 return s+"("+self.name()+")" 793 794 def getDescr(self): 795 '''Return a short description for a GSAS-II variable 796 797 :returns: a short description or 'no definition' if not found 798 ''' 799 # iterating over uncompiled regular expressions is not terribly fast, 800 # but this routine should not need to be all that speedy 801 for key in self.VarDesc: 802 if re.match(key, self.name): 803 return self.VarDesc[key] 804 return 'no definition' 805 806 def getDescr(self): 807 '''Return a short description for a GSAS-II variable 808 809 :returns: a short description or 'no definition' if not found 810 ''' 811 # iterating over uncompiled regular expressions is not terribly fast, 812 # but this routine should not need to be all that speedy 813 for key in self.VarDesc: 814 if re.match(key, self.name): 815 return self.VarDesc[key] 816 return 'no definition' 817 818 def fullDescr(self): 819 '''Return a longer description for a GSAS-II variable 820 821 :returns: a short description or 'no definition' if not found 822 ''' 823 # iterating over uncompiled regular expressions is not terribly fast, 824 # but this routine should not need to be all that speedy 825 str = self.name() 826 827 for key in self.VarDesc: 828 if re.match(key, self.name): 829 return self.VarDesc[key] 830 return 'no definition' 831 1119 s = "<" 1120 if self.phase is not None: 1121 ph = _lookup(PhaseRanIdLookup,self.phase) 1122 s += "Phase: rId=" + str(self.phase) + " (#"+ ph + "); " 1123 if self.histogram is not None: 1124 hist = _lookup(HistRanIdLookup,self.histogram) 1125 s += "Histogram: rId=" + str(self.histogram) + " (#"+ hist + "); " 1126 if self.atom is not None: 1127 s += "Atom rId=" + str(self.atom) 1128 if ph in AtomRanIdLookup: 1129 s += " (#" + AtomRanIdLookup[ph].get(self.atom,'?') + "); " 1130 else: 1131 s += " (#? -- no such phase!); " 1132 s += 'Variable name="' + str(self.name) + '">' 1133 return s+"("+self.varname()+")" 1134 1135 def __eq__(self, other): 1136 if type(other) is type(self): 1137 return (self.phase == other.phase and 1138 self.histogram == other.histogram and 1139 self.name == other.name and 1140 self.atom == other.atom) 1141 return False 832 1142 833 1143 def _show(self): -
trunk/GSASIIstrIO.py
r1137 r1138 29 29 import GSASIIlattice as G2lat 30 30 import GSASIIspc as G2spc 31 import GSASIIobj as G2obj 31 32 import GSASIImapvars as G2mv 32 33 import GSASIImath as G2mth … … 79 80 constDict,fixedList,ignored = ProcessConstraints(constList) 80 81 if ignored: 81 print ignored,' old-style Constraints were rejected'82 print ignored,'Constraints were rejected. Was a constrained phase, histogram or atom deleted?' 82 83 return constDict,fixedList 83 84 84 85 def ProcessConstraints(constList): 85 86 """Interpret the constraints in the constList input into a dictionary, etc. 87 All :class:`GSASIIobj.G2VarObj` objects are mapped to the appropriate 88 phase/hist/atoms based on the object internals (random Ids). If this can't be 89 done (if a phase has been deleted, etc.), the variable is ignored. 90 If the constraint cannot be used due to too many dropped variables, 91 it is counted as ignored. 86 92 87 93 :param list constList: a list of lists where each item in the outer list 88 specifies a constraint of some form. The last item in each inner list 89 determines which of the four constraints types has been input: 90 91 * h (hold): a single variable that will not be varied. It 92 will be removed from the varyList later. 93 * c (constraint): specifies a linear relationship that 94 can be varied as a new grouped variable 95 a fixed value. 96 * f (fixed): specifies a linear relationship that is assigned 97 a fixed value. 98 * e (equivalence): specifies a series of variables where the 99 first variable in the last can be used to generate the 100 values for all the remaining variables. 94 specifies a constraint of some form, as described in the :mod:`GSASIIobj` 95 :ref:`Constraint definition <Constraint_definitions_table>`. 101 96 102 97 :returns: a tuple of (constDict,fixedList,ignored) where: 103 98 104 * constDict (list ) contains the constraint relationships99 * constDict (list of dicts) contains the constraint relationships 105 100 * fixedList (list) contains the fixed values for type 106 101 of constraint. 107 102 * ignored (int) counts the number of invalid constraint items 108 103 (should always be zero!) 109 110 104 """ 111 105 constDict = [] … … 116 110 # process a hold 117 111 fixedList.append('0') 118 constDict.append({item[0][1]:0.0}) 112 var = str(item[0][1]) 113 if '?' not in var: 114 constDict.append({var:0.0}) 115 else: 116 ignored += 1 119 117 elif item[-1] == 'f': 120 118 # process a new variable 121 119 fixedList.append(None) 122 constDict.append({}) 120 D = {} 121 varyFlag = item[-2] 122 name = item[-3] 123 123 for term in item[:-3]: 124 constDict[-1][term[1]] = term[0] 124 var = str(term[1]) 125 if '?' not in var: 126 D[var] = term[0] 127 if len(D) > 1: 128 # add extra dict terms for input variable name and vary flag 129 #if name is not None: 130 # D['_name'] = name 131 #D['_vary'] = varyFlag == True # force to bool 132 constDict.append(D) 133 else: 134 ignored += 1 125 135 #constFlag[-1] = ['Vary'] 126 136 elif item[-1] == 'c': 127 137 # process a contraint relationship 128 fixedList.append(str(item[-3])) 129 constDict.append({}) 138 D = {} 130 139 for term in item[:-3]: 131 constDict[-1][term[1]] = term[0] 132 #constFlag[-1] = ['VaryFree'] 140 var = str(term[1]) 141 if '?' not in var: 142 D[var] = term[0] 143 if len(D) >= 1: 144 fixedList.append(str(item[-3])) 145 constDict.append(D) 146 else: 147 ignored += 1 133 148 elif item[-1] == 'e': 134 149 # process an equivalence … … 137 152 for term in item[:-3]: 138 153 if term[0] == 0: term[0] = 1.0 154 var = str(term[1]) 155 if '?' in var: continue 139 156 if firstmult is None: 140 firstmult,firstvar = term 157 firstmult = term[0] 158 firstvar = var 141 159 else: 142 eqlist.append([term[1],firstmult/term[0]]) 143 G2mv.StoreEquivalence(firstvar,eqlist) 160 eqlist.append([var,firstmult/term[0]]) 161 if len(eqlist) > 0: 162 G2mv.StoreEquivalence(firstvar,eqlist) 163 else: 164 ignored += 1 144 165 else: 145 166 ignored += 1 … … 156 177 if not Histograms: 157 178 return 'Error: no diffraction data','' 179 G2obj.IndexAllIds(Histograms=Histograms,Phases=Phases) 158 180 rigidbodyDict = GetRigidBodies(GPXfile) 159 181 rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]}) … … 335 357 def GetUsedHistogramsAndPhases(GPXfile): 336 358 ''' Returns all histograms that are found in any phase 337 and any phase that uses a histogram 359 and any phase that uses a histogram. This also 360 assigns numbers to used phases and histograms by the 361 order they appear in the file. 338 362 339 363 :param str GPXfile: full .gpx file name 340 :return : (Histograms,Phases)364 :returns: (Histograms,Phases) 341 365 342 366 * Histograms = dictionary of histograms as {name:data,...} … … 363 387 Phase['Histograms'][hist]['Use'] = True 364 388 if hist not in Histograms and Phase['Histograms'][hist]['Use']: 365 Histograms[hist] = allHistograms[hist] 366 hId = histoList.index(hist) 367 Histograms[hist]['hId'] = hId 389 try: 390 Histograms[hist] = allHistograms[hist] 391 hId = histoList.index(hist) 392 Histograms[hist]['hId'] = hId 393 except KeyError: # would happen if a referenced histogram were 394 # renamed or deleted 395 print('For phase "'+str(phase)+ 396 '" unresolved reference to histogram "'+str(hist)+'"') 368 397 return Histograms,Phases 369 398 -
trunk/GSASIIstrMain.py
r1125 r1138 58 58 calcControls = {} 59 59 calcControls.update(Controls) 60 constrDict,fixedList = G2stIO.GetConstraints(GPXfile) 60 constrDict,fixedList = G2stIO.GetConstraints(GPXfile) # better to pass in Histograms,Phases 61 61 restraintDict = G2stIO.GetRestraints(GPXfile) 62 62 Histograms,Phases = G2stIO.GetUsedHistogramsAndPhases(GPXfile) 63 G2obj.IndexAllIds(Histograms=Histograms,Phases=Phases) 63 64 if not Phases: 64 65 print ' *** ERROR - you have no phases! ***' … … 91 92 try: 92 93 groups,parmlist = G2mv.GroupConstraints(constrDict) 94 #G2mv.debug = True # DEBUG 93 95 G2mv.GenerateConstraints(groups,parmlist,varyList,constrDict,fixedList) 96 #G2mv.debug = False # DEBUG 94 97 except: 95 98 print ' *** ERROR - your constraints are internally inconsistent ***' … … 98 101 if warnmsg: print 'Warnings',warnmsg 99 102 raise Exception(' *** Refine aborted ***') 103 #raise Exception(' *** Refine DEBUG ***') # DEBUG 100 104 # # check to see which generated parameters are fully varied 101 105 # msg = G2mv.SetVaryFlags(varyList)
Note: See TracChangeset
for help on using the changeset viewer.