Changeset 1057
- Timestamp:
- Sep 17, 2013 4:22:51 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIIIO.py
r1034 r1057 27 27 import cPickle 28 28 import sys 29 import re 29 30 import random as ran 30 31 import GSASIIpath … … 53 54 else: 54 55 return 0 56 57 58 def trim(val): 59 '''Simplify a string containing leading and trailing spaces 60 as well as newlines, tabs, repeated spaces etc. into a shorter and 61 more simple string, by replacing all ranges of whitespace 62 characters with a single space. 63 64 :param str val: the string to be simplified 65 66 :returns: the (usually) shortened version of the string 67 ''' 68 return re.sub('\s+', ' ', val).strip() 55 69 56 70 def makeInstDict(names,data,codes): -
trunk/GSASIIgrid.py
r1056 r1057 181 181 upper limit is unbounded 182 182 183 :param wx.Size size: an optional size parameter that dictates the184 size for the TextCtrl. None (the default) indicates that the185 default size should be used.186 187 183 :param function OKcontrol: specifies a function or method that will be 188 184 called when the input is validated. The called function is supplied … … 209 205 be called. 210 206 211 :param type typeHint: the value of typeHint is used if the initial value 212 for the dict/list element ``loc[key]`` is None. In this case typeHint 213 must be int or float, which specifies the type for input to the TextCtrl. 214 Defaults as None. 207 :param type typeHint: the value of typeHint is overrides the initial value 208 for the dict/list element ``loc[key]``, if set to 209 int or float, which specifies the type for input to the TextCtrl. 210 Defaults as None, which is ignored. 211 212 :param bool CIFinput: for str input, indicates that only printable 213 ASCII characters may be entered into the TextCtrl. Forces output 214 to be ASCII rather than Unicode. For float and int input, allows 215 use of a single '?' or '.' character as valid input. 216 217 :param (other): other optional keyword parameters for the 218 wx.TextCtrl widget such as Size or Style may be specified. 215 219 216 220 ''' 217 221 def __init__(self,parent,loc,key,notBlank=True,min=None,max=None, 218 size=None,OKcontrol=None,OnLeave=None,typeHint=None): 222 OKcontrol=None,OnLeave=None,typeHint=None, 223 CIFinput=False, **kw): 219 224 # save passed values needed outside __init__ 220 225 self.result = loc … … 222 227 self.OKcontrol=OKcontrol 223 228 self.OnLeave = OnLeave 229 self.CIFinput = CIFinput 224 230 # initialization 225 231 self.invalid = False # indicates if the control has invalid contents 226 232 self.evaluated = False # set to True when the validator recognizes an expression 227 233 val = loc[key] 228 if isinstance(val,int) or (val is None and typeHint is int):234 if isinstance(val,int) or typeHint is int: 229 235 wx.TextCtrl.__init__( 230 236 self,parent,wx.ID_ANY, 231 validator=NumberValidator(int,result=loc,key=key,min=min,max=max, 232 OKcontrol=OKcontrol) 233 ) 237 validator=NumberValidator(int,result=loc,key=key, 238 min=min,max=max, 239 OKcontrol=OKcontrol, 240 CIFinput=CIFinput), 241 **kw) 234 242 if val is not None: 235 243 self.SetValue(str(val)) 236 else: 244 try: 245 int(val) 246 except: 247 if CIFinput and (val == '?' or val == '.'): 248 pass 249 else: 250 self.invalid = True 251 self._IndicateValidity() 252 else: # no default is invalid for a number 237 253 self.ShowStringValidity() 238 elif isinstance(val,float) or (val is None and typeHint is float): 254 255 elif isinstance(val,float) or typeHint is float: 239 256 wx.TextCtrl.__init__( 240 257 self,parent,wx.ID_ANY, 241 validator=NumberValidator(float,result=loc,key=key,min=min,max=max, 242 OKcontrol=OKcontrol) 243 ) 258 validator=NumberValidator(float,result=loc,key=key, 259 min=min,max=max, 260 OKcontrol=OKcontrol, 261 CIFinput=CIFinput), 262 **kw) 244 263 if val is not None: 245 264 self.SetValue(str(val)) 265 try: 266 float(val) 267 except: 268 if CIFinput and (val == '?' or val == '.'): 269 pass 270 else: 271 self.invalid = True 272 self._IndicateValidity() 246 273 else: 247 274 self.ShowStringValidity() 248 275 elif isinstance(val,str) or isinstance(val,unicode): 249 wx.TextCtrl.__init__(self,parent,wx.ID_ANY,val) 276 if self.CIFinput: 277 wx.TextCtrl.__init__( 278 self,parent,wx.ID_ANY,val, 279 validator=ASCIIValidator(result=loc,key=key), 280 **kw) 281 else: 282 wx.TextCtrl.__init__(self,parent,wx.ID_ANY,val,**kw) 250 283 if notBlank: 251 284 self.Bind(wx.EVT_CHAR,self._onStringKey) … … 259 292 raise Exception,("ValidatedTxtCtrl error: Unknown element ("+str(key)+ 260 293 ") type: "+str(type(val))) 261 if size: self.SetSize(size)294 # if size: self.SetSize(size) 262 295 # When the mouse is moved away or the widget loses focus 263 296 # display the last saved value, if an expression … … 272 305 wx.CallAfter(self.ShowStringValidity,False) # was valid 273 306 307 def _IndicateValidity(self): 308 'Set the control colors to show invalid input' 309 if self.invalid: 310 self.SetForegroundColour("red") 311 self.SetBackgroundColour("yellow") 312 self.SetFocus() 313 self.Refresh() 314 else: # valid input 315 self.SetBackgroundColour( 316 wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) 317 self.SetForegroundColour("black") 318 self.Refresh() 319 274 320 def ShowStringValidity(self,previousInvalid=None): 275 321 '''Check if input is valid. Anytime the input is … … 284 330 val = self.GetValue().strip() 285 331 self.invalid = not val 286 'Set the control colors to show invalid input'332 self._IndicateValidity() 287 333 if self.invalid: 288 self.SetForegroundColour("red")289 self.SetBackgroundColour("yellow")290 self.SetFocus()291 self.Refresh()292 334 if self.OKcontrol: 293 335 self.OKcontrol(False) 294 else: # valid input 295 self.SetBackgroundColour( 296 wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) 297 self.SetForegroundColour("black") 298 self.Refresh() 299 if self.OKcontrol and previousInvalid: 300 self.OKcontrol(True) 301 self.result[self.key] = val # always store the result 336 elif self.OKcontrol and previousInvalid: 337 self.OKcontrol(True) 338 # always store the result 339 if self.CIFinput: 340 self.result[self.key] = val.encode('ascii','replace') 341 else: 342 self.result[self.key] = val 302 343 303 344 def _onLoseFocus(self,event): … … 348 389 an OK button for a window. 349 390 Ignored if None (default) 391 392 :param bool CIFinput: allows use of a single '?' or '.' character 393 as valid input. 394 350 395 ''' 351 396 def __init__(self, typ, positiveonly=False, min=None, max=None, 352 result=None, key=None, OKcontrol=None ):397 result=None, key=None, OKcontrol=None, CIFinput=False): 353 398 'Create the validator' 354 399 wx.PyValidator.__init__(self) … … 361 406 self.key = key 362 407 self.OKcontrol = OKcontrol 408 self.CIFinput = CIFinput 363 409 # set allowed keys by data type 410 self.Bind(wx.EVT_CHAR, self.OnChar) 364 411 if self.typ == int and self.positiveonly: 365 412 self.validchars = '0123456789' … … 372 419 else: 373 420 self.validchars = None 374 self.Bind(wx.EVT_CHAR, self.OnChar) 421 return 422 if self.CIFinput: 423 self.validchars += '?.' 375 424 def Clone(self): 376 425 'Create a copy of the validator, a strange, but required component' 377 426 return NumberValidator(typ=self.typ, 378 positiveonly=self.positiveonly, 379 min=self.min, max=self.max, 380 result=self.result, key=self.key, 381 OKcontrol=self.OKcontrol) 427 positiveonly=self.positiveonly, 428 min=self.min, max=self.max, 429 result=self.result, key=self.key, 430 OKcontrol=self.OKcontrol, 431 CIFinput=self.CIFinput) 382 432 tc = self.GetWindow() 383 433 tc.invalid = False # make sure the validity flag is defined in parent … … 400 450 is associated with. 401 451 ''' 402 tc.invalid = False # assume invalid 452 tc.invalid = False # assume valid 453 if self.CIFinput: 454 val = tc.GetValue().strip() 455 if val == '?' or val == '.': 456 self.result[self.key] = val 457 return 403 458 try: 404 459 val = self.typ(tc.GetValue()) … … 497 552 498 553 ################################################################################ 554 class ASCIIValidator(wx.PyValidator): 555 '''A validator to be used with a TextCtrl to prevent 556 entering characters other than ASCII characters. 557 558 The value is checked for validity after every keystroke 559 If an invalid number is entered, the box is highlighted. 560 If the number is valid, it is saved in result[key] 561 562 :param dict/list result: List or dict where value should be placed when valid 563 564 :param any key: key to use for result (int for list) 565 566 ''' 567 def __init__(self, result=None, key=None): 568 'Create the validator' 569 import string 570 wx.PyValidator.__init__(self) 571 # save passed parameters 572 self.result = result 573 self.key = key 574 self.validchars = string.ascii_letters + string.digits + string.punctuation + string.whitespace 575 self.Bind(wx.EVT_CHAR, self.OnChar) 576 def Clone(self): 577 'Create a copy of the validator, a strange, but required component' 578 return ASCIIValidator(result=self.result, key=self.key) 579 tc = self.GetWindow() 580 tc.invalid = False # make sure the validity flag is defined in parent 581 def TransferToWindow(self): 582 'Needed by validator, strange, but required component' 583 return True # Prevent wxDialog from complaining. 584 def TransferFromWindow(self): 585 'Needed by validator, strange, but required component' 586 return True # Prevent wxDialog from complaining. 587 def TestValid(self,tc): 588 '''Check if the value is valid by casting the input string 589 into ASCII. 590 591 Save it in the dict/list where the initial value was stored 592 593 :param wx.TextCtrl tc: A reference to the TextCtrl that the validator 594 is associated with. 595 ''' 596 self.result[self.key] = tc.GetValue().encode('ascii','replace') 597 598 def OnChar(self, event): 599 '''Called each type a key is pressed 600 ignores keys that are not allowed for int and float types 601 ''' 602 key = event.GetKeyCode() 603 tc = self.GetWindow() 604 if key == wx.WXK_RETURN: 605 self.TestValid(tc) 606 return 607 if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: # control characters get processed 608 event.Skip() 609 self.TestValid(tc) 610 return 611 elif chr(key) in self.validchars: # valid char pressed? 612 event.Skip() 613 self.TestValid(tc) 614 return 615 if not wx.Validator_IsSilent(): 616 wx.Bell() 617 return # Returning without calling event.Skip, which eats the keystroke 618 ################################################################################ 619 class EnumSelector(wx.ComboBox): 620 '''A customized :class:`wxpython.ComboBox` that selects items from a list 621 of choices, but sets a dict (list) entry to the corresponding 622 entry from the input list of values. 623 624 :param wx.Panel parent: the parent to the :class:`~wxpython.ComboBox` (usually a 625 frame or panel) 626 :param dict dct: a dict (or list) to contain the value set 627 for the :class:`~wxpython.ComboBox`. 628 :param item: the dict key (or list index) where ``dct[item]`` will 629 be set to the value selected in the :class:`~wxpython.ComboBox`. Also, dct[item] 630 contains the starting value shown in the widget. If the value 631 does not match an entry in :data:`values`, the first value 632 in :data:`choices` is used as the default, but ``dct[item]`` is 633 not changed. 634 :param list choices: a list of choices to be displayed to the 635 user such as 636 :: 637 638 ["default","option 1","option 2",] 639 640 Note that these options will correspond to the entries in 641 :data:`values` (if specified) item by item. 642 :param list values: a list of values that correspond to 643 the options in :data:`choices`, such as 644 :: 645 646 [0,1,2] 647 648 The default for :data:`values` is to use the same list as 649 specified for :data:`choices`. 650 :param (other): additional keyword arguments accepted by 651 :class:`~wxpython.ComboBox` can be specified. 652 ''' 653 def __init__(self,parent,dct,item,choices,values=None,**kw): 654 if values is None: 655 values = choices 656 if dct[item] in values: 657 i = values.index(dct[item]) 658 else: 659 i = 0 660 startval = choices[i] 661 wx.ComboBox.__init__(self,parent,wx.ID_ANY,startval, 662 choices = choices, 663 style=wx.CB_DROPDOWN|wx.CB_READONLY, 664 **kw) 665 self.choices = choices 666 self.values = values 667 self.dct = dct 668 self.item = item 669 self.Bind(wx.EVT_COMBOBOX, self.onSelection) 670 def onSelection(self,event): 671 # respond to a selection by setting the enum value in the CIF dictionary 672 if self.GetValue() in self.choices: # should always be true! 673 self.dct[self.item] = self.values[self.choices.index(self.GetValue())] 674 else: 675 self.dct[self.item] = self.values[0] # unknown 676 677 ################################################################################ 499 678 def CallScrolledMultiEditor(parent,dictlst,elemlst,prelbl=[],postlbl=[], 500 679 title='Edit items',header='',size=(300,250)): … … 503 682 504 683 :returns: True if the OK button is pressed; False if the window is closed 505 with the system menu or the C losebutton.684 with the system menu or the Cancel button. 506 685 507 686 ''' … … 586 765 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) 587 766 mainSizer = wx.BoxSizer(wx.VERTICAL) 588 # ad a header if supplied 767 self.orig = [] 768 self.dictlst = dictlst 769 self.elemlst = elemlst 770 for d,i in zip(dictlst,elemlst): 771 self.orig.append(d[i]) 772 # add a header if supplied 589 773 if header: 590 774 subSizer = wx.BoxSizer(wx.HORIZONTAL) … … 622 806 mainSizer.Add(panel,1, wx.ALL|wx.EXPAND,1) 623 807 624 # Sizer for OK/Close buttons. N.B. using Close rather than Cancel because 625 # Cancel would imply that the changes should be discarded. In fact 626 # any valid changes are retained, unless one makes a copy of the 627 # input dicts & lists and restores them. 808 # Sizer for OK/Close buttons. N.B. on Close changes are discarded 809 # by restoring the initial values 628 810 btnsizer = wx.BoxSizer(wx.HORIZONTAL) 629 811 btnsizer.Add(self.OKbtn) 630 btn = wx.Button(self, wx.ID_CLOSE )812 btn = wx.Button(self, wx.ID_CLOSE,"Cancel") 631 813 btn.Bind(wx.EVT_BUTTON,self._onClose) 632 814 btnsizer.Add(btn) … … 638 820 639 821 def _onClose(self,event): 640 'Close the window' 822 'Restore original values & close the window' 823 for d,i,v in zip(self.dictlst,self.elemlst,self.orig): 824 d[i] = v 641 825 self.EndModal(wx.ID_CANCEL) 642 826 … … 995 1179 def __init__(self,parent,title,prompt,value='',size=(200,-1)): 996 1180 wx.Dialog.__init__(self,parent,wx.ID_ANY,title, 997 pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) 1181 pos=wx.DefaultPosition, 1182 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) 998 1183 self.value = value 999 1184 self.prompt = prompt … … 1375 1560 'GSAS-II Updates', 1376 1561 wx.OK|wx.CANCEL) 1377 if dlg.ShowModal() != wx.ID_OK: return 1562 if dlg.ShowModal() != wx.ID_OK: 1563 dlg.Destroy() 1564 return 1565 dlg.Destroy() 1378 1566 print 'start updates' 1379 1567 dlg = wx.MessageDialog(self.frame, -
trunk/GSASIIimgGUI.py
r1049 r1057 45 45 ''' 46 46 import ImageCalibrants as calFile 47 try:48 import UserCalibrants as userFile49 calFile.Calibrants.update(userFile.Calibrants)50 except:51 pass52 47 #patch 53 48 if 'GonioAngles' not in data: -
trunk/GSASIIobj.py
r1046 r1057 610 610 611 611 ''' 612 import re 612 613 IDdict = {} 613 614 IDdict['phases'] = {} -
trunk/GSASIIstrIO.py
r1053 r1057 1762 1762 hfx = ':%d:'%(hId) 1763 1763 for item in inst: 1764 if type(inst) is not list: continue # skip over non-refined items (such as InstName) 1764 1765 hapDict[hfx+item] = inst[item][1] 1765 1766 pfx = str(pId)+':'+str(hId)+':' -
trunk/ImageCalibrants.py
r1049 r1057 3 3 ---------------------------------------- 4 4 5 GSASII powder calibrants as a dictionary of substances commonly used for powder6 c alibrations for image data.5 GSASII powder calibrants as a dictionary ``ImageCalibrants.Calibrants`` with substances 6 commonly used for powder calibrations for image data. 7 7 8 Create your own in file UserCalibrants.py following the format shown here; 9 if you use the same names given here your entries will replace the corresponding 10 ones given here. 11 Each entry consists of: 12 'name':(Bravais no,(a,b,c,alpha,beta,gamma),no. lines skipped,(dmin,pixLimit,cutOff) 13 Useful Bravais nos.: F-cubic=0,I-cubic=1,P-cubic=2,R3/m(hex)=3, P6=4, P4mmm=6 8 Each entry in ``ImageCalibrants`` consists of:: 9 10 'key':([Bravais num,],[(a,b,c,alpha,beta,gamma),],no. lines skipped,(dmin,pixLimit,cutOff)) 11 12 as an example:: 13 14 'LaB6 SRM660a':([2,],[(4.1569162,4.1569162,4.1569162,90,90,90),],0,(1.0,10,10)), 15 16 or where "Bravais num" and "(a,b,...)" are repeated in the case of mixtures:: 17 18 'LaB6 & CeO2':([2,0], [(4.1569,4.1569,4.1569,90,90,90),(5.4117,5.4117,5.4117,90,90,90)], 0, (1.0,2,1)), 19 20 To expand this list with locally needed additions, do not modify this file, 21 because you may lose these changes during a software update. Instead 22 duplicate the format of this file in a file named `UserCalibrants.py` 23 and there define the material(s) you want:: 24 25 Calibrants={ 26 'LaB6 skip 2 lines':([2,],[(4.1569162,4.1569162,4.1569162,90,90,90),],2,(1.0,10,10)), 27 } 28 29 New key values will be added to the list of options. 30 If a key is duplicated, the information in `UserCalibrants.py` will 31 override the information in this file. 32 33 Note, some useful Bravais numbers are: F-cubic=0, I-cubic=1, P-cubic=2, R3/m (hex)=3, P6=4, P4mmm=6 14 34 """ 15 35 Calibrants={ … … 31 51 } 32 52 53 # this should not be duplicated in the UserCalibrants.py file: 54 try: 55 import UserCalibrants as userFile 56 Calibrants.update(userFile.Calibrants) 57 except: 58 pass -
trunk/exports/G2cif.py
r1045 r1057 25 25 #reload(G2IO) 26 26 import GSASIIgrid as G2gd 27 reload(G2gd) 27 28 import GSASIIstrIO as G2stIO 28 29 #reload(G2stIO) … … 36 37 #reload(G2pg) 37 38 import GSASIIstrMain as G2stMn 38 reload(G2stMn)39 #reload(G2stMn) 39 40 40 41 DEBUG = False #True to skip printing of reflection/powder profile lists … … 66 67 ''' 67 68 69 # ===== define functions for export method ======================================= 68 70 def openCIF(filnam): 69 71 if DEBUG: … … 115 117 #WriteCIFitem('_refine_diff_density_max',rhomax) #these need to be defined for each phase! 116 118 #WriteCIFitem('_refine_diff_density_min',rhomin) 117 WriteCIFitem('_computing_structure_refinement','GSAS-II (Toby & Von Dreele, 2013)')119 WriteCIFitem('_computing_structure_refinement','GSAS-II (Toby & Von Dreele, J. Appl. Cryst. 46, 544-549, 2013)') 118 120 try: 119 121 vars = str(len(self.OverallParms['Covariance']['varyList'])) … … 854 856 slam2 = self.sigDict.get('Lam2',-0.00009) 855 857 # always assume Ka1 & Ka2 if two wavelengths are present 858 WriteCIFitem('_diffrn_radiation_type','K\\a~1,2~') 856 859 WriteCIFitem('loop_' + 857 860 '\n\t_diffrn_radiation_wavelength' + 858 861 '\n\t_diffrn_radiation_wavelength_wt' + 859 '\n\t_diffrn_radiation_type' +860 862 '\n\t_diffrn_radiation_wavelength_id') 861 863 WriteCIFitem(' ' + PutInCol(G2mth.ValEsd(lam1,slam1),15)+ 862 864 PutInCol('1.0',15) + 863 PutInCol('K\\a~1~',10) +864 865 PutInCol('1',5)) 865 866 WriteCIFitem(' ' + PutInCol(G2mth.ValEsd(lam2,slam2),15)+ 866 867 PutInCol(G2mth.ValEsd(ratio,sratio),15)+ 867 PutInCol('K\\a~2~',10) +868 868 PutInCol('2',5)) 869 869 else: … … 903 903 ) 904 904 WriteCIFitem('loop_' + 905 '\n\t_pd_proc_ls_R_F_factor' + 906 '\n\t_pd_proc_ls_R_Fsqd_factor') 905 '\n\t_gsas_proc_phase_R_F_factor' + 906 '\n\t_gsas_proc_phase_R_Fsqd_factor' + 907 '\n\t_gsas_proc_phase_id' + 908 '\n\t_gsas_proc_phase_block_id') 907 909 for phasenam in phasebyhistDict.get(histlbl): 908 910 pfx = str(self.Phases[phasenam]['pId'])+':'+str(hId)+':' … … 910 912 ' '+ 911 913 ' '+G2mth.ValEsd(histblk[pfx+'Rf']/100.,-.00009) + 912 ' '+G2mth.ValEsd(histblk[pfx+'Rf^2']/100.,-.00009) 914 ' '+G2mth.ValEsd(histblk[pfx+'Rf^2']/100.,-.00009)+ 915 ' '+str(self.Phases[phasenam]['pId'])+ 916 ' '+datablockidDict[phasenam] 913 917 ) 914 918 else: 919 # single phase in this histogram 915 920 pfx = '0:'+str(hId)+':' 916 WriteCIFitem('_ pd_proc_ls_R_F_factor ','%.5f'%(histblk[pfx+'Rf']/100.))917 WriteCIFitem('_ pd_proc_ls_R_Fsqd_factor ','%.5f'%(histblk[pfx+'Rf^2']/100.))921 WriteCIFitem('_refine_ls_R_F_factor ','%.5f'%(histblk[pfx+'Rf']/100.)) 922 WriteCIFitem('_refine_ls_R_Fsqd_factor ','%.5f'%(histblk[pfx+'Rf^2']/100.)) 918 923 919 924 WriteCIFitem('_pd_proc_ls_prof_R_factor ','%.5f'%(histblk['R']/100.)) 920 925 WriteCIFitem('_pd_proc_ls_prof_wR_factor ','%.5f'%(histblk['wR']/100.)) 921 WriteCIFitem('_ pd_proc_ls_prof_R_B_factor ','%.5f'%(histblk['Rb']/100.))922 WriteCIFitem('_ pd_proc_ls_prof_wR_B_factor','%.5f'%(histblk['wRb']/100.))926 WriteCIFitem('_gsas_proc_ls_prof_R_B_factor ','%.5f'%(histblk['Rb']/100.)) 927 WriteCIFitem('_gsas_proc_ls_prof_wR_B_factor','%.5f'%(histblk['wRb']/100.)) 923 928 WriteCIFitem('_pd_proc_ls_prof_wR_expected','%.5f'%(histblk['wRmin']/100.)) 924 929 … … 1145 1150 WriteCIFitem('_reflns_R_F_factor_obs ','%.4f'%(histblk[pfx+'Rf']/100.)) 1146 1151 WriteCIFitem('_reflns_R_Fsqd_factor_obs','%.4f'%(histblk[pfx+'Rf^2']/100.)) 1147 1148 #============================================================ 1152 def EditAuthor(event=None): 1153 'Edit the CIF author name' 1154 dlg = G2gd.SingleStringDialog(self.G2frame, 1155 'Get CIF Author', 1156 'Provide CIF Author name (Last, First)', 1157 value=self.author) 1158 if not dlg.Show(): 1159 dlg.Destroy() 1160 return False # cancel was pressed 1161 self.author = dlg.GetValue() 1162 dlg.Destroy() 1163 try: 1164 self.OverallParms['Controls']["Author"] = self.author # save for future 1165 except KeyError: 1166 pass 1167 return True 1168 def EditInstNames(event=None,msg=''): 1169 'Provide a dialog for editing instrument names' 1170 dictlist = [] 1171 keylist = [] 1172 lbllist = [] 1173 for hist in self.Histograms: 1174 if hist.startswith("PWDR"): 1175 key2 = "Sample Parameters" 1176 d = self.Histograms[hist][key2] 1177 elif hist.startswith("HKLF"): 1178 key2 = "Instrument Parameters" 1179 d = self.Histograms[hist][key2][0] 1180 1181 lbllist.append(hist) 1182 dictlist.append(d) 1183 keylist.append('InstrName') 1184 instrname = d.get('InstrName') 1185 if instrname is None: 1186 d['InstrName'] = '' 1187 return G2gd.CallScrolledMultiEditor( 1188 self.G2frame,dictlist,keylist, 1189 prelbl=range(1,len(dictlist)+1), 1190 postlbl=lbllist, 1191 title='Instrument names', 1192 header="Edit instrument names. Note that a non-blank\nname is required for all histograms"+msg) 1193 def EditCIFDefaults(parent): 1194 import wx.lib.scrolledpanel as wxscroll 1195 cfrm = wx.Dialog(parent,style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) 1196 cfrm.SetTitle('child') 1197 vbox = wx.BoxSizer(wx.VERTICAL) 1198 cpnl = wxscroll.ScrolledPanel(cfrm,size=(300,300)) 1199 cbox = wx.BoxSizer(wx.VERTICAL) 1200 but = wx.Button(cpnl, wx.ID_ANY,'Edit CIF Author') 1201 but.Bind(wx.EVT_BUTTON,EditAuthor) 1202 cbox.Add(but,0,wx.ALIGN_CENTER,3) 1203 but = wx.Button(cpnl, wx.ID_ANY,'Edit Instrument Name(s)') 1204 but.Bind(wx.EVT_BUTTON,EditInstNames) 1205 cbox.Add(but,0,wx.ALIGN_CENTER,3) 1206 1207 cpnl.SetSizer(cbox) 1208 cpnl.SetAutoLayout(1) 1209 cpnl.SetupScrolling() 1210 #cpnl.Bind(rw.EVT_RW_LAYOUT_NEEDED, self.OnLayoutNeeded) 1211 cpnl.Layout() 1212 1213 vbox.Add(cpnl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 0) 1214 btnsizer = wx.StdDialogButtonSizer() 1215 btn = wx.Button(cfrm, wx.ID_OK, "Create CIF") 1216 btn.SetDefault() 1217 btnsizer.AddButton(btn) 1218 btn = wx.Button(cfrm, wx.ID_CANCEL) 1219 btnsizer.AddButton(btn) 1220 btnsizer.Realize() 1221 vbox.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 5) 1222 cfrm.SetSizer(vbox) 1223 vbox.Fit(cfrm) 1224 if cfrm.ShowModal() == wx.ID_OK: 1225 val = True 1226 else: 1227 val = False 1228 cfrm.Destroy() 1229 return val 1230 1231 # ===== end of functions for export method ======================================= 1232 #================================================================================= 1233 1149 1234 # the export process starts here 1150 1235 # load all of the tree into a set of dicts … … 1171 1256 self.xtalDict[i] = hist 1172 1257 # is there anything to export? 1173 if len(self.Phases) + len(self.powderDict) + len(self.xtalDict) == 0:1174 1175 1176 'No data or phases to include in CIF')1177 1178 # is there a file name defined?1258 if len(self.Phases) == len(self.powderDict) == len(self.xtalDict) == 0: 1259 self.G2frame.ErrorDialog( 1260 'Empty project', 1261 'Project does not contain interconnected data & phase(s)') 1262 return 1263 # get the project file name 1179 1264 self.CIFname = os.path.splitext( 1180 1265 os.path.split(self.G2frame.GSASprojectfile)[1] 1181 1266 )[0] 1182 1267 self.CIFname = self.CIFname.replace(' ','') 1183 if not self.CIFname: 1184 self.G2frame.ErrorDialog( 1185 'No GPX name', 1186 'Please save the project to provide a name') 1187 return 1268 if not self.CIFname: # none defined & needed, save as GPX to get one 1269 self.G2frame.OnFileSaveas(None) 1270 if not self.G2frame.GSASprojectfile: return 1271 self.CIFname = os.path.splitext( 1272 os.path.split(self.G2frame.GSASprojectfile)[1] 1273 )[0] 1274 self.CIFname = self.CIFname.replace(' ','') 1188 1275 # test for quick CIF mode or no data 1189 1276 self.quickmode = False … … 1217 1304 pass 1218 1305 while not (self.author or self.quickmode): 1219 dlg = G2gd.SingleStringDialog(self.G2frame,'Get CIF Author','Provide CIF Author name (Last, First)') 1220 if not dlg.Show(): return # cancel was pressed 1221 self.author = dlg.GetValue() 1222 dlg.Destroy() 1223 try: 1224 self.OverallParms['Controls']["Author"] = self.author # save for future 1225 except KeyError: 1226 pass 1306 if not EditAuthor(): return 1227 1307 self.shortauthorname = self.author.replace(',','').replace(' ','')[:20] 1228 1308 1229 # check the instrument name for every histogram1309 # check there is an instrument name for every histogram 1230 1310 if not self.quickmode: 1231 dictlist = []1232 keylist = []1233 lbllist = []1234 1311 invalid = 0 1235 1312 key3 = 'InstrName' … … 1240 1317 elif hist.startswith("HKLF"): 1241 1318 key2 = "Instrument Parameters" 1242 d = self.Histograms[hist][key2][0] 1243 1244 lbllist.append(hist) 1245 dictlist.append(d) 1246 keylist.append(key3) 1319 d = self.Histograms[hist][key2][0] 1247 1320 instrname = d.get(key3) 1248 1321 if instrname is None: … … 1258 1331 "File/Copy option to duplicate the name" 1259 1332 ) 1260 if not G2gd.CallScrolledMultiEditor( 1261 self.G2frame,dictlist,keylist, 1262 prelbl=range(1,len(dictlist)+1), 1263 postlbl=lbllist, 1264 title='Instrument names', 1265 header="Edit instrument names. Note that a non-blank\nname is required for all histograms"+msg, 1266 ): return 1333 if not EditInstNames(msg=msg): return 1334 # check for a distance-angle range search range for each phase 1335 if not self.quickmode: 1336 for phasenam in sorted(self.Phases.keys()): 1337 i = self.Phases[phasenam]['pId'] 1338 phasedict = self.Phases[phasenam] # pointer to current phase info 1339 generalData = phasedict['General'] 1340 if 'DisAglCtls' not in generalData: 1341 dlg = G2gd.DisAglDialog(self.G2frame,{},generalData) 1342 if dlg.ShowModal() == wx.ID_OK: 1343 generalData['DisAglCtls'] = dlg.GetData() 1344 else: 1345 dlg.Destroy() 1346 return 1347 dlg.Destroy() 1267 1348 1268 1349 if oneblock and not self.quickmode: 1269 1350 # select a dataset to use (there should only be one set in one block, 1270 # but take whatever comes 1st 1351 # but take whatever comes 1st) 1271 1352 for hist in self.Histograms: 1272 1353 histblk = self.Histograms[hist] … … 1282 1363 fil = self.defSaveFile() 1283 1364 if not fil: return 1284 openCIF(fil) 1365 if not self.quickmode: # give the user a chance to edit all defaults 1366 if not EditCIFDefaults(self.G2frame): return 1285 1367 #====================================================================== 1286 1368 # Start writing the CIF - single block 1287 1369 #====================================================================== 1370 openCIF(fil) 1288 1371 if oneblock: 1289 1372 WriteCIFitem('data_'+self.CIFname)
Note: See TracChangeset
for help on using the changeset viewer.