Changeset 2899 for branch/2frame


Ignore:
Timestamp:
Jul 3, 2017 4:12:45 PM (4 years ago)
Author:
toby
Message:

partial reorg

Location:
branch/2frame
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branch/2frame/GSASII.py

    r2898 r2899  
    1818import os
    1919import sys
    20 import math
    21 import copy
    22 import random as ran
    23 import glob
    24 import imp
    25 import inspect
    26 import numpy as np
    27 import scipy as sp
    28 import wx
    29 import wx.lib.scrolledpanel as wxscroll
    30 try:  # patch for LANG environment var problem on occasional OSX machines
    31     import locale
    32     locale.getdefaultlocale()
    33 except ValueError:
    34     print('Fixing location (see https://github.com/matplotlib/matplotlib/issues/5420.)')
    35     os.environ['LC_ALL'] = 'en_US.UTF-8'
    36     locale.getdefaultlocale()
    37 import matplotlib as mpl
    38 try:
    39     import OpenGL as ogl
    40 except ImportError:
    41     print('*******************************************************')
    42     print('PyOpenGL is missing from your python installation')
    43     print('     - we will try to install it')
    44     print('*******************************************************')
    45     def install_with_easyinstall(package):
    46         try:
    47             print "trying a system-wide PyOpenGl install"
    48             easy_install.main(['-f',os.path.split(__file__)[0],package])
    49             return
    50         except:
    51             pass
    52         try:
    53             print "trying a user level PyOpenGl install"
    54             easy_install.main(['-f',os.path.split(__file__)[0],'--user',package])
    55             return
    56         except:
    57             print "Install of '+package+' failed. Please report this information:"
    58             import traceback
    59             print traceback.format_exc()
    60             sys.exit()
    61     from setuptools.command import easy_install
    62     install_with_easyinstall('PyOpenGl')
    63     print('*******************************************************')         
    64     print('OpenGL has been installed. Restarting GSAS-II')
    65     print('*******************************************************')         
    66     loc = os.path.dirname(__file__)
    67     import subprocess
    68     subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py')])
    69     sys.exit()
    70    
    71 # load the GSAS routines
    72 import GSASIIpath
    73 GSASIIpath.SetVersionNumber("$Revision$")
    74 import GSASIIIO as G2IO
    75 import GSASIIElem as G2elem
    76 import GSASIIgrid as G2gd
    77 import GSASIIctrls as G2G
    78 import GSASIIplot as G2plt
    79 import GSASIIpwd as G2pwd
    80 import GSASIIpwdGUI as G2pdG
    81 import GSASIIspc as G2spc
    82 import GSASIIstrMain as G2stMn
    83 import GSASIIstrIO as G2stIO
    84 import GSASIImath as G2mth
    85 import GSASIImapvars as G2mv
    86 import GSASIIobj as G2obj
    87 import GSASIIlattice as G2lat
    88 import GSASIIlog as log
    89 WACV = wx.ALIGN_CENTER_VERTICAL
    90 #                GSASIIpath.IPyBreak()
    9120
    9221__version__ = '0.3.0'
     
    9726sys.stderr = sys.stdout
    9827
    99 def create(parent):
    100     return GSASII(parent)
    101 
    102 def SetDefaultDData(dType,histoName,NShkl=0,NDij=0):
    103     if dType in ['SXC','SNC']:
    104         return {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
    105             'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
    106             'Extinction':['Lorentzian','None', {'Tbar':0.1,'Cos2TM':0.955,
    107             'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}],
    108             'Flack':[0.0,False]}
    109     elif dType == 'SNT':
    110         return {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
    111             'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
    112             'Extinction':['Lorentzian','None', {
    113             'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}]}
    114     elif 'P' in dType:
    115         return {'Histogram':histoName,'Show':False,'Scale':[1.0,False],
    116             'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{},[],0.1],
    117             'Size':['isotropic',[1.,1.,1.],[False,False,False],[0,0,1],
    118                 [1.,1.,1.,0.,0.,0.],6*[False,]],
    119             'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
    120                 NShkl*[0.01,],NShkl*[False,]],
    121             'HStrain':[NDij*[0.0,],NDij*[False,]],                         
    122             'Extinction':[0.0,False],'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}}
     28#def create(parent):
     29#    return GSASII(parent)
    12330
    12431# class GSASIIsplit(wx.SplitterWindow):
     
    13542#         evt.Skip()
    13643# #        print "sash changing to %s\n" % str(evt.GetSashPosition())
    137 
    138 class GSASII(wx.Frame):
    139     '''Define the main GSAS-II frame and its associated menu items
    140     '''
    141     def MenuBinding(self,event):
    142         '''Called when a menu is clicked upon; looks up the binding in table
    143         '''
    144         log.InvokeMenuCommand(event.GetId(),self,event)
    145            
    146     def Bind(self,eventtype,handler,*args,**kwargs):
    147         '''Override the Bind function so that we can wrap calls that will be logged.
    148        
    149         N.B. This is a bit kludgy. Menu bindings with an id are wrapped and
    150         menu bindings with an object and no id are not.
    151         '''
    152         if eventtype == wx.EVT_MENU and 'id' in kwargs:
    153             menulabels = log.SaveMenuCommand(kwargs['id'],self,handler)
    154             if menulabels:
    155                 wx.Frame.Bind(self,eventtype,self.MenuBinding,*args,**kwargs)
     44   
     45if __name__ == '__main__':
     46    import numpy as np
     47    import scipy as sp
     48    import wx
     49    import wx.lib.scrolledpanel as wxscroll
     50    try:  # patch for LANG environment var problem on occasional OSX machines
     51        import locale
     52        locale.getdefaultlocale()
     53    except ValueError:
     54        print('Fixing location (see https://github.com/matplotlib/matplotlib/issues/5420.)')
     55        os.environ['LC_ALL'] = 'en_US.UTF-8'
     56        locale.getdefaultlocale()
     57    import matplotlib as mpl
     58    try:
     59        import OpenGL as ogl
     60    except ImportError:
     61        print('*******************************************************')
     62        print('PyOpenGL is missing from your python installation')
     63        print('     - we will try to install it')
     64        print('*******************************************************')
     65        def install_with_easyinstall(package):
     66            try:
     67                print "trying a system-wide PyOpenGl install"
     68                easy_install.main(['-f',os.path.split(__file__)[0],package])
    15669                return
    157         wx.Frame.Bind(self,eventtype,handler,*args,**kwargs)     
    158    
    159     def _Add_FileMenuItems(self, parent):
    160         item = parent.Append(
    161             help='Open a GSAS-II project file (*.gpx)', id=wx.ID_ANY,
    162             kind=wx.ITEM_NORMAL,text='&Open project...')
    163         self.Bind(wx.EVT_MENU, self.OnFileOpen, id=item.GetId())
    164         item = parent.Append(
    165             help='Save project under current name', id=wx.ID_ANY,
    166             kind=wx.ITEM_NORMAL,text='&Save project')
    167         self.Bind(wx.EVT_MENU, self.OnFileSave, id=item.GetId())
    168         item = parent.Append(
    169             help='Save current project to new file', id=wx.ID_ANY,
    170             kind=wx.ITEM_NORMAL,text='Save project as...')
    171         self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=item.GetId())
    172         item = parent.Append(
    173             help='Create empty new project, saving current is optional', id=wx.ID_ANY,
    174             kind=wx.ITEM_NORMAL,text='&New project')
    175         self.Bind(wx.EVT_MENU, self.OnFileClose, id=item.GetId())
    176         item = parent.Append(wx.ID_PREFERENCES, text = "&Preferences")
    177         self.Bind(wx.EVT_MENU, self.OnPreferences, item)
    178         if GSASIIpath.GetConfigValue('debug'):
    179             def OnIPython(event):
    180                 GSASIIpath.IPyBreak()
    181             item = parent.Append(wx.ID_ANY, text = "IPython Console")
    182             self.Bind(wx.EVT_MENU, OnIPython, item)
    183         item = parent.Append(
    184             help='Exit from GSAS-II', id=wx.ID_ANY,
    185             kind=wx.ITEM_NORMAL,text='&Exit')
    186         self.Bind(wx.EVT_MENU, self.OnFileExit, id=item.GetId())
    187        
    188     def _Add_DataMenuItems(self,parent):
    189         # item = parent.Append(
    190         #     help='',id=wx.ID_ANY,
    191         #     kind=wx.ITEM_NORMAL,
    192         #     text='Read image data...')
    193         # self.Bind(wx.EVT_MENU, self.OnImageRead, id=item.GetId())
    194         item = parent.Append(
    195             help='',id=wx.ID_ANY,
    196             kind=wx.ITEM_NORMAL,
    197             text='Read Powder Pattern Peaks...')
    198         self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=item.GetId())
    199         item = parent.Append(
    200             help='',id=wx.ID_ANY,
    201             kind=wx.ITEM_NORMAL,
    202             text='Sum powder data')
    203         self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=item.GetId())
    204         item = parent.Append(
    205             help='',id=wx.ID_ANY,
    206             kind=wx.ITEM_NORMAL,
    207             text='Sum image data')
    208         self.Bind(wx.EVT_MENU, self.OnImageSum, id=item.GetId())
    209         item = parent.Append(
    210             help='',id=wx.ID_ANY,
    211             kind=wx.ITEM_NORMAL,
    212             text='Add new phase')
    213         self.Bind(wx.EVT_MENU, self.OnAddPhase, id=item.GetId())
    214         item = parent.Append(
    215             help='',id=wx.ID_ANY,
    216             kind=wx.ITEM_NORMAL,
    217             text='Delete phase')
    218         self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=item.GetId())
    219         item = parent.Append(
    220             help='Rename the selected data tree item (PWDR, HKLF or IMG)',id=wx.ID_ANY,
    221             kind=wx.ITEM_NORMAL,
    222             text='Rename tree item')
    223         self.Bind(wx.EVT_MENU, self.OnRenameData, id=item.GetId())
    224         item = parent.Append(
    225             help='Delete selected data items from data tree',id=wx.ID_ANY,
    226             kind=wx.ITEM_NORMAL,
    227             text='Delete tree items')
    228         self.Bind(wx.EVT_MENU, self.OnDataDelete, id=item.GetId())
    229         expandmenu = wx.Menu()
    230         item = parent.AppendMenu(
    231             wx.ID_ANY, 'Expand tree items', expandmenu,
    232             help='Expand items of type in GSAS-II data tree')
    233         for s in 'all','IMG','PWDR','PDF','HKLF','SASD','REFD':
    234             if s == 'all':
    235                 help = 'Expand all items in GSAS-II data tree'
    236             else:
    237                 help = 'Expand '+s+' type items in GSAS-II data tree'
    238             item = expandmenu.Append(wx.ID_ANY,kind=wx.ITEM_NORMAL,text=s,help=help)
    239             self.Bind(wx.EVT_MENU,self.ExpandAll,id=item.GetId())
    240         movemenu = wx.Menu()
    241         item = parent.AppendMenu(
    242             wx.ID_ANY, 'Move tree items', movemenu,
    243             help='Move items of type items to end of GSAS-II data tree')
    244         for s in 'IMG','PWDR','PDF','HKLF','SASD','REFD','Phase':
    245             help = 'Move '+s+' type items to end of GSAS-II data tree'
    246             item = movemenu.Append(wx.ID_ANY,kind=wx.ITEM_NORMAL,text=s,help=help)
    247             self.Bind(wx.EVT_MENU,self.MoveTreeItems,id=item.GetId())
    248 
    249     def _Add_CalculateMenuItems(self,parent):
    250         item = parent.Append(help='Create PDF tree entries for selected powder patterns',
    251             id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Setup PDFs')
    252         self.MakePDF.append(item)
    253         self.Bind(wx.EVT_MENU, self.OnMakePDFs, id=item.GetId())
    254        
    255         item = parent.Append(help='View least squares parameters',
    256             id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='&View LS parms')
    257         self.Bind(wx.EVT_MENU, self.OnShowLSParms, id=item.GetId())
    258        
    259         item = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,
    260             text='&Refine')
    261         if len(self.Refine): # extend state for new menus to match main (on mac)
    262             state = self.Refine[0].IsEnabled()
    263         else:
    264             state = False
    265         item.Enable(state)
    266         self.Refine.append(item)
    267         self.Bind(wx.EVT_MENU, self.OnRefine, id=item.GetId())
    268        
    269         item = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,
    270             text='Sequential refine')
    271         self.Bind(wx.EVT_MENU, self.OnSeqRefine, id=item.GetId())
    272         if len(self.SeqRefine): # extend state for new menus to match main (on mac)
    273             state = self.SeqRefine[0].IsEnabled()
    274         else:
    275             state = False
    276         item.Enable(state)
    277         self.SeqRefine.append(item) # save menu obj for use in self.EnableSeqRefineMenu
    278 #        if GSASIIpath.GetConfigValue('debug'): # allow exceptions for debugging
    279 #            item = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,
    280 #                text='tree test')
    281 #            self.Bind(wx.EVT_MENU, self.TreeTest, id=item.GetId())
    282 
    283     def _init_Imports(self):
    284         '''import all the G2phase*.py & G2sfact*.py & G2pwd*.py files that
    285         are found in the path
    286         '''
    287 
    288         self.ImportPhaseReaderlist = []
    289         self._init_Import_routines('phase',self.ImportPhaseReaderlist,'Phase')
    290         self.ImportSfactReaderlist = []
    291         self._init_Import_routines('sfact',self.ImportSfactReaderlist,'Struct_Factor')
    292         self.ImportPowderReaderlist = []
    293         self._init_Import_routines('pwd',self.ImportPowderReaderlist,'Powder_Data')
    294         self.ImportSmallAngleReaderlist = []
    295         self._init_Import_routines('sad',self.ImportSmallAngleReaderlist,'SmallAngle_Data')
    296         self.ImportReflectometryReaderlist = []
    297         self._init_Import_routines('rfd',self.ImportReflectometryReaderlist,'Reflectometry_Data')
    298         self.ImportPDFReaderlist = []
    299         self._init_Import_routines('pdf',self.ImportPDFReaderlist,'PDF_Data')
    300         self.ImportImageReaderlist = []
    301         self._init_Import_routines('img',self.ImportImageReaderlist,'Images')
    302         self.ImportMenuId = {}
    303 
    304     def _init_Import_routines(self,prefix,readerlist,errprefix):
    305         '''import all the import readers matching the prefix
    306         '''
    307         #path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file
    308         #pathlist = sys.path[:]
    309         #if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2)
    310         #path2GSAS2 = os.path.join(
    311         #    os.path.dirname(os.path.realpath(__file__)), # location of this file
    312         #    'imports')
    313         pathlist = sys.path[:]
    314         #if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2)
    315         if '.' not in pathlist: pathlist.append('.') # insert the directory where G2 is started
    316 
    317         filelist = []
    318         for path in pathlist:
    319             for filename in glob.iglob(os.path.join(
    320                 path,
    321                 "G2"+prefix+"*.py")):
    322                 filelist.append(filename)   
    323                 #print 'debug: found',filename
    324         filelist = sorted(list(set(filelist))) # remove duplicates
    325         for filename in filelist:
    326             path,rootname = os.path.split(filename)
    327             pkg = os.path.splitext(rootname)[0]
    328             try:
    329                 fp = None
    330                 fp, fppath,desc = imp.find_module(pkg,[path,])
    331                 pkg = imp.load_module(pkg,fp,fppath,desc)
    332                 for clss in inspect.getmembers(pkg): # find classes defined in package
    333                     if clss[0].startswith('_'): continue
    334                     if inspect.isclass(clss[1]):
    335                         # check if we have the required methods
    336                         for m in 'Reader','ExtensionValidator','ContentsValidator':
    337                             if not hasattr(clss[1],m): break
    338                             if not callable(getattr(clss[1],m)): break
    339                         else:
    340                             reader = clss[1]() # create an import instance
    341                             if reader.UseReader:
    342                                 readerlist.append(reader)
    343             except AttributeError:
    344                 print 'Import_'+errprefix+': Attribute Error '+ filename
    345             #except ImportError:
    346             #    print 'Import_'+errprefix+': Error importing file '+ filename
    347             except Exception,errmsg:
    348                 print('\nImport_'+errprefix+': Error importing file '+ filename)
    349                 print(u'Error message: {}\n'.format(errmsg))
    350             if fp: fp.close()
    351 
    352     def EnableSeqRefineMenu(self):
    353         '''Enable or disable the sequential refinement menu items based on the
    354         contents of the Controls 'Seq Data' item (if present)
    355         '''
    356         controls = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.root, 'Controls'))
    357         if controls.get('Seq Data'):
    358             for i in self.SeqRefine: i.Enable(True)
    359         else:
    360             for i in self.SeqRefine: i.Enable(False)
    361 
    362     def PreviewFile(self,filename,fp):
    363         'confirm we have the right file'
    364         rdmsg = 'File '+ filename +' begins:\n\n'
    365         try:
    366             rdmsg += fp.read(80)
    367             rdmsg += '\n\nDo you want to read this file?'
    368         except UnicodeDecodeError:
    369             rdmsg = None
    370         if rdmsg is None or not all([ord(c) < 128 and ord(c) != 0 for c in rdmsg]): # show only if ASCII
    371             rdmsg = 'File '+ filename +' is a binary file. Do you want to read this file?'
    372         # it would be better to use something that
    373         # would resize better, but this will do for now
    374         dlg = wx.MessageDialog(
    375             self, rdmsg,
    376             'Is this the file you want?',
    377             wx.YES_NO | wx.ICON_QUESTION,
    378             )
    379         dlg.SetSize((700,300)) # does not resize on Mac
    380         result = wx.ID_NO
    381         try:
    382             result = dlg.ShowModal()
    383         finally:
    384             dlg.Destroy()
    385         if result == wx.ID_NO: return True
    386         return False
    387    
    388     def OnImportGeneric(self,reader,readerlist,label,multiple=False,
    389         usedRanIdList=[],Preview=True,load2Tree=False):
    390         '''Used for all imports, including Phases, datasets, images...
    391 
    392         Called from :meth:`GSASII.OnImportPhase`, :meth:`GSASII.OnImportImage`,
    393         :meth:`GSASII.OnImportSfact`, :meth:`GSASII.OnImportPowder`,
    394         :meth:`GSASII.OnImportSmallAngle` and :meth:'GSASII.OnImportReflectometry`
    395 
    396         Uses reader_objects subclassed from :class:`GSASIIobj.ImportPhase`,
    397         :class:`GSASIIobj.ImportStructFactor`,
    398         :class:`GSASIIobj.ImportPowderData`,
    399         :class:`GSASIIobj.ImportSmallAngleData`
    400         :class:`GSASIIobj.ImportReflectometryData` or
    401         :class:`GSASIIobj.ImportImage`.
    402         If a specific reader is specified, only that method will be called,
    403         but if no reader is specified, every one that is potentially
    404         compatible (by file extension) will be tried on the file(s)
    405         selected in the Open File dialog.
    406 
    407         :param reader_object reader: This will be a reference to
    408           a particular object to be used to read a file or None,
    409           if every appropriate reader should be used.
    410 
    411         :param list readerlist: a list of reader objects appropriate for
    412           the current read attempt. At present, this will be either
    413           self.ImportPhaseReaderlist, self.ImportSfactReaderlist
    414           self.ImportPowderReaderlist or self.ImportImageReaderlist
    415           (defined in _init_Imports from the files found in the path),
    416           but in theory this list could be tailored.
    417           Used only when reader is None.
    418 
    419         :param str label: string to place on the open file dialog:
    420           Open `label` input file
    421 
    422         :param bool multiple: True if multiple files can be selected
    423           in the file dialog. False is default. At present True is used
    424           only for reading of powder data.
    425 
    426         :param list usedRanIdList: an optional list of random Ids that
    427           have been used and should not be reused
    428 
    429         :param bool Preview: indicates if a preview of the file should
    430           be shown. Default is True, but set to False for image files
    431           which are all binary.
    432 
    433         :param bool load2Tree: indicates if the file should be loaded
    434           into the data tree immediately (used for images only). True
    435           only when called from :meth:`OnImportImage`; causes return
    436           value to change to a list of True values rather than
    437           reader objects.
    438 
    439         :returns: a list of reader objects (rd_list) that were able
    440           to read the specified file(s). This list may be empty.
    441         '''
    442         self.lastimport = ''
    443         self.zipfile = None
    444         singlereader = True
    445         if reader is None:
    446             singlereader = False
    447             multiple = False
    448             #print "use all formats"
    449             choices = "any file (*.*)|*.*"
    450             choices += "|zip archive (.zip)|*.zip"
    451             extdict = {}
    452             # compile a list of allowed extensions
    453             for rd in readerlist:
    454                 fmt = rd.formatName
    455                 for extn in rd.extensionlist:
    456                     if not extdict.get(extn): extdict[extn] = []
    457                     extdict[extn] += [fmt,]
    458             for extn in sorted(extdict.keys(),cmp=lambda x,y: cmp(x.lower(), y.lower())):
    459                 fmt = ''
    460                 for f in extdict[extn]:
    461                     if fmt != "": fmt += ', '
    462                     fmt += f
    463                 choices += "|" + fmt + " file (*" + extn + ")|*" + extn
    464         else:
    465             readerlist = [reader,]
    466             # compile a list of allowed extensions
    467             choices = reader.formatName + " file ("
    468             w = ""
    469             for extn in reader.extensionlist:
    470                 if w != "": w += ";"
    471                 w += "*" + extn
    472             choices += w + ")|" + w
    473             choices += "|zip archive (.zip)|*.zip"
    474             if not reader.strictExtension:
    475                 choices += "|any file (*.*)|*.*"
    476         # get the file(s)
    477         if multiple:
    478             mode = wx.OPEN|wx.MULTIPLE
    479         else:
    480             mode = wx.OPEN
    481         filelist = G2G.GetImportFile(self,message="Choose "+label+" input file",
    482                     defaultFile="",wildcard=choices,style=mode)
    483         rd_list = []
    484         filelist1 = []
    485         for filename in filelist:
    486             # is this a zip file?
    487             if os.path.splitext(filename)[1].lower() == '.zip':
    488                 extractedfiles = G2IO.ExtractFileFromZip(
    489                     filename,parent=self,
    490                     multipleselect=True)
    491                 if extractedfiles is None: continue # error or Cancel
    492                 if extractedfiles != filename:
    493                     self.zipfile = filename # save zip name
    494                     filelist1 += extractedfiles
    495                     continue
    496             filelist1.append(filename)
    497         filelist = filelist1
    498         Start = True    #1st time read - clear selections below
    499         for filename in filelist:
    500             # is this a zip file?
    501             if os.path.splitext(filename)[1].lower() == '.zip':
    502                 extractedfile = G2IO.ExtractFileFromZip(filename,parent=self)
    503                 if extractedfile is None: continue # error or Cancel
    504                 if extractedfile != filename:
    505                     filename,self.zipfile = extractedfile,filename # now use the file that was created
    506             # determine which formats are compatible with this file
    507             primaryReaders = []
    508             secondaryReaders = []
    509             for rd in readerlist:
    510                 flag = rd.ExtensionValidator(filename)
    511                 if flag is None:
    512                     secondaryReaders.append(rd)
    513                 elif flag:
    514                     primaryReaders.append(rd)
    515             if len(secondaryReaders) + len(primaryReaders) == 0 and reader:
    516                 self.ErrorDialog('Not supported','The selected reader cannot read file '+filename)
    517                 return []
    518             elif len(secondaryReaders) + len(primaryReaders) == 0:
    519                 self.ErrorDialog('No Format','No matching format for file '+filename)
    520                 return []
    521 
    522             fp = None
    523             msg = ''
    524             fp = open(filename,'Ur')
    525             if len(filelist) == 1 and Preview:
    526                 if self.PreviewFile(filename,fp): return []
    527             self.lastimport = filename # this is probably not what I want to do -- it saves only the
    528             # last name in a series. See rd.readfilename for a better name.
    529 
    530             # try the file first with Readers that specify the
    531             # file's extension and later with ones that merely allow it
    532             errorReport = ''
    533             for rd in primaryReaders+secondaryReaders:
    534                 if Start:   #clear old bank selections to allow new ones to be selected by user
    535                     rd.selections = []
    536                     rd.dnames = []
    537                 rd.ReInitialize() # purge anything from a previous read
    538                 fp.seek(0)  # rewind
    539                 rd.errors = "" # clear out any old errors
    540                 if not rd.ContentsValidator(fp): # rejected on cursory check
    541                     errorReport += "\n  "+rd.formatName + ' validator error'
    542                     if rd.errors:
    543                         errorReport += ': '+rd.errors
    544                     continue
    545                 if len(rd.selections)>1 and Start:
    546                     dlg = G2G.G2MultiChoiceDialog(self,'Dataset Selector','Select data to read from the list below',rd.dnames)
    547                     if dlg.ShowModal() == wx.ID_OK:
    548                         rd.selections = dlg.GetSelections()
    549                     Start = False
    550                     dlg.Destroy()
    551                 repeat = True
    552                 rdbuffer = {} # create temporary storage for file reader
    553                 block = 0
    554                 fp.seek(0)  # rewind
    555                 while repeat: # loop if the reader asks for another pass on the file
    556                     block += 1
    557                     repeat = False
    558                     rd.objname = os.path.basename(filename)
    559                     flag = False
    560                     if GSASIIpath.GetConfigValue('debug'): # allow exceptions for debugging
    561                         flag = rd.Reader(filename,fp,self,buffer=rdbuffer,blocknum=block,
    562                             usedRanIdList=usedRanIdList,)
    563                     else:
    564                         try:
    565                             flag = rd.Reader(filename,fp,self,buffer=rdbuffer,
    566                                 blocknum=block,usedRanIdList=usedRanIdList,)
    567                         except rd.ImportException as detail:
    568                             rd.errors += "\n  Read exception: "+str(detail)
    569                         except Exception as detail:
    570                             import traceback
    571                             rd.errors += "\n  Unhandled read exception: "+str(detail)
    572                             rd.errors += "\n  Traceback info:\n"+str(traceback.format_exc())
    573                     if flag: # this read succeeded
    574                         if rd.SciPy:        #was default read by scipy; needs 1 time fixes
    575                             G2IO.EditImageParms(self,rd.Data,rd.Comments,rd.Image,filename)
    576                             rd.SciPy = False
    577                         rd.readfilename = filename
    578                         if load2Tree:   #images only
    579                             if rd.repeatcount == 1 and not rd.repeat: # skip image number if only one in set
    580                                 rd.Data['ImageTag'] = None
    581                             else:
    582                                 rd.Data['ImageTag'] = rd.repeatcount
    583                             rd.Data['formatName'] = rd.formatName
    584                             if rd.sumfile:
    585                                 rd.readfilename = rd.sumfile
    586                             G2IO.LoadImage2Tree(rd.readfilename,self,rd.Comments,rd.Data,rd.Npix,rd.Image)
    587                             rd_list.append(True) # save a stub the result before it is written over
    588                             del rd.Image
    589                         else:                                                   
    590                             rd_list.append(copy.deepcopy(rd)) # save the result before it is written over
    591                         if rd.repeat:
    592                             repeat = True
    593                         continue
    594                     errorReport += '\n'+rd.formatName + ' read error'
    595                     if rd.errors:
    596                         errorReport += ': '+rd.errors
    597                 if rd_list: # read succeeded, was there a warning or any errors?
    598                     if rd.warnings:
    599                         self.ErrorDialog('Read Warning','The '+ rd.formatName+
    600                             ' reader reported a warning message:\n\n'+rd.warnings)
    601                     break # success in reading, try no further
    602             else:
    603                 if singlereader:
    604                     print('The '+ rd.formatName+' reader was not able to read file '+filename+msg)
    605                     try:
    606                         print('\n\nError message(s):\n\t'+errorReport)
    607                     except:
    608                         pass
    609                     self.ErrorDialog('Read Error','The '+ rd.formatName+
    610                         ' reader was not able to read file '+filename+msg)
    611                 else:
    612                     print('No reader was able to read file '+filename+msg)
    613                     try:
    614                         print('\n\nError message(s):\n\t'+errorReport)
    615                     except:
    616                         pass
    617                     self.ErrorDialog('Read Error','No reader was able to read file '+filename+msg)
    618             if fp: fp.close()
    619         return rd_list
    620 
    621     def _Add_ImportMenu_Phase(self,parent):
    622         '''configure the Import Phase menus accord to the readers found in _init_Imports
    623         '''
    624         submenu = wx.Menu()
    625         item = parent.AppendMenu(wx.ID_ANY, 'Phase',
    626             submenu, help='Import phase data')
    627         for reader in self.ImportPhaseReaderlist:
    628             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,
    629                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    630             self.ImportMenuId[item.GetId()] = reader
    631             self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId())
    632         item = submenu.Append(wx.ID_ANY,help='Import phase data, use file to try to determine format',
    633             kind=wx.ITEM_NORMAL,text='guess format from file')
    634         self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId())
    635        
    636     def OnImportPhase(self,event):
    637         '''Called in response to an Import/Phase/... menu item
    638         to read phase information.
    639         dict self.ImportMenuId is used to look up the specific
    640         reader item associated with the menu item, which will be
    641         None for the last menu item, which is the "guess" option
    642         where all appropriate formats will be tried.
    643         '''
    644         # look up which format was requested
    645         reqrdr = self.ImportMenuId.get(event.GetId())
    646        
    647         # make a list of phase names, ranId's and the histograms used in those phases
    648         phaseRIdList,usedHistograms = self.GetPhaseInfofromTree()
    649         phaseNameList = usedHistograms.keys() # phase names in use
    650         usedHKLFhists = [] # used single-crystal histograms
    651         for p in usedHistograms:
    652             for h in usedHistograms[p]:
    653                 if h.startswith('HKLF ') and h not in usedHKLFhists:
    654                     usedHKLFhists.append(h)
    655                    
    656                    
    657         rdlist = self.OnImportGeneric(reqrdr,self.ImportPhaseReaderlist,
    658             'phase',usedRanIdList=phaseRIdList)
    659         if len(rdlist) == 0: return
    660         # for now rdlist is only expected to have one element
    661         # but below will allow multiple phases to be imported
    662         # if ever the import routines ever implement multiple phase reads.
    663         self.CheckNotebook()
    664         newPhaseList = []
    665         for rd in rdlist:
    666             PhaseName = ''
    667             dlg = wx.TextEntryDialog(self, 'Enter the name for the new phase',
    668                 'Edit phase name', rd.Phase['General']['Name'],style=wx.OK)
    669             while PhaseName == '':
    670                 dlg.CenterOnParent()
    671                 if dlg.ShowModal() == wx.ID_OK:
    672                     PhaseName = dlg.GetValue().strip()
    673                 else:
    674                     dlg.Destroy()
    675                     return
    676             dlg.Destroy()
    677             # make new phase names unique
    678             rd.Phase['General']['Name'] = G2obj.MakeUniqueLabel(PhaseName,phaseNameList)
    679             PhaseName = rd.Phase['General']['Name'][:]
    680             newPhaseList.append(PhaseName)
    681             print(u'Read phase {} from file {}'.format(PhaseName,self.lastimport))
    682             if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
    683                 sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
    684             else:
    685                 sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    686             psub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
    687             self.PatternTree.SetItemPyData(psub,rd.Phase)
    688             self.PatternTree.Expand(self.root) # make sure phases are seen
    689             self.PatternTree.Expand(sub)
    690             self.PatternTree.Expand(psub)
    691             wx.CallAfter(G2gd.SelectDataTreeItem,self,psub) #bring up new phase General tab
    692 
    693             if rd.Constraints:
    694                 sub = G2gd.GetPatternTreeItemId(self,self.root,'Constraints') # was created in CheckNotebook if needed
    695                 Constraints = self.PatternTree.GetItemPyData(sub)               
    696                 # TODO: make sure that NEWVAR names are unique here?
    697                 for i in rd.Constraints:
    698                     if type(i) is dict:
    699                         #for j in i: print j,' --> ',i[j]
    700                         if '_Explain' not in Constraints: Constraints['_Explain'] = {}
    701                         Constraints['_Explain'].update(i)
    702                         continue
    703                     Constraints['Phase'].append(i)
    704         if not newPhaseList: return # somehow, no new phases
    705         # get a list of existing histograms
    706         PWDRlist = []
    707         HKLFlist = []
    708         if self.PatternTree.GetCount():
    709             item, cookie = self.PatternTree.GetFirstChild(self.root)
    710             while item:
    711                 name = self.PatternTree.GetItemText(item)
    712                 if name.startswith('PWDR ') and name not in PWDRlist:
    713                     PWDRlist.append(name)
    714                 if name.startswith('HKLF ') and name not in HKLFlist:
    715                     HKLFlist.append(name)
    716                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    717         TextList = PWDRlist + HKLFlist
    718         if not TextList:
    719             return          #no histograms
    720         header = 'Select histogram(s) to add to new phase(s):'
    721         for phaseName in newPhaseList:
    722             header += '\n  '+phaseName
    723 
    724         notOK = True
    725         while notOK:
    726             result = G2G.ItemSelector(TextList,self,header,header='Add histogram(s)',multiple=True)
    727             if not result: return
    728             # check that selected single crystal histograms are not already in use!
    729             used = [TextList[i] for i in result if TextList[i] in usedHKLFhists]
    730             #for i in result:
    731             #    if TextList[i] in usedHKLFhists: used.append(TextList[i])
    732             if used:
    733                 msg = 'The following single crystal histogram(s) are already in use'
    734                 for i in used:
    735                     msg += '\n  '+str(i)
    736                 msg += '\nAre you sure you want to add them to this phase? '
    737                 msg += 'Associating a single crystal dataset to >1 histogram is usually an error, '
    738                 msg += 'so No is suggested here.'
    739                 if self.ErrorDialog('Likely error',msg,self,wtype=wx.YES_NO) == wx.ID_YES: notOK = False
    740             else:
    741                 notOK = False
    742         # connect new phases to histograms
    743         sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    744         if not sub:
    745             raise Exception('ERROR -- why are there no phases here?')
    746         wx.BeginBusyCursor()
    747         item, cookie = self.PatternTree.GetFirstChild(sub)
    748         while item: # loop over (new) phases
    749             phaseName = self.PatternTree.GetItemText(item)
    750             data = self.PatternTree.GetItemPyData(item)
    751             item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    752             if phaseName not in newPhaseList: continue
    753             generalData = data['General']
    754             SGData = generalData['SGData']
    755             Super = generalData.get('Super',0)
    756             SuperVec = []
    757             if Super:
    758                 SuperVec = np.array(generalData['SuperVec'][0])
    759             UseList = data['Histograms']
    760             NShkl = len(G2spc.MustrainNames(SGData))
    761             NDij = len(G2spc.HStrainNames(SGData))
    762             for i in result:
    763                 histoName = TextList[i]
    764                 if histoName in HKLFlist:
    765                     #redo UpdateHKLFdata(histoName) here:
    766                     Id = G2gd.GetPatternTreeItemId(self,self.root,histoName)
    767                     refDict,reflData = self.PatternTree.GetItemPyData(Id)
    768                     G,g = G2lat.cell2Gmat(generalData['Cell'][1:7])
    769                     Super = reflData.get('Super',0)
    770                     for iref,ref in enumerate(reflData['RefList']):
    771                         hkl = ref[:3]
    772                         if Super:
    773                             H = list(hkl+SuperVec*ref[3])
    774                         else:
    775                             H = hkl
    776                         ref[4+Super] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
    777                         iabsnt = G2spc.GenHKLf(H,SGData)[0]
    778                         if iabsnt:  #flag space gp. absences
    779                             if Super:
    780                                 if not ref[2+Super]:
    781                                     ref[3+Super] = 0
    782                                 else:
    783                                     ref[3+Super] = 1    #twin id
    784                             else:
    785                                 ref[3] = 0
    786                     UseList[histoName] = SetDefaultDData(reflData['Type'],histoName)
    787                 elif histoName in PWDRlist:
    788                     Id = G2gd.GetPatternTreeItemId(self,self.root,histoName)
    789                     refList = self.PatternTree.GetItemPyData(
    790                         G2gd.GetPatternTreeItemId(self,Id,'Reflection Lists'))
    791                     refList[generalData['Name']] = {}
    792                     UseList[histoName] = SetDefaultDData('PWDR',histoName,NShkl=NShkl,NDij=NDij)
    793                 else:
    794                     raise Exception('Unexpected histogram '+histoName)
    795         wx.EndBusyCursor()
    796         self.EnableRefineCommand()
    797        
    798         return # success
    799        
    800     def _Add_ImportMenu_Image(self,parent):
    801         '''configure the Import Image menus accord to the readers found in _init_Imports
    802         '''
    803         submenu = wx.Menu()
    804         item = parent.AppendMenu(wx.ID_ANY, 'Image',
    805             submenu, help='Import image file')
    806         for reader in self.ImportImageReaderlist:
    807             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,
    808                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    809             self.ImportMenuId[item.GetId()] = reader
    810             self.Bind(wx.EVT_MENU, self.OnImportImage, id=item.GetId())
    811         item = submenu.Append(wx.ID_ANY,help='Import image data, use file to try to determine format',
    812             kind=wx.ITEM_NORMAL,text='guess format from file')
    813         self.Bind(wx.EVT_MENU, self.OnImportImage, id=item.GetId())
    814        
    815     def OnImportImage(self,event):
    816         '''Called in response to an Import/Image/... menu item
    817         to read an image from a file. Like all the other imports,
    818         dict self.ImportMenuId is used to look up the specific
    819         reader item associated with the menu item, which will be
    820         None for the last menu item, which is the "guess" option
    821         where all appropriate formats will be tried.
    822 
    823         A reader object is filled each time an image is read.
    824         '''
    825         self.CheckNotebook()
    826         # look up which format was requested
    827         reqrdr = self.ImportMenuId.get(event.GetId())
    828         rdlist = self.OnImportGeneric(reqrdr,self.ImportImageReaderlist,
    829             'image',multiple=True,Preview=False,load2Tree=True)
    830         if rdlist:
    831             self.PatternTree.SelectItem(G2gd.GetPatternTreeItemId(self,self.Image,'Image Controls'))             #show last image to have beeen read
    832                    
    833     def _Add_ImportMenu_Sfact(self,parent):
    834         '''configure the Import Structure Factor menus accord to the readers found in _init_Imports
    835         '''
    836         submenu = wx.Menu()
    837         item = parent.AppendMenu(wx.ID_ANY, 'Structure Factor',
    838             submenu, help='Import Structure Factor data')
    839         for reader in self.ImportSfactReaderlist:
    840             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,               
    841                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    842             self.ImportMenuId[item.GetId()] = reader
    843             self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId())
    844         item = submenu.Append(wx.ID_ANY,
    845             help='Import Structure Factor, use file to try to determine format',
    846             kind=wx.ITEM_NORMAL,
    847             text='guess format from file')
    848         self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId())
    849 
    850     def OnImportSfact(self,event):
    851         '''Called in response to an Import/Structure Factor/... menu item
    852         to read single crystal datasets.
    853         dict self.ImportMenuId is used to look up the specific
    854         reader item associated with the menu item, which will be
    855         None for the last menu item, which is the "guess" option
    856         where all appropriate formats will be tried.
    857         '''
    858         # get a list of existing histograms
    859         HKLFlist = []
    860         if self.PatternTree.GetCount():
    861             item, cookie = self.PatternTree.GetFirstChild(self.root)
    862             while item:
    863                 name = self.PatternTree.GetItemText(item)
    864                 if name.startswith('HKLF ') and name not in HKLFlist:
    865                     HKLFlist.append(name)
    866                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    867         # look up which format was requested
    868         reqrdr = self.ImportMenuId.get(event.GetId())
    869         rdlist = self.OnImportGeneric(reqrdr,self.ImportSfactReaderlist,
    870             'Structure Factor',multiple=True)
    871         if len(rdlist) == 0: return
    872         self.CheckNotebook()
    873         newHistList = []
    874         for rd in rdlist:
    875             HistName = rd.objname
    876             if len(rdlist) <= 2:
    877                 dlg = wx.TextEntryDialog( # allow editing of Structure Factor name
    878                     self, 'Enter the name for the new Structure Factor',
    879                     'Edit Structure Factor name', HistName,
    880                     style=wx.OK)
    881                 dlg.CenterOnParent()
    882                 if dlg.ShowModal() == wx.ID_OK:
    883                     HistName = dlg.GetValue()
    884                 dlg.Destroy()
    885             HistName = 'HKLF '+G2obj.StripUnicode(HistName,'_')
    886             # make new histogram names unique
    887             if len(rd.Banks):
    888                 for Bank in rd.Banks:
    889                     valuesdict = {'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxint),}
    890                     HistName = G2obj.MakeUniqueLabel(HistName,HKLFlist)
    891                     print 'Read structure factor table '+HistName+' from file '+self.lastimport
    892                     Id = self.PatternTree.AppendItem(parent=self.root,text=HistName)
    893                     if not Bank['RefDict'].get('FF'):
    894                         Bank['RefDict']['FF'] = {}
    895                     self.PatternTree.SetItemPyData(Id,[valuesdict,Bank['RefDict']])
    896                     Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
    897                     self.PatternTree.SetItemPyData(Sub,copy.copy(rd.Parameters))
    898                     self.PatternTree.SetItemPyData(
    899                         self.PatternTree.AppendItem(Id,text='Reflection List'),{})  #dummy entry for GUI use
    900                     newHistList.append(HistName)
    901             else:
    902                 valuesdict = {'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxint),}
    903                 HistName = G2obj.MakeUniqueLabel(HistName,HKLFlist)
    904                 print 'Read structure factor table '+HistName+' from file '+self.lastimport
    905                 if not rd.RefDict.get('FF'):
    906                     rd.RefDict['FF'] = {}
    907                 Id = self.PatternTree.AppendItem(parent=self.root,text=HistName)
    908                 self.PatternTree.SetItemPyData(Id,[valuesdict,rd.RefDict])
    909                 Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
    910                 self.PatternTree.SetItemPyData(Sub,rd.Parameters)
    911                 self.PatternTree.SetItemPyData(
    912                     self.PatternTree.AppendItem(Id,text='Reflection List'),{})  #dummy entry for GUI use
    913                 newHistList.append(HistName)
    914                
    915             self.PatternTree.SelectItem(Id)
    916             self.PatternTree.Expand(Id)
    917             self.Sngl = True
    918 
    919         if not newHistList: return # somehow, no new histograms
    920         # make a list of phase names
    921         phaseRIdList,usedHistograms = self.GetPhaseInfofromTree()
    922         phaseNameList = usedHistograms.keys() # phase names in use
    923         if not phaseNameList: return # no phases yet, nothing to do
    924         header = 'Select phase(s) to add the new\nsingle crystal dataset(s) to:'
    925         for Name in newHistList:
    926             header += '\n  '+str(Name)
    927         result = G2G.ItemSelector(phaseNameList,self,header,header='Add to phase(s)',multiple=True)
    928         if not result: return
    929         # connect new phases to histograms
    930         sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    931         if not sub:
    932             raise Exception('ERROR -- why are there no phases here?')
    933         wx.BeginBusyCursor()
    934         item, cookie = self.PatternTree.GetFirstChild(sub)
    935         iph = -1
    936         while item: # loop over (new) phases
    937             iph += 1
    938             data = self.PatternTree.GetItemPyData(item)
    939             item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    940             if iph not in result: continue
    941             generalData = data['General']
    942             SGData = generalData['SGData']
    943             Super = generalData.get('Super',0)
    944             SuperVec = []
    945             if Super:
    946                 SuperVec = np.array(generalData['SuperVec'][0])
    947             UseList = data['Histograms']
    948             for histoName in newHistList:
    949                 #redo UpdateHKLFdata(histoName) here:
    950                 Id = G2gd.GetPatternTreeItemId(self,self.root,histoName)
    951                 refDict,reflData = self.PatternTree.GetItemPyData(Id)
    952                 UseList[histoName] = SetDefaultDData(reflData['Type'],histoName)
    953                 G,g = G2lat.cell2Gmat(generalData['Cell'][1:7])
    954                 if 'TwMax' in reflData:     #nonmerohedral twins present
    955                     UseList[histoName]['Twins'] = []
    956                     for iT in range(reflData['TwMax'][0]+1):
    957                         if iT in reflData['TwMax'][1]:
    958                             UseList[histoName]['Twins'].append([False,0.0])
    959                         else:
    960                             UseList[histoName]['Twins'].append([np.array([[1,0,0],[0,1,0],[0,0,1]]),[1.0,False,reflData['TwMax'][0]]])
    961                 else:   #no nonmerohedral twins
    962                     UseList[histoName]['Twins'] = [[np.array([[1,0,0],[0,1,0],[0,0,1]]),[1.0,False,0]],]
    963                 for iref,ref in enumerate(reflData['RefList']):
    964                     hkl = ref[:3]
    965                     if Super:
    966                         H = list(hkl+SuperVec*ref[3])
    967                     else:
    968                         H = hkl
    969                     ref[4+Super] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
    970                     iabsnt,mul,Uniq,phi = G2spc.GenHKLf(H,SGData)
    971                     if iabsnt:  #flag space gp. absences
    972                         if Super:
    973                             if not ref[2+Super]:
    974                                 ref[3+Super] = 0
    975                             else:
    976                                 ref[3+Super] = 1    #twin id?
    977                         else:
    978                             ref[3] = 0
    979         wx.EndBusyCursor()
    980         self.EnableRefineCommand()       
    981         return # success
    982 
    983     def _Add_ImportMenu_powder(self,parent):
    984         '''configure the Powder Data menus accord to the readers found in _init_Imports
    985         '''
    986         submenu = wx.Menu()
    987         item = parent.AppendMenu(wx.ID_ANY, 'Powder Data',
    988             submenu, help='Import Powder data')
    989         for reader in self.ImportPowderReaderlist:
    990             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,
    991                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    992             self.ImportMenuId[item.GetId()] = reader
    993             self.Bind(wx.EVT_MENU, self.OnImportPowder, id=item.GetId())
    994         item = submenu.Append(wx.ID_ANY,
    995             help='Import powder data, use file to try to determine format',
    996             kind=wx.ITEM_NORMAL,text='guess format from file')
    997         self.Bind(wx.EVT_MENU, self.OnImportPowder, id=item.GetId())
    998         submenu.AppendSeparator()
    999         item = submenu.Append(wx.ID_ANY,
    1000             help='Create a powder data set entry that will be simulated',
    1001             kind=wx.ITEM_NORMAL,text='Simulate a dataset')
    1002         self.Bind(wx.EVT_MENU, self.OnDummyPowder, id=item.GetId())
    1003        
    1004     def OpenPowderInstprm(self,instfile):
    1005         '''Read a GSAS-II (new) instrument parameter file
    1006 
    1007         :param str instfile: name of instrument parameter file
    1008 
    1009         '''
    1010         File = open(instfile,'r')
    1011         lines = File.readlines()
    1012         File.close()
    1013         return lines       
    1014            
    1015     def ReadPowderInstprm(self,instLines,bank,databanks,rd):
    1016         '''Read lines from a GSAS-II (new) instrument parameter file
    1017         similar to G2pwdGUI.OnLoad
    1018         If instprm file has multiple banks each with header #Bank n: ..., this
    1019         finds matching bank no. to load - problem with nonmatches?
    1020 
    1021         :param list instLines: strings from GSAS-II parameter file; can be concatenated with ';'
    1022         :param int  bank: bank number to check when instprm file has '#BANK n:...' strings
    1023             when bank = n then use parameters; otherwise skip that set. Ignored if BANK n:
    1024             not present. NB: this kind of instprm file made by a Save all profile command in Instrument Parameters
    1025         :return dict: Inst  instrument parameter dict if OK, or
    1026                 str: Error message if failed   
    1027         '''
    1028         if 'GSAS-II' not in instLines[0]: # not a valid file
    1029             return 'Not a valid GSAS-II instprm file'
    1030         newItems = []
    1031         newVals = []
    1032         Found = False
    1033         il = 0
    1034         if bank is None: # no bank was specified in the input file, is more than one present in file?
    1035             banklist = set([])
    1036             for S in instLines:
    1037                 if S[0] == '#' and 'Bank' in S:
    1038                     banklist.add(int(S.split(':')[0].split()[1]))
    1039             if len(banklist) > 1: # yes, the user must make a selection
    1040                 choices = [str(i) for i in banklist]
    1041                 bank = int(G2G.ItemSelector(choices,self.G2frame,multiple=False))
    1042             else:
    1043                 bank = 1
    1044             rd.powderentry[2] = bank
    1045         while il < len(instLines):
    1046             S = instLines[il]
    1047             if S[0] == '#':
    1048                 if Found:
    1049                     break
    1050                 if 'Bank' in S:
    1051                     if bank == int(S.split(':')[0].split()[1]):
    1052                         il += 1
    1053                         S = instLines[il]
    1054                     else:
    1055                         il += 1
    1056                         S = instLines[il]
    1057                         while il < len(instLines) and '#Bank' not in S:
    1058                             il += 1
    1059                             if il == len(instLines):
    1060                                 return 'Bank %d not found in instprm file'%(bank)
    1061                             S = instLines[il]
    1062                         continue
    1063                 else:   #a non #Bank file
    1064                     il += 1
    1065                     S = instLines[il]
    1066             Found = True
    1067             if '"""' in S:
    1068                 delim = '"""'
    1069             elif "'''" in S:
    1070                 delim = "'''"
    1071             else:
    1072                 S = S.replace(' ','')
    1073                 SS = S.strip().split(';')
    1074                 for s in SS:
    1075                     [item,val] = s.split(':',1)
    1076                     newItems.append(item)
    1077                     try:
    1078                         newVals.append(float(val))
    1079                     except ValueError:
    1080                         newVals.append(val)
    1081                 il += 1
    1082                 continue
    1083             # read multiline values, delimited by ''' or """
    1084             item,val = S.strip().split(':',1)
    1085             val = val.replace(delim,'').rstrip()
    1086             val += '\n'
    1087             while True:
    1088                 il += 1
    1089                 if il >= len(instLines): break
    1090                 S = instLines[il]
    1091                 if delim in S:
    1092                     val += S.replace(delim,'').rstrip()
    1093                     val += '\n'
    1094                     break
    1095                 else:
    1096                     val += S.rstrip()
    1097                     val += '\n'
    1098             newItems.append(item)
    1099             newVals.append(val)
    1100             il += 1
    1101         return [G2IO.makeInstDict(newItems,newVals,len(newVals)*[False,]),{}]
    1102        
    1103     def ReadPowderIparm(self,instfile,bank,databanks,rd):
    1104         '''Read a GSAS (old) instrument parameter file
    1105 
    1106         :param str instfile: name of instrument parameter file
    1107         :param int bank: the bank number read in the raw data file
    1108         :param int databanks: the number of banks in the raw data file.
    1109           If the number of banks in the data and instrument parameter files
    1110           agree, then the sets of banks are assumed to match up and bank
    1111           is used to select the instrument parameter file. If not and not TOF,
    1112           the user is asked to make a selection.
    1113         :param obj rd: the raw data (histogram) data object. This
    1114           sets rd.instbank.
    1115 
    1116         '''
    1117         if not os.path.exists(instfile): # no such file
    1118             return {}
    1119         fp = 0
    1120         try:
    1121             fp = open(instfile,'Ur')
    1122             Iparm = {}
    1123             for S in fp:
    1124                 if '#' in S[0]:
    1125                     continue
    1126                 Iparm[S[:12]] = S[12:-1]
    1127         except IOError:
    1128             print(u'Error reading file: {}'.format(instfile))
    1129         if fp:       
    1130             fp.close()
    1131 
    1132         ibanks = int(Iparm.get('INS   BANK  ','1').strip())
    1133         if ibanks == 1: # there is only one bank here, return it
    1134             rd.instbank = 1
    1135             rd.powderentry[2] = 1
    1136             return Iparm
    1137         if 'PNT' in Iparm['INS   HTYPE ']:      #allow mismatch between banks in data  iparm file for TOF
    1138             rd.instbank = bank
    1139         elif ibanks != databanks or bank is None:
    1140             choices = []
    1141             for i in range(1,1+ibanks):
    1142                 choices.append('Bank '+str(i))
    1143             bank = 1 + G2IO.BlockSelector(
    1144                 choices, self,
    1145                 title='Select an instrument parameter bank for '+
    1146                 os.path.split(rd.powderentry[0])[1]+' BANK '+str(bank)+
    1147                 '\nOr use Cancel to select from the default parameter sets',
    1148                 header='Block Selector')
    1149         if bank is None: return {}
    1150         # pull out requested bank # bank from the data, and change the bank to 1
    1151         IparmS = {}
    1152         for key in Iparm:
    1153             if 'INS' in key[:3]:    #skip around rubbish lines in some old iparm files
    1154                 if key[4:6] == "  ":
    1155                     IparmS[key] = Iparm[key]
    1156                 elif int(key[4:6].strip()) == bank:
    1157                     IparmS[key[:4]+' 1'+key[6:]] = Iparm[key]
    1158         rd.instbank = bank
    1159         return IparmS
    1160                        
    1161     def GetPowderIparm(self,rd, prevIparm, lastIparmfile, lastdatafile):
    1162         '''Open and read an instrument parameter file for a data file
    1163         Returns the list of parameters used in the data tree
    1164 
    1165         :param obj rd: the raw data (histogram) data object.
    1166 
    1167         :param str prevIparm: not used
    1168 
    1169         :param str lastIparmfile: Name of last instrument parameter
    1170           file that was read, or a empty string.
    1171 
    1172         :param str lastdatafile: Name of last data file that was read.
    1173 
    1174         :returns: a list of two dicts, the first containing instrument parameters
    1175           and the second used for TOF lookup tables for profile coeff.
    1176 
    1177         '''
    1178         def SetPowderInstParms(Iparm, rd):
    1179             '''extracts values from instrument parameters in rd.instdict
    1180             or in array Iparm.
    1181             Create and return the contents of the instrument parameter tree entry.
    1182             '''
    1183             Irads = {0:' ',1:'CrKa',2:'FeKa',3:'CuKa',4:'MoKa',5:'AgKa',6:'TiKa',7:'CoKa'}
    1184             DataType = Iparm['INS   HTYPE '].strip()[:3]  # take 1st 3 chars
    1185             # override inst values with values read from data file
    1186             Bank = rd.powderentry[2]    #should be used in multibank iparm files
    1187             if rd.instdict.get('type'):
    1188                 DataType = rd.instdict.get('type')
    1189             data = [DataType,]
    1190             instname = Iparm.get('INS  1INAME ')
    1191             irad = int(Iparm.get('INS  1 IRAD ','0'))
    1192             if instname:
    1193                 rd.Sample['InstrName'] = instname.strip()
    1194             if 'C' in DataType:
    1195                 wave1 = None
    1196                 wave2 = 0.0
    1197                 if rd.instdict.get('wave'):
    1198                     wl = rd.instdict.get('wave')
    1199                     wave1 = wl[0]
    1200                     if len(wl) > 1: wave2 = wl[1]
    1201                 s = Iparm['INS  1 ICONS']
    1202                 if not wave1:
    1203                     wave1 = G2IO.sfloat(s[:10])
    1204                     wave2 = G2IO.sfloat(s[10:20])
    1205                 v = (wave1,wave2,
    1206                      G2IO.sfloat(s[20:30])/100.,G2IO.sfloat(s[55:65]),G2IO.sfloat(s[40:50])) #get lam1, lam2, zero, pola & ratio
    1207                 if not v[1]:
    1208                     names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
    1209                     v = (v[0],v[2],v[4])
    1210                     codes = [0,0,0,0]
    1211                     rd.Sample.update({'Type':'Debye-Scherrer','Absorption':[0.,False],'DisplaceX':[0.,False],'DisplaceY':[0.,False]})
    1212                 else:
    1213                     names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
    1214                     codes = [0,0,0,0,0,0]
    1215                     rd.Sample.update({'Type':'Bragg-Brentano','Shift':[0.,False],'Transparency':[0.,False],
    1216                         'SurfRoughA':[0.,False],'SurfRoughB':[0.,False]})
    1217                 data.extend(v)
    1218                 if 'INS  1PRCF  ' in Iparm:
    1219                     v1 = Iparm['INS  1PRCF  '].split()                                                 
    1220                     v = Iparm['INS  1PRCF 1'].split()
    1221                     data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
    1222                     azm = float(Iparm.get('INS  1DETAZM','0.0'))
    1223                     v = Iparm['INS  1PRCF 2'].split()
    1224                     if v1[0] == 3:
    1225                         data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)])  #get LX, LY, S+H/L & azimuth
    1226                     else:
    1227                         data.extend([0.0,0.0,0.002,azm])                                      #OK defaults if fxn #3 not 1st in iprm file                   
    1228                 else:
    1229                     v1 = Iparm['INS  1PRCF1 '].split()                                                 
    1230                     v = Iparm['INS  1PRCF11'].split()
    1231                     data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
    1232                     azm = float(Iparm.get('INS  1DETAZM','0.0'))
    1233                     v = Iparm['INS  1PRCF12'].split()
    1234                     if v1[0] == 3:
    1235                         data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)])  #get LX, LY, S+H/L & azimuth
    1236                     else:
    1237                         data.extend([0.0,0.0,0.002,azm])                                      #OK defaults if fxn #3 not 1st in iprm file
    1238                 codes.extend([0,0,0,0,0,0,0])
    1239                 Iparm1 = G2IO.makeInstDict(names,data,codes)
    1240                 Iparm1['Source'] = [Irads[irad],Irads[irad]]
    1241                 Iparm1['Bank'] = [Bank,Bank,0]
    1242                 return [Iparm1,{}]
    1243             elif 'T' in DataType:
    1244                 names = ['Type','fltPath','2-theta','difC','difA', 'difB','Zero','alpha','beta-0','beta-1',
    1245                     'beta-q','sig-0','sig-1','sig-2','sig-q', 'X','Y','Azimuth',]
    1246                 codes = [0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,]
    1247                 azm = 0.
    1248                 if 'INS  1DETAZM' in Iparm:
    1249                     azm = float(Iparm['INS  1DETAZM'])
    1250                 rd.Sample['Azimuth'] = azm
    1251                 fltPath0 = 20.                      #arbitrary
    1252                 if 'INS   FPATH1' in Iparm:                   
    1253                     s = Iparm['INS   FPATH1'].split()
    1254                     fltPath0 = G2IO.sfloat(s[0])
    1255                 if 'INS  1BNKPAR' not in Iparm:     #bank missing from Iparm file
    1256                     return []
    1257                 s = Iparm['INS  1BNKPAR'].split()
    1258                 fltPath1 = G2IO.sfloat(s[0])
    1259                 data.extend([fltPath0+fltPath1,])               #Flight path source-sample-detector
    1260                 data.extend([G2IO.sfloat(s[1]),])               #2-theta for bank
    1261                 s = Iparm['INS  1 ICONS'].split()
    1262                 data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,G2IO.sfloat(s[2])])    #difC,difA,difB,Zero
    1263                 if 'INS  1PRCF  ' in Iparm:
    1264                     s = Iparm['INS  1PRCF  '].split()
    1265                     pfType = int(s[0])
    1266                     s = Iparm['INS  1PRCF 1'].split()
    1267                     if abs(pfType) == 1:
    1268                         data.extend([G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),G2IO.sfloat(s[3])]) #alpha, beta-0, beta-1
    1269                         s = Iparm['INS  1PRCF 2'].split()
    1270                         data.extend([0.0,0.0,G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y
    1271                     elif abs(pfType) in [3,4,5]:
    1272                         data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),G2IO.sfloat(s[2])]) #alpha, beta-0, beta-1
    1273                         if abs(pfType) == 4:
    1274                             data.extend([0.0,0.0,G2IO.sfloat(s[3]),0.0,0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y
    1275                         else:
    1276                             s = Iparm['INS  1PRCF 2'].split()
    1277                             data.extend([0.0,0.0,G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y                       
    1278                     elif abs(pfType) == 2:
    1279                         data.extend([G2IO.sfloat(s[1]),0.0,1./G2IO.sfloat(s[3])]) #alpha, beta-0, beta-1
    1280                         data.extend([0.0,0.0,G2IO.sfloat(s[1]),0.0,0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y                           
    1281                 else:
    1282                     s = Iparm['INS  1PRCF1 '].split()
    1283                     pfType = int(s[0])
    1284                     s = Iparm['INS  1PRCF11'].split()
    1285                     if abs(pfType) == 1:
    1286                         data.extend([G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),G2IO.sfloat(s[3])]) #alpha, beta-0, beta-1
    1287                         s = Iparm['INS  1PRCF12'].split()
    1288                         data.extend([0.0,0.0,G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y
    1289                     elif abs(pfType) in [3,4,5]:
    1290                         data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),G2IO.sfloat(s[2])]) #alpha, beta-0, beta-1
    1291                         if abs(pfType) == 4:
    1292                             data.extend([0.0,0.0,G2IO.sfloat(s[3]),0.0,0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y
    1293                         else:
    1294                             s = Iparm['INS  1PRCF12'].split()
    1295                             data.extend([0.0,0.0,G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,0.0,0.0,azm])    #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y                       
    1296                 Inst1 = G2IO.makeInstDict(names,data,codes)
    1297                 Inst1['Bank'] = [Bank,Bank,0]
    1298                 Inst2 = {}
    1299                 if pfType < 0:
    1300                     Ipab = 'INS  1PAB'+str(-pfType)
    1301                     Npab = int(Iparm[Ipab+'  '].strip())
    1302                     Inst2['Pdabc'] = []
    1303                     for i in range(Npab):
    1304                         k = Ipab+str(i+1).rjust(2)
    1305                         s = Iparm[k].split()
    1306                         Inst2['Pdabc'].append([float(t) for t in s])
    1307                     Inst2['Pdabc'] = np.array(Inst2['Pdabc'])
    1308                     Inst2['Pdabc'].T[3] += Inst2['Pdabc'].T[0]*Inst1['difC'][0] #turn 3rd col into TOF
    1309                 if 'INS  1I ITYP' in Iparm:
    1310                     s = Iparm['INS  1I ITYP'].split()
    1311                     Ityp = int(s[0])
    1312                     Tminmax = [float(s[1])*1000.,float(s[2])*1000.]
    1313                     Itypes = ['Exponential','Maxwell/Exponential','','Maxwell/Chebyschev','']
    1314                     if Ityp in [1,2,4]:
    1315                         Inst2['Itype'] = Itypes[Ityp-1]
    1316                         Inst2['Tminmax'] = Tminmax
    1317                         Icoeff = []
    1318                         Iesd = []
    1319                         Icovar = []                   
    1320                         for i in range(3):
    1321                             s = Iparm['INS  1ICOFF'+str(i+1)].split()
    1322                             Icoeff += [float(S) for S in s]
    1323                             s = Iparm['INS  1IECOF'+str(i+1)].split()
    1324                             Iesd += [float(S) for S in s]
    1325                         NT = 10
    1326                         for i in range(8):
    1327                             s = Iparm['INS  1IECOR'+str(i+1)]
    1328                             if i == 7:
    1329                                 NT = 8
    1330                             Icovar += [float(s[6*j:6*j+6]) for j in range(NT)]
    1331                         Inst2['Icoeff'] = Icoeff
    1332                         Inst2['Iesd'] = Iesd
    1333                         Inst2['Icovar'] = Icovar
    1334                 return [Inst1,Inst2]
    1335                
    1336         def GetDefaultParms(self,rd):
    1337             '''Solicits from user a default set of parameters & returns Inst parm dict
    1338             param: self: refers to the GSASII main class
    1339             param: rd: importer data structure
    1340             returns: dict: Instrument parameter dictionary
    1341             '''       
    1342             sind = lambda x: math.sin(x*math.pi/180.)
    1343             tand = lambda x: math.tan(x*math.pi/180.)
    1344             import defaultIparms as dI
    1345             while True: # loop until we get a choice
    1346                 choices = []
    1347                 head = 'Select from default instrument parameters for '+rd.idstring
    1348    
    1349                 for l in dI.defaultIparm_lbl:
    1350                     choices.append('Defaults for '+l)
    1351                 res = G2IO.BlockSelector(choices,ParentFrame=self,title=head,
    1352                     header='Select default inst parms',useCancel=True)
    1353                 if res is None: return None
    1354                 rd.instfile = ''
    1355                 if 'lab data' in choices[res]:
    1356                     rd.Sample.update({'Type':'Bragg-Brentano','Shift':[0.,False],'Transparency':[0.,False],
    1357                         'SurfRoughA':[0.,False],'SurfRoughB':[0.,False]})
    1358                 else:
    1359                     rd.Sample.update({'Type':'Debye-Scherrer','Absorption':[0.,False],'DisplaceX':[0.,False],
    1360                         'DisplaceY':[0.,False]})
    1361                 if 'Generic' in choices[res]:
    1362                     dlg = G2G.MultiFloatDialog(self,title='Generic TOF detector bank',
    1363                         prompts=['Total FP','2-theta',],values=[25.0,150.,],
    1364                             limits=[[6.,200.],[5.,175.],],formats=['%6.2f','%6.1f',])
    1365                     if dlg.ShowModal() == wx.ID_OK: #strictly empirical approx.
    1366                         FP,tth = dlg.GetValues()
    1367                         difC = 505.632*FP*sind(tth/2.)
    1368                         sig1 = 50.+2.5e-6*(difC/tand(tth/2.))**2
    1369                         bet1 = .00226+7.76e+11/difC**4
    1370                         rd.instmsg = 'default: '+dI.defaultIparm_lbl[res]
    1371                         Inst = self.ReadPowderInstprm(dI.defaultIparms[res],bank,numbanks,rd)
    1372                         Inst[0]['difC'] = [difC,difC,0]
    1373                         Inst[0]['sig-1'] = [sig1,sig1,0]
    1374                         Inst[0]['beta-1'] = [bet1,bet1,0]
    1375                         return Inst    #this is [Inst1,Inst2] a pair of dicts
    1376                     dlg.Destroy()
    1377                 else:
    1378                     rd.instmsg = 'default: '+dI.defaultIparm_lbl[res]
    1379                     return self.ReadPowderInstprm(dI.defaultIparms[res],bank,numbanks,rd)    #this is [Inst1,Inst2] a pair of dicts
    1380 
    1381         # stuff we might need from the reader
    1382         filename = rd.powderentry[0]
    1383         bank = rd.powderentry[2]
    1384         numbanks = rd.numbanks
    1385         #1st priority: is there an instrument parameter file matching the current file
    1386         # with extension .instprm, .prm, .inst, or .ins? If so read it
    1387         basename = os.path.splitext(filename)[0]
    1388         for ext in '.prm','.inst','.ins','.instprm':
    1389             if self.zipfile:
    1390                 instfile = G2IO.ExtractFileFromZip(self.zipfile,
    1391                     selection=os.path.split(basename + ext)[1],parent=self)
    1392                 if instfile == None:
    1393                     continue
    1394             else:
    1395                 instfile = basename + ext
    1396             if not os.path.exists(instfile):
    1397                 continue
    1398             if 'instprm' in instfile:
    1399                 Lines = self.OpenPowderInstprm(instfile)
    1400                 instParmList = self.ReadPowderInstprm(Lines,bank,numbanks,rd)    #this is [Inst1,Inst2] a pair of dicts
    1401                 if 'list' in str(type(instParmList)):
    1402                     rd.instfile = instfile
    1403                     rd.instmsg = 'GSAS-II file '+instfile
    1404                     return instParmList
    1405                 else:
    1406                     #print 'debug: open/read failed',instfile
    1407                     pass # fail silently
    1408             else:
    1409                 Iparm = self.ReadPowderIparm(instfile,bank,numbanks,rd)
    1410                 if Iparm:
    1411                     #print 'debug: success'
    1412                     rd.instfile = instfile
    1413                     rd.instmsg = instfile + ' bank ' + str(rd.instbank)
    1414                     return SetPowderInstParms(Iparm,rd)
    1415                 else:
    1416                     #print 'debug: open/read failed',instfile
    1417                     pass # fail silently
    1418 
    1419         #2nd priority: is there an instrument parameter file defined for the current data set?
    1420         # or if this is a read on a set of set of files, use the last one again
    1421         #if rd.instparm as found in data file header or (lastdatafile == filename and lastIparmfile):
    1422         if rd.instparm or lastIparmfile:
    1423             if rd.instparm:
    1424                 instfile = os.path.join(os.path.split(filename)[0],rd.instparm)
    1425             else:
    1426                 # for multiple reads of one data file, reuse the inst parm file
    1427                 instfile = lastIparmfile
    1428 #            if self.zipfile:
    1429 #                instfile = G2IO.ExtractFileFromZip(self.zipfile,
    1430 #                    selection=os.path.split(instfile)[1],parent=self)
    1431             if instfile != None and os.path.exists(instfile):
    1432                 #print 'debug: try read',instfile
    1433                 if 'instprm' in instfile:   #GSAS-II file must have .instprm as extension
    1434                     Lines = self.OpenPowderInstprm(instfile)
    1435                     if Lines is not None:
    1436                         instParmList = self.ReadPowderInstprm(Lines,bank,numbanks,rd)   #this is [Inst1,Inst2] a pair of dicts
    1437                 else:   #old GSAS style iparm file - could be named anything!
    1438                     Iparm = self.ReadPowderIparm(instfile,bank,numbanks,rd)
    1439                     if Iparm:
    1440                         #print 'debug: success'
    1441                         rd.instfile = instfile
    1442                         rd.instmsg = instfile + ' bank ' + str(rd.instbank)
    1443                         instParmList = SetPowderInstParms(Iparm,rd)     #this is [Inst1,Inst2] a pair of dicts
    1444                 if 'list' in str(type(instParmList)):   #record stuff & return stuff
    1445                     rd.instfile = instfile
    1446                     rd.instmsg = 'GSAS-II file '+instfile
    1447                     return instParmList
    1448                 else:   #bad iparms - try default
    1449                     rd.instmsg = instParmList   #an error message
    1450                     return GetDefaultParms(self,rd)
    1451             else:
    1452                 self.ErrorDialog('Open Error',u'Error opening instrument parameter file '   \
    1453                     +'{} requested by file '.format(instfile,filename))
    1454         #Finally - ask user for Instrument parametrs file - seems it can't be in a zip file
    1455         while True: # loop until we get a file that works or we get a cancel
    1456             instfile = ''
    1457             pth = G2G.GetImportPath(self)
    1458             if not pth: pth = '.'
    1459             dlg = wx.FileDialog(self,
    1460                 'Choose inst. param file for "'+rd.idstring+'" (or Cancel for default)',
    1461                 pth, '',
    1462                 'GSAS iparm file (*.prm,*.inst,*.ins)|*.prm;*.inst;*.ins|'
    1463                 'GSAS-II iparm file (*.instprm)|*.instprm|'
    1464                 'All files (*.*)|*.*', wx.OPEN)
    1465             if os.path.exists(lastIparmfile):
    1466                 dlg.SetFilename(lastIparmfile)
    1467             if dlg.ShowModal() == wx.ID_OK:
    1468                 instfile = dlg.GetPath()
    1469             dlg.Destroy()
    1470             if not instfile:
    1471                 return GetDefaultParms(self,rd) #on Cancel/break
    1472             if 'instprm' in instfile:
    1473                 Lines = self.OpenPowderInstprm(instfile)
    1474                 if Lines is not None:
    1475                     instParmList = self.ReadPowderInstprm(Lines,bank,numbanks,rd)    #this is [Inst1,Inst2] a pair of dicts
    1476                 if 'list' in str(type(instParmList)):
    1477                     rd.instfile = instfile
    1478                     rd.instmsg = 'GSAS-II file '+instfile
    1479                     return instParmList
    1480                 else:
    1481                     rd.instmsg = instParmList   #an error message
    1482                     return GetDefaultParms(self,rd)
    1483             else:
    1484                 Iparm = self.ReadPowderIparm(instfile,bank,numbanks,rd)
    1485                 if Iparm:
    1486                     #print 'debug: success with',instfile
    1487                     rd.instfile = instfile
    1488                     rd.instmsg = instfile + ' bank ' + str(rd.instbank)
    1489                     return SetPowderInstParms(Iparm,rd)
    1490                 else:
    1491                     self.ErrorDialog('Read Error',
    1492                                      u'Error opening/reading file {}'.format(instfile))
    1493     def EnableRefineCommand(self):
    1494         haveData = False
    1495         # check for phases connected to histograms
    1496         sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    1497         if not sub: return
    1498         item, cookie = self.PatternTree.GetFirstChild(sub)
    1499         while item: # loop over phases
    1500             data = self.PatternTree.GetItemPyData(item)
    1501             item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    1502             UseList = data['Histograms']
    1503             if UseList: haveData = True
    1504         if haveData:
    1505             self.dataWindow.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
    1506             for item in self.Refine: item.Enable(True)
    1507         else:
    1508             self.dataWindow.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
    1509             for item in self.Refine: item.Enable(False)
    1510 
    1511        
    1512     def OnImportPowder(self,event):
    1513         '''Called in response to an Import/Powder Data/... menu item
    1514         to read a powder diffraction data set.
    1515         dict self.ImportMenuId is used to look up the specific
    1516         reader item associated with the menu item, which will be
    1517         None for the last menu item, which is the "guess" option
    1518         where all appropriate formats will be tried.
    1519 
    1520         Also reads an instrument parameter file for each dataset.
    1521         '''
    1522         # get a list of existing histograms
    1523         PWDRlist = []
    1524         if self.PatternTree.GetCount():
    1525             item, cookie = self.PatternTree.GetFirstChild(self.root)
    1526             while item:
    1527                 name = self.PatternTree.GetItemText(item)
    1528                 if name.startswith('PWDR ') and name not in PWDRlist:
    1529                     PWDRlist.append(name)
    1530                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    1531         # look up which format was requested
    1532         reqrdr = self.ImportMenuId.get(event.GetId()) 
    1533         rdlist = self.OnImportGeneric(
    1534             reqrdr,self.ImportPowderReaderlist,'Powder Data',multiple=True)
    1535         if len(rdlist) == 0: return
    1536         self.CheckNotebook()
    1537         Iparm = None
    1538         lastIparmfile = ''
    1539         lastdatafile = ''
    1540         newHistList = []
    1541 #        lastVals = []
    1542         self.EnablePlot = False
    1543         for rd in rdlist:
    1544             if 'Instrument Parameters' in rd.pwdparms:
    1545                 Iparm1,Iparm2 = rd.pwdparms['Instrument Parameters']
    1546             else:
    1547                 # get instrument parameters for each dataset, unless already set
    1548 #                if lastIparmfile:  # is this histogram like previous?
    1549 #                    if lastVals != (rd.powderdata[0].min(),rd.powderdata[0].max(),len(rd.powderdata[0])):
    1550 #                        lastIparmfile = ''
    1551                 Iparms = self.GetPowderIparm(rd, Iparm, lastIparmfile, lastdatafile)
    1552                 if not Iparms:  #may have bailed out
    1553                     Id = 0
    1554                     continue
    1555                 Iparm1,Iparm2 = Iparms
    1556                 if rd.repeat_instparm:
    1557                     lastIparmfile = rd.instfile
    1558 #                    lastVals = (rd.powderdata[0].min(),rd.powderdata[0].max(),len(rd.powderdata[0]))
    1559                 # override any keys in read instrument parameters with ones set in import
    1560                 for key in Iparm1: 
    1561                     if key in rd.instdict:
    1562                         Iparm1[key] = rd.instdict[key]
    1563             lastdatafile = rd.powderentry[0]
    1564             HistName = 'PWDR '+G2obj.StripUnicode(rd.idstring,'_')
    1565             # make new histogram names unique
    1566             if HistName in PWDRlist:
    1567                 dlg = wx.MessageDialog(self,'Skip %s?'%(HistName),'Duplicate data name',wx.YES_NO)
    1568                 try:
    1569                     if dlg.ShowModal() == wx.ID_YES:
    1570                         Id = 0
    1571                         continue
    1572                 finally:
    1573                     dlg.Destroy()
    1574             HistName = G2obj.MakeUniqueLabel(HistName,PWDRlist)
    1575             print('Read powder data '+HistName+
    1576                 ' from file '+rd.readfilename +
    1577                 ' (format: '+ rd.formatName +
    1578                 '). Inst parameters from '+rd.instmsg)
    1579             # data are read, now store them in the tree
    1580             Id = self.PatternTree.AppendItem(parent=self.root,text=HistName)
    1581             if 'T' in Iparm1['Type'][0]:
    1582                 if not rd.clockWd and rd.GSAS:
    1583                     rd.powderdata[0] *= 100.        #put back the CW centideg correction
    1584                 cw = np.diff(rd.powderdata[0])
    1585                 rd.powderdata[0] = rd.powderdata[0][:-1]+cw/2.
    1586                 if rd.GSAS:     #NB: old GSAS wanted intensities*CW even if normalized!
    1587                     npts = min(len(rd.powderdata[0]),len(rd.powderdata[1]),len(cw))
    1588                     rd.powderdata[1] = rd.powderdata[1][:npts]/cw[:npts]
    1589                     rd.powderdata[2] = rd.powderdata[2][:npts]*cw[:npts]**2  #1/var=w at this point
    1590                 else:       #NB: from topas/fullprof type files
    1591                     rd.powderdata[1] = rd.powderdata[1][:-1]
    1592                     rd.powderdata[2] = rd.powderdata[2][:-1]
    1593                 if 'Itype' in Iparm2:
    1594                     Ibeg = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][0])
    1595                     Ifin = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][1])
    1596                     rd.powderdata[0] = rd.powderdata[0][Ibeg:Ifin]
    1597                     YI,WYI = G2pwd.calcIncident(Iparm2,rd.powderdata[0])
    1598                     rd.powderdata[1] = rd.powderdata[1][Ibeg:Ifin]/YI
    1599                     var = 1./rd.powderdata[2][Ibeg:Ifin]
    1600                     var += WYI*rd.powderdata[1]**2
    1601                     var /= YI**2
    1602                     rd.powderdata[2] = 1./var
    1603                 rd.powderdata[3] = np.zeros_like(rd.powderdata[0])
    1604                 rd.powderdata[4] = np.zeros_like(rd.powderdata[0])
    1605                 rd.powderdata[5] = np.zeros_like(rd.powderdata[0])
    1606             Ymin = np.min(rd.powderdata[1])                 
    1607             Ymax = np.max(rd.powderdata[1])                 
    1608             valuesdict = {
    1609                 'wtFactor':1.0,
    1610                 'Dummy':False,
    1611                 'ranId':ran.randint(0,sys.maxint),
    1612                 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax,
    1613                 'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax]
    1614                 }
    1615             # apply user-supplied corrections to powder data
    1616             if 'CorrectionCode' in Iparm1:
    1617                 print('Applying corrections from instprm file')
    1618                 corr = Iparm1['CorrectionCode'][0]
    1619                 try:
    1620                     exec(corr)
    1621                     print('done')
    1622                 except Exception as err:
    1623                     print(u'error: {}'.format(err))
    1624                     print('with commands -------------------')
    1625                     print(corr)
    1626                     print('---------------------------------')
    1627                 finally:
    1628                     del Iparm1['CorrectionCode']
    1629             rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday
    1630             self.PatternTree.SetItemPyData(Id,[valuesdict,rd.powderdata])
    1631             self.PatternTree.SetItemPyData(
    1632                 self.PatternTree.AppendItem(Id,text='Comments'),
    1633                 rd.comments)
    1634             Tmin = min(rd.powderdata[0])
    1635             Tmax = max(rd.powderdata[0])
    1636             Tmin1 = Tmin
    1637             if 'NT' in Iparm1['Type'][0] and G2lat.Pos2dsp(Iparm1,Tmin) < 0.4:               
    1638                 Tmin1 = G2lat.Dsp2pos(Iparm1,0.4)
    1639             self.PatternTree.SetItemPyData(
    1640                 self.PatternTree.AppendItem(Id,text='Limits'),
    1641                 rd.pwdparms.get('Limits',[(Tmin,Tmax),[Tmin1,Tmax]])
    1642                 )
    1643             self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
    1644             self.PatternTree.SetItemPyData(
    1645                 self.PatternTree.AppendItem(Id,text='Background'),
    1646                 rd.pwdparms.get('Background',
    1647                     [['chebyschev',True,3,1.0,0.0,0.0],{'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
    1648                     )
    1649             self.PatternTree.SetItemPyData(
    1650                 self.PatternTree.AppendItem(Id,text='Instrument Parameters'),
    1651                 [Iparm1,Iparm2])
    1652             self.PatternTree.SetItemPyData(
    1653                 self.PatternTree.AppendItem(Id,text='Sample Parameters'),
    1654                 rd.Sample)
    1655             self.PatternTree.SetItemPyData(
    1656                 self.PatternTree.AppendItem(Id,text='Peak List')
    1657                 ,{'peaks':[],'sigDict':{}})
    1658             self.PatternTree.SetItemPyData(
    1659                 self.PatternTree.AppendItem(Id,text='Index Peak List'),
    1660                 [[],[]])
    1661             self.PatternTree.SetItemPyData(
    1662                 self.PatternTree.AppendItem(Id,text='Unit Cells List'),
    1663                 [])
    1664             self.PatternTree.SetItemPyData(
    1665                 self.PatternTree.AppendItem(Id,text='Reflection Lists'),
    1666                 {})
    1667             # if any Control values have been set, move them into tree
    1668             Controls = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.root, 'Controls'))
    1669             Controls.update(rd.Controls)
    1670             newHistList.append(HistName)
    1671             rd.repeat_instparm = False  #clear the iparm reuse flag
    1672         else:
    1673             self.EnablePlot = True
    1674             if Id:
    1675                 self.PatternTree.Expand(Id)
    1676                 self.PatternTree.SelectItem(Id)
    1677 
    1678         if not newHistList: return # somehow, no new histograms
    1679         # make a list of phase names
    1680         phaseRIdList,usedHistograms = self.GetPhaseInfofromTree()
    1681         phaseNameList = usedHistograms.keys() # phase names in use
    1682         if not phaseNameList: return # no phases yet, nothing to do
    1683         header = 'Select phase(s) to link\nto the newly-read data:'
    1684         for Name in newHistList:
    1685             header += '\n  '+str(Name)
    1686 
    1687         result = G2G.ItemSelector(phaseNameList,self,header,header='Add to phase(s)',multiple=True)
    1688         if not result: return
    1689         # connect new phases to histograms
    1690         sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    1691         if not sub:
    1692             raise Exception('ERROR -- why are there no phases here?')
    1693         item, cookie = self.PatternTree.GetFirstChild(sub)
    1694         iph = -1
    1695         while item: # loop over (new) phases
    1696             iph += 1
    1697             data = self.PatternTree.GetItemPyData(item)
    1698             item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    1699             if iph not in result: continue
    1700             generalData = data['General']
    1701             SGData = generalData['SGData']
    1702             UseList = data['Histograms']
    1703             NShkl = len(G2spc.MustrainNames(SGData))
    1704             NDij = len(G2spc.HStrainNames(SGData))
    1705             for histoName in newHistList:
    1706                 UseList[histoName] = SetDefaultDData('PWDR',histoName,NShkl=NShkl,NDij=NDij)
    1707                 Id = G2gd.GetPatternTreeItemId(self,self.root,histoName)
    1708                 refList = self.PatternTree.GetItemPyData(
    1709                     G2gd.GetPatternTreeItemId(self,Id,'Reflection Lists'))
    1710                 refList[generalData['Name']] = []
    1711         self.EnableRefineCommand()
    1712         return # success
    1713 
    1714     def OnDummyPowder(self,event):
    1715         '''Called in response to Import/Powder Data/Simulate menu item
    1716         to create a Dummy powder diffraction data set.
    1717 
    1718         Reads an instrument parameter file and then gets input from the user
    1719         '''
    1720         # get a list of existing histograms
    1721         PWDRlist = []
    1722         if self.PatternTree.GetCount():
    1723             item, cookie = self.PatternTree.GetFirstChild(self.root)
    1724             while item:
    1725                 name = self.PatternTree.GetItemText(item)
    1726                 if name.startswith('PWDR ') and name not in PWDRlist:
    1727                     PWDRlist.append(name)
    1728                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    1729         # Initialize a base class reader
    1730         rd = G2obj.ImportPowderData(
    1731             extensionlist=tuple(),
    1732             strictExtension=False,
    1733             formatName = 'Simulate dataset',
    1734             longFormatName = 'Compute a simulated pattern')
    1735         rd.powderentry[0] = '' # no filename
    1736         # #self.powderentry[1] = pos # bank offset (N/A here)
    1737         rd.powderentry[2] = 1 # only one bank
    1738         rd.comments.append('This is a dummy dataset for powder pattern simulation')
    1739         self.CheckNotebook()
    1740         Iparm = None
    1741         lastdatafile = ''
    1742         self.zipfile = None
    1743         # get instrument parameters for it
    1744         Iparm1,Iparm2 = self.GetPowderIparm(rd, Iparm, '', lastdatafile)
    1745         if 'T' in Iparm1['Type'][0]:
    1746             print('TOF simulation not supported yet')
    1747             return False
    1748         else:
    1749             # need to get name, 2theta start, end, step
    1750             rd.idstring = ' CW'
    1751             if 'X' in Iparm1['Type'][0]:
    1752                 rd.idstring = 'CW x-ray simulation'
    1753             else:
    1754                 rd.idstring = 'CW neutron simulation'
    1755             # base initial range on wavelength
    1756             wave = Iparm1.get('Lam')
    1757             if wave:
    1758                 wave = wave[0]
    1759             else:
    1760                 wave = Iparm1.get('Lam1')
    1761                 if wave:
    1762                     wave = wave[0]
    1763         N = 0
    1764         while (N < 3): # insist on a dataset with a few points
    1765             names = ('dataset name', 'start angle', 'end angle', 'step size')
    1766             if not wave or wave < 1.0:
    1767                 inp = [rd.idstring, 10.,40.,0.005] # see names for what's what
    1768             else:
    1769                 inp = [rd.idstring, 10.,80.,0.01] # see names for what's what
    1770             dlg = G2G.ScrolledMultiEditor(
    1771                 self,[inp] * len(inp),range(len(inp)),names,
    1772                 header='Enter simulation name and range',
    1773                 minvals=(None,0.001,0.001,0.0001),
    1774                 maxvals=(None,180.,180.,.1),
    1775                 sizevals=((225,-1),)
    1776                 )
    1777             dlg.CenterOnParent()
    1778             if dlg.ShowModal() == wx.ID_OK:
    1779                 if inp[1] > inp[2]:
    1780                     end,start,step = inp[1:]
    1781                 else:               
    1782                     start,end,step = inp[1:]
    1783                 step = abs(step)
    1784             else:
    1785                 return False
    1786             N = int((end-start)/step)+1
    1787             x = np.linspace(start,end,N,True)
    1788             N = len(x)
    1789         rd.powderdata = [
    1790             np.array(x), # x-axis values
    1791             np.zeros_like(x), # powder pattern intensities
    1792             np.ones_like(x), # 1/sig(intensity)^2 values (weights)
    1793             np.zeros_like(x), # calc. intensities (zero)
    1794             np.zeros_like(x), # calc. background (zero)
    1795             np.zeros_like(x), # obs-calc profiles
    1796             ]
    1797         Tmin = rd.powderdata[0][0]
    1798         Tmax = rd.powderdata[0][-1]
    1799         # data are read, now store them in the tree
    1800         HistName = inp[0]
    1801         HistName = 'PWDR '+HistName
    1802         HistName = G2obj.MakeUniqueLabel(HistName,PWDRlist)  # make new histogram names unique
    1803         Id = self.PatternTree.AppendItem(parent=self.root,text=HistName)
    1804         Ymin = np.min(rd.powderdata[1])
    1805         Ymax = np.max(rd.powderdata[1])
    1806         valuesdict = {
    1807             'wtFactor':1.0,
    1808             'Dummy':True,
    1809             'ranId':ran.randint(0,sys.maxint),
    1810             'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax,
    1811             'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax]
    1812             }
    1813         self.PatternTree.SetItemPyData(Id,[valuesdict,rd.powderdata])
    1814         self.PatternTree.SetItemPyData(
    1815             self.PatternTree.AppendItem(Id,text='Comments'),
    1816             rd.comments)
    1817         self.PatternTree.SetItemPyData(
    1818             self.PatternTree.AppendItem(Id,text='Limits'),
    1819             [(Tmin,Tmax),[Tmin,Tmax]])
    1820         self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
    1821         self.PatternTree.SetItemPyData(
    1822             self.PatternTree.AppendItem(Id,text='Background'),
    1823             [['chebyschev',True,3,1.0,0.0,0.0],
    1824              {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
    1825         self.PatternTree.SetItemPyData(
    1826             self.PatternTree.AppendItem(Id,text='Instrument Parameters'),
    1827             [Iparm1,Iparm2])
    1828         self.PatternTree.SetItemPyData(
    1829             self.PatternTree.AppendItem(Id,text='Sample Parameters'),
    1830             rd.Sample)
    1831         self.PatternTree.SetItemPyData(
    1832             self.PatternTree.AppendItem(Id,text='Peak List')
    1833             ,{'peaks':[],'sigDict':{}})
    1834         self.PatternTree.SetItemPyData(
    1835             self.PatternTree.AppendItem(Id,text='Index Peak List'),
    1836             [[],[]])
    1837         self.PatternTree.SetItemPyData(
    1838             self.PatternTree.AppendItem(Id,text='Unit Cells List'),
    1839             [])
    1840         self.PatternTree.SetItemPyData(
    1841             self.PatternTree.AppendItem(Id,text='Reflection Lists'),
    1842             {})
    1843         self.PatternTree.Expand(Id)
    1844         self.PatternTree.SelectItem(Id)
    1845         print(u'Added simulation powder data {}'.format(HistName)+
    1846               ' with parameters from {}'.format(rd.instmsg))
    1847 
    1848         # make a list of phase names
    1849         phaseRIdList,usedHistograms = self.GetPhaseInfofromTree()
    1850         phaseNameList = usedHistograms.keys() # phase names in use
    1851         if not phaseNameList: return # no phases yet, nothing to do
    1852         header = 'Select phase(s) to add the new\npowder simulation (dummy) dataset to:'
    1853         result = G2G.ItemSelector(phaseNameList,self,header,header='Add to phase(s)',multiple=True)
    1854         if not result: return
    1855         # connect new phases to histograms
    1856         sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    1857         if not sub:
    1858             raise Exception('ERROR -- why are there no phases here?')
    1859         item, cookie = self.PatternTree.GetFirstChild(sub)
    1860         iph = -1
    1861         while item: # loop over (new) phases
    1862             iph += 1
    1863             data = self.PatternTree.GetItemPyData(item)
    1864             item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    1865             if iph not in result: continue
    1866             generalData = data['General']
    1867             SGData = generalData['SGData']
    1868             UseList = data['Histograms']
    1869             NShkl = len(G2spc.MustrainNames(SGData))
    1870             NDij = len(G2spc.HStrainNames(SGData))
    1871             UseList[HistName] = SetDefaultDData('PWDR',HistName,NShkl=NShkl,NDij=NDij)
    1872             Id = G2gd.GetPatternTreeItemId(self,self.root,HistName)
    1873             refList = self.PatternTree.GetItemPyData(
    1874                 G2gd.GetPatternTreeItemId(self,Id,'Reflection Lists'))
    1875             refList[generalData['Name']] = []
    1876         self.EnableRefineCommand()
    1877         return # success
    1878        
    1879     def OnPreferences(self,event):
    1880         'Edit the GSAS-II configuration variables'
    1881         dlg = G2G.SelectConfigSetting(self)
    1882         dlg.ShowModal() == wx.ID_OK
    1883         dlg.Destroy()
    1884 
    1885     def _Add_ImportMenu_smallangle(self,parent):
    1886         '''configure the Small Angle Data menus accord to the readers found in _init_Imports
    1887         '''
    1888         submenu = wx.Menu()
    1889         item = parent.AppendMenu(wx.ID_ANY, 'Small Angle Data',
    1890             submenu, help='Import small angle data')
    1891         for reader in self.ImportSmallAngleReaderlist:
    1892             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,
    1893                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    1894             self.ImportMenuId[item.GetId()] = reader
    1895             self.Bind(wx.EVT_MENU, self.OnImportSmallAngle, id=item.GetId())
    1896         # item = submenu.Append(wx.ID_ANY,
    1897         #     help='Import small angle data, use file to try to determine format',
    1898         #     kind=wx.ITEM_NORMAL,text='guess format from file')
    1899         # self.Bind(wx.EVT_MENU, self.OnImportSmallAngle, id=item.GetId())
    1900 
    1901     def OnImportSmallAngle(self,event):
    1902         '''Called in response to an Import/Small Angle Data/... menu item
    1903         to read a small angle diffraction data set.
    1904         dict self.ImportMenuId is used to look up the specific
    1905         reader item associated with the menu item, which will be
    1906         None for the last menu item, which is the "guess" option
    1907         where all appropriate formats will be tried.
    1908 
    1909         '''
    1910        
    1911         def GetSASDIparm(reader):
    1912             parm = reader.instdict
    1913             Iparm = {'Type':[parm['type'],parm['type'],0],'Lam':[parm['wave'],
    1914                 parm['wave'],0],'Azimuth':[0.,0.,0]}           
    1915             return Iparm,{}
    1916            
    1917         # get a list of existing histograms
    1918         SASDlist = []
    1919         if self.PatternTree.GetCount():
    1920             item, cookie = self.PatternTree.GetFirstChild(self.root)
    1921             while item:
    1922                 name = self.PatternTree.GetItemText(item)
    1923                 if name.startswith('SASD ') and name not in SASDlist:
    1924                     SASDlist.append(name)
    1925                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    1926         # look up which format was requested
    1927         reqrdr = self.ImportMenuId.get(event.GetId()) 
    1928         rdlist = self.OnImportGeneric(
    1929             reqrdr,self.ImportSmallAngleReaderlist,'Small Angle Data',multiple=True)
    1930         if len(rdlist) == 0: return
    1931         self.CheckNotebook()
    1932         newHistList = []
    1933         self.EnablePlot = False
    1934         for rd in rdlist:
    1935             HistName = rd.idstring
    1936             HistName = 'SASD '+HistName
    1937             # make new histogram names unique
    1938             HistName = G2obj.MakeUniqueLabel(HistName,SASDlist)
    1939             print 'Read small angle data '+HistName+ \
    1940                 ' from file '+self.lastimport
    1941             # data are read, now store them in the tree
    1942             Id = self.PatternTree.AppendItem(parent=self.root,text=HistName)
    1943             Iparm1,Iparm2 = GetSASDIparm(rd)
    1944 #            if 'T' in Iparm1['Type'][0]:
    1945 #                if not rd.clockWd and rd.GSAS:
    1946 #                    rd.powderdata[0] *= 100.        #put back the CW centideg correction
    1947 #                cw = np.diff(rd.powderdata[0])
    1948 #                rd.powderdata[0] = rd.powderdata[0][:-1]+cw/2.
    1949 #                rd.powderdata[1] = rd.powderdata[1][:-1]/cw
    1950 #                rd.powderdata[2] = rd.powderdata[2][:-1]*cw**2  #1/var=w at this point
    1951 #                if 'Itype' in Iparm2:
    1952 #                    Ibeg = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][0])
    1953 #                    Ifin = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][1])
    1954 #                    rd.powderdata[0] = rd.powderdata[0][Ibeg:Ifin]
    1955 #                    YI,WYI = G2pwd.calcIncident(Iparm2,rd.powderdata[0])
    1956 #                    rd.powderdata[1] = rd.powderdata[1][Ibeg:Ifin]/YI
    1957 #                    var = 1./rd.powderdata[2][Ibeg:Ifin]
    1958 #                    var += WYI*rd.powderdata[1]**2
    1959 #                    var /= YI**2
    1960 #                    rd.powderdata[2] = 1./var
    1961 #                rd.powderdata[3] = np.zeros_like(rd.powderdata[0])                                       
    1962 #                rd.powderdata[4] = np.zeros_like(rd.powderdata[0])                                       
    1963 #                rd.powderdata[5] = np.zeros_like(rd.powderdata[0])                                       
    1964             Tmin = min(rd.smallangledata[0])
    1965             Tmax = max(rd.smallangledata[0])
    1966             valuesdict = {
    1967                 'wtFactor':1.0,
    1968                 'Dummy':False,
    1969                 'ranId':ran.randint(0,sys.maxint),
    1970                 'Offset':[0.0,0.0],
    1971                 }
    1972             rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday
    1973             self.PatternTree.SetItemPyData(Id,[valuesdict,rd.smallangledata])
    1974             self.PatternTree.SetItemPyData(
    1975                 self.PatternTree.AppendItem(Id,text='Comments'),
    1976                 rd.comments)
    1977             self.PatternTree.SetItemPyData(
    1978                 self.PatternTree.AppendItem(Id,text='Limits'),
    1979                 [(Tmin,Tmax),[Tmin,Tmax]])
    1980             self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
    1981             self.PatternTree.SetItemPyData(
    1982                 self.PatternTree.AppendItem(Id,text='Instrument Parameters'),
    1983                 [Iparm1,Iparm2])
    1984             self.PatternTree.SetItemPyData(
    1985                 self.PatternTree.AppendItem(Id,text='Substances'),G2pdG.SetDefaultSubstances())
    1986             self.PatternTree.SetItemPyData(
    1987                 self.PatternTree.AppendItem(Id,text='Sample Parameters'),
    1988                 rd.Sample)
    1989             self.PatternTree.SetItemPyData(
    1990                 self.PatternTree.AppendItem(Id,text='Models'),G2pdG.SetDefaultSASDModel())
    1991             newHistList.append(HistName)
    1992         else:
    1993             self.EnablePlot = True
    1994             self.PatternTree.Expand(Id)
    1995             self.PatternTree.SelectItem(Id)
    1996            
    1997         if not newHistList: return # somehow, no new histograms
    1998         return # success
    1999        
    2000     def _Add_ImportMenu_reflectometry(self,parent):
    2001         '''configure the reflectometry Data menus accord to the readers found in _init_Imports
    2002         '''
    2003         submenu = wx.Menu()
    2004         item = parent.AppendMenu(wx.ID_ANY, 'Reflectometry Data',
    2005             submenu, help='Import reflectometry data')
    2006         for reader in self.ImportReflectometryReaderlist:
    2007             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,
    2008                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    2009             self.ImportMenuId[item.GetId()] = reader
    2010             self.Bind(wx.EVT_MENU, self.OnImportReflectometry, id=item.GetId())
    2011         # item = submenu.Append(wx.ID_ANY,
    2012         #     help='Import reflectometry data, use file to try to determine format',
    2013         #     kind=wx.ITEM_NORMAL,text='guess format from file')
    2014         # self.Bind(wx.EVT_MENU, self.OnImportReflectometry, id=item.GetId())
    2015        
    2016     def OnImportReflectometry(self,event):
    2017         '''Called in response to an Import/Reflectometry Data/... menu item
    2018         to read a reflectometry data set.
    2019         dict self.ImportMenuId is used to look up the specific
    2020         reader item associated with the menu item, which will be
    2021         None for the last menu item, which is the "guess" option
    2022         where all appropriate formats will be tried.
    2023 
    2024         '''
    2025        
    2026         def GetREFDIparm(reader):
    2027             parm = reader.instdict
    2028             Iparm = {'Type':[parm['type'],parm['type'],0],'Lam':[parm['wave'],
    2029                 parm['wave'],0],'Azimuth':[0.,0.,0]}           
    2030             return Iparm,{}
    2031            
    2032         # get a list of existing histograms
    2033         REFDlist = []
    2034         if self.PatternTree.GetCount():
    2035             item, cookie = self.PatternTree.GetFirstChild(self.root)
    2036             while item:
    2037                 name = self.PatternTree.GetItemText(item)
    2038                 if name.startswith('REFD ') and name not in REFDlist:
    2039                     REFDlist.append(name)
    2040                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    2041         # look up which format was requested
    2042         reqrdr = self.ImportMenuId.get(event.GetId()) 
    2043         rdlist = self.OnImportGeneric(
    2044             reqrdr,self.ImportReflectometryReaderlist,'Reflectometry Data',multiple=True)
    2045         if len(rdlist) == 0: return
    2046         self.CheckNotebook()
    2047         newHistList = []
    2048         self.EnablePlot = False
    2049         for rd in rdlist:
    2050             HistName = rd.idstring
    2051             HistName = 'REFD '+HistName
    2052             # make new histogram names unique
    2053             HistName = G2obj.MakeUniqueLabel(HistName,REFDlist)
    2054             print 'Read reflectometry data '+HistName+ \
    2055                 ' from file '+self.lastimport
    2056             # data are read, now store them in the tree
    2057             Id = self.PatternTree.AppendItem(parent=self.root,text=HistName)
    2058             Iparm1,Iparm2 = GetREFDIparm(rd)
    2059 #            if 'T' in Iparm1['Type'][0]:
    2060 #                if not rd.clockWd and rd.GSAS:
    2061 #                    rd.powderdata[0] *= 100.        #put back the CW centideg correction
    2062 #                cw = np.diff(rd.powderdata[0])
    2063 #                rd.powderdata[0] = rd.powderdata[0][:-1]+cw/2.
    2064 #                rd.powderdata[1] = rd.powderdata[1][:-1]/cw
    2065 #                rd.powderdata[2] = rd.powderdata[2][:-1]*cw**2  #1/var=w at this point
    2066 #                if 'Itype' in Iparm2:
    2067 #                    Ibeg = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][0])
    2068 #                    Ifin = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][1])
    2069 #                    rd.powderdata[0] = rd.powderdata[0][Ibeg:Ifin]
    2070 #                    YI,WYI = G2pwd.calcIncident(Iparm2,rd.powderdata[0])
    2071 #                    rd.powderdata[1] = rd.powderdata[1][Ibeg:Ifin]/YI
    2072 #                    var = 1./rd.powderdata[2][Ibeg:Ifin]
    2073 #                    var += WYI*rd.powderdata[1]**2
    2074 #                    var /= YI**2
    2075 #                    rd.powderdata[2] = 1./var
    2076 #                rd.powderdata[3] = np.zeros_like(rd.powderdata[0])                                       
    2077 #                rd.powderdata[4] = np.zeros_like(rd.powderdata[0])                                       
    2078 #                rd.powderdata[5] = np.zeros_like(rd.powderdata[0])                                       
    2079             Tmin = min(rd.reflectometrydata[0])
    2080             Tmax = max(rd.reflectometrydata[0])
    2081             ifDQ = np.any(rd.reflectometrydata[5])
    2082             valuesdict = {
    2083                 'wtFactor':1.0,
    2084                 'Dummy':False,
    2085                 'ranId':ran.randint(0,sys.maxint),
    2086                 'Offset':[0.0,0.0],
    2087                 'ifDQ':ifDQ
    2088                 }
    2089             rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday
    2090             self.PatternTree.SetItemPyData(Id,[valuesdict,rd.reflectometrydata])
    2091             self.PatternTree.SetItemPyData(
    2092                 self.PatternTree.AppendItem(Id,text='Comments'),
    2093                 rd.comments)
    2094             self.PatternTree.SetItemPyData(
    2095                 self.PatternTree.AppendItem(Id,text='Limits'),
    2096                 [(Tmin,Tmax),[Tmin,Tmax]])
    2097             self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
    2098             self.PatternTree.SetItemPyData(
    2099                 self.PatternTree.AppendItem(Id,text='Instrument Parameters'),
    2100                 [Iparm1,Iparm2])
    2101             self.PatternTree.SetItemPyData(
    2102                 self.PatternTree.AppendItem(Id,text='Substances'),G2pdG.SetDefaultSubstances())
    2103             self.PatternTree.SetItemPyData(
    2104                 self.PatternTree.AppendItem(Id,text='Sample Parameters'),
    2105                 rd.Sample)
    2106             self.PatternTree.SetItemPyData(
    2107                 self.PatternTree.AppendItem(Id,text='Models'),G2pdG.SetDefaultREFDModel())
    2108             newHistList.append(HistName)
    2109         else:
    2110             self.EnablePlot = True
    2111             self.PatternTree.Expand(Id)
    2112             self.PatternTree.SelectItem(Id)
    2113            
    2114         if not newHistList: return # somehow, no new histograms
    2115         return # success
    2116 
    2117     def _Add_ImportMenu_PDF(self,parent):
    2118         '''configure the PDF Data menus accord to the readers found in _init_Imports
    2119         '''
    2120         submenu = wx.Menu()
    2121         item = parent.AppendMenu(wx.ID_ANY, 'PDF G(R) Data',
    2122             submenu, help='Import PDF G(R) data')
    2123         for reader in self.ImportPDFReaderlist:
    2124             item = submenu.Append(wx.ID_ANY,help=reader.longFormatName,
    2125                 kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file')
    2126             self.ImportMenuId[item.GetId()] = reader
    2127             self.Bind(wx.EVT_MENU, self.OnImportPDF, id=item.GetId())
    2128         # item = submenu.Append(wx.ID_ANY,
    2129         #     help='Import reflectometry data, use file to try to determine format',
    2130         #     kind=wx.ITEM_NORMAL,text='guess format from file')
    2131         # self.Bind(wx.EVT_MENU, self.OnImportReflectometry, id=item.GetId())
    2132        
    2133     def OnImportPDF(self,event):
    2134         '''Called in response to an Import/PDF G(R) Data/... menu item
    2135         to read a PDF G(R) data set.
    2136         dict self.ImportMenuId is used to look up the specific
    2137         reader item associated with the menu item, which will be
    2138         None for the last menu item, which is the "guess" option
    2139         where all appropriate formats will be tried.
    2140 
    2141         '''
    2142        
    2143         # get a list of existing histograms
    2144         PDFlist = []
    2145         if self.PatternTree.GetCount():
    2146             item, cookie = self.PatternTree.GetFirstChild(self.root)
    2147             while item:
    2148                 name = self.PatternTree.GetItemText(item)
    2149                 if name.startswith('PDF ') and name not in PDFlist:
    2150                     PDFlist.append(name)
    2151                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    2152         # look up which format was requested
    2153         reqrdr = self.ImportMenuId.get(event.GetId()) 
    2154         rdlist = self.OnImportGeneric(
    2155             reqrdr,self.ImportPDFReaderlist,'PDF G(R) Data',multiple=True)
    2156         if len(rdlist) == 0: return
    2157         self.CheckNotebook()
    2158         newHistList = []
    2159         self.EnablePlot = False
    2160         for rd in rdlist:
    2161             HistName = rd.idstring
    2162             HistName = 'PDF '+HistName
    2163             # make new histogram names unique
    2164             HistName = G2obj.MakeUniqueLabel(HistName,PDFlist)
    2165             print 'Read PDF G(R) data '+HistName+ \
    2166                 ' from file '+self.lastimport
    2167             # data are read, now store them in the tree
    2168             Id = self.PatternTree.AppendItem(self.root,text=HistName)
    2169             Ymin = np.min(rd.pdfdata[1])                 
    2170             Ymax = np.max(rd.pdfdata[1])                 
    2171             valuesdict = {
    2172                 'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxint),
    2173                 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,
    2174                 'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax]
    2175                 }
    2176             self.PatternTree.SetItemPyData(
    2177                 self.PatternTree.AppendItem(Id,text='PDF Controls'),
    2178                     {'G(R)':[valuesdict,rd.pdfdata,HistName],'diffGRname':'','diffMult':1.0})
    2179             self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='PDF Peaks'),
    2180                 {'Limits':[1.,5.],'Background':[2,[0.,-0.2*np.pi],False],'Peaks':[]})
    2181         else:
    2182             self.EnablePlot = True
    2183             self.PatternTree.Expand(Id)
    2184             self.PatternTree.SelectItem(Id)
    2185            
    2186         if not newHistList: return # somehow, no new histograms
    2187         return # success
    2188        
    2189 ###############################################################################
    2190 #Command logging
    2191 ###############################################################################
    2192 
    2193     def OnMacroRecordStatus(self,event,setvalue=None):
    2194         '''Called when the record macro menu item is used which toggles the
    2195         value. Alternately a value to be set can be provided. Note that this
    2196         routine is made more complex because on the Mac there are lots of menu
    2197         items (listed in self.MacroStatusList) and this loops over all of them.
    2198         '''
    2199         nextvalue = log.ShowLogStatus() != True
    2200         if setvalue is not None:
    2201             nextvalue = setvalue
    2202         if nextvalue:
    2203             log.LogOn()
    2204             set2 = True
    2205         else:
    2206             log.LogOff()
    2207             set2 = False
    2208         for menuitem in self.MacroStatusList:
    2209             menuitem.Check(set2)
    2210 
    2211     def _init_Macro(self):
    2212         '''Define the items in the macro menu.
    2213         '''
    2214         menu = self.MacroMenu
    2215         item = menu.Append(
    2216                 help='Start or stop recording of menu actions, etc.', id=wx.ID_ANY,
    2217                 kind=wx.ITEM_CHECK,text='Record actions')
    2218         self.MacroStatusList.append(item)
    2219         item.Check(log.ShowLogStatus())
    2220         self.Bind(wx.EVT_MENU, self.OnMacroRecordStatus, item)
    2221 
    2222         # this may only be of value for development work
    2223         item = menu.Append(
    2224             help='Show logged commands', id=wx.ID_ANY,
    2225             kind=wx.ITEM_NORMAL,text='Show log')
    2226         def OnShowLog(event):
    2227             print 70*'='
    2228             print 'List of logged actions'
    2229             for i,line in enumerate(log.G2logList):
    2230                 if line: print i,line
    2231             print 70*'='
    2232         self.Bind(wx.EVT_MENU, OnShowLog, item)
    2233 
    2234         item = menu.Append(
    2235             help='Clear logged commands', id=wx.ID_ANY,
    2236             kind=wx.ITEM_NORMAL,text='Clear log')
    2237         def OnClearLog(event): log.G2logList=[None]
    2238         self.Bind(wx.EVT_MENU, OnClearLog, item)
    2239        
    2240         item = menu.Append(
    2241             help='Save logged commands to file', id=wx.ID_ANY,
    2242             kind=wx.ITEM_NORMAL,text='Save log')
    2243         def OnSaveLog(event):
    2244             import cPickle
    2245             defnam = os.path.splitext(
    2246                 os.path.split(self.GSASprojectfile)[1]
    2247                 )[0]+'.gcmd'
    2248             dlg = wx.FileDialog(self,
    2249                 'Choose an file to save past actions', '.', defnam,
    2250                 'GSAS-II cmd output (*.gcmd)|*.gcmd',
    2251                 wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
    2252             dlg.CenterOnParent()
    2253             try:
    2254                 if dlg.ShowModal() == wx.ID_OK:
    2255                     filename = dlg.GetPath()
    2256                     # make sure extension is correct
    2257                     filename = os.path.splitext(filename)[0]+'.gcmd'
    2258                 else:
    2259                     filename = None
    2260             finally:
    2261                 dlg.Destroy()
    2262             if filename:
    2263                 fp = open(filename,'wb')
    2264                 fp.write(str(len(log.G2logList)-1)+'\n')
    2265                 for item in log.G2logList:
    2266                     if item: cPickle.dump(item,fp)
    2267                 fp.close()
    2268         self.Bind(wx.EVT_MENU, OnSaveLog, item)
    2269 
    2270         item = menu.Append(
    2271             help='Load logged commands from file', id=wx.ID_ANY,
    2272             kind=wx.ITEM_NORMAL,text='Load log')
    2273         def OnLoadLog(event):
    2274             # this appends. Perhaps we should ask to clear?
    2275             import cPickle
    2276             defnam = os.path.splitext(
    2277                 os.path.split(self.GSASprojectfile)[1]
    2278                 )[0]+'.gcmd'
    2279             dlg = wx.FileDialog(self,
    2280                 'Choose an file to read saved actions', '.', defnam,
    2281                 'GSAS-II cmd output (*.gcmd)|*.gcmd',
    2282                 wx.OPEN)
    2283             dlg.CenterOnParent()
    2284             try:
    2285                 if dlg.ShowModal() == wx.ID_OK:
    2286                     filename = dlg.GetPath()
    2287                     # make sure extension is correct
    2288                     filename = os.path.splitext(filename)[0]+'.gcmd'
    2289                 else:
    2290                     filename = None
    2291             finally:
    2292                 dlg.Destroy()
    2293             if filename and os.path.exists(filename):
    2294                 fp = open(filename,'rb')
    2295                 lines = fp.readline()
    2296                 for i in range(int(lines)):
    2297                     log.G2logList.append(cPickle.load(fp))
    2298                 fp.close()
    2299         self.Bind(wx.EVT_MENU, OnLoadLog, item)
    2300 
    2301         item = menu.Append(
    2302             help='Replay saved commands', id=wx.ID_ANY,
    2303             kind=wx.ITEM_NORMAL,text='Replay log')
    2304         self.Bind(wx.EVT_MENU, log.ReplayLog, item)
    2305 
    2306     def _init_Exports(self,menu):
    2307         '''Find exporter routines and add them into menus
    2308         '''
    2309         # set up the top-level menus
    2310         projectmenu = wx.Menu()
    2311         item = menu.AppendMenu(
    2312             wx.ID_ANY, 'Entire project as',
    2313             projectmenu, help='Export entire project')
    2314 
    2315         phasemenu = wx.Menu()
    2316         item = menu.AppendMenu(
    2317             wx.ID_ANY, 'Phase as',
    2318             phasemenu, help='Export phase or sometimes phases')
    2319 
    2320         powdermenu = wx.Menu()
    2321         item = menu.AppendMenu(
    2322             wx.ID_ANY, 'Powder data as',
    2323             powdermenu, help='Export powder diffraction histogram(s)')
    2324 
    2325         singlemenu = wx.Menu()
    2326         item = menu.AppendMenu(
    2327             wx.ID_ANY, 'Single crystal data as',
    2328             singlemenu, help='Export single crystal histogram(s)')
    2329 
    2330         imagemenu = wx.Menu()
    2331         item = menu.AppendMenu(
    2332             wx.ID_ANY, 'Image data as',
    2333             imagemenu, help='Export powder image(s) data')
    2334 
    2335         mapmenu = wx.Menu()
    2336         item = menu.AppendMenu(
    2337             wx.ID_ANY, 'Maps as',
    2338             mapmenu, help='Export density map(s)')
    2339 
    2340         # pdfmenu = wx.Menu()
    2341         # item = menu.AppendMenu(
    2342         #     wx.ID_ANY, 'PDFs as',
    2343         #     pdfmenu, help='Export pair distribution function(s)')
    2344 
    2345         # find all the exporter files
    2346         if not self.exporterlist: # this only needs to be done once
    2347             pathlist = sys.path
    2348             filelist = []
    2349             for path in pathlist:
    2350                 for filename in glob.iglob(os.path.join(path,"G2export*.py")):
    2351                     filelist.append(filename)   
    2352             filelist = sorted(list(set(filelist))) # remove duplicates
    2353             # go through the routines and import them, saving objects that
    2354             # have export routines (method Exporter)
    2355             for filename in filelist:
    2356                 path,rootname = os.path.split(filename)
    2357                 pkg = os.path.splitext(rootname)[0]
    2358 #                try:
    2359                 fp = None
    2360                 fp, fppath,desc = imp.find_module(pkg,[path,])
    2361                 pkg = imp.load_module(pkg,fp,fppath,desc)
    2362                 for clss in inspect.getmembers(pkg): # find classes defined in package
    2363                     if clss[0].startswith('_'): continue
    2364                     if inspect.isclass(clss[1]):
    2365                         # check if we have the required methods
    2366                         for m in 'Exporter','loadParmDict':
    2367                             if not hasattr(clss[1],m): break
    2368                             if not callable(getattr(clss[1],m)): break
    2369                         else:
    2370                             exporter = clss[1](self) # create an export instance
    2371                             self.exporterlist.append(exporter)
    2372 #                except AttributeError:
    2373 #                    print 'Import_'+errprefix+': Attribute Error'+str(filename)
    2374 #                    pass
    2375 #                except ImportError:
    2376 #                    print 'Import_'+errprefix+': Error importing file'+str(filename)
    2377 #                    pass
    2378                 if fp: fp.close()
    2379         # Add submenu item(s) for each Exporter by its self-declared type (can be more than one)
    2380         for obj in self.exporterlist:
    2381             #print 'exporter',obj
    2382             for typ in obj.exporttype:
    2383                 if typ == "project":
    2384                     submenu = projectmenu
    2385                 elif typ == "phase":
    2386                     submenu = phasemenu
    2387                 elif typ == "powder":
    2388                     submenu = powdermenu
    2389                 elif typ == "single":
    2390                     submenu = singlemenu
    2391                 elif typ == "image":
    2392                     submenu = imagemenu
    2393                 elif typ == "map":
    2394                     submenu = mapmenu
    2395                 # elif typ == "pdf":
    2396                 #     submenu = pdfmenu
    2397                 else:
    2398                     print("Error, unknown type in "+str(obj))
    2399                     break
    2400                 item = submenu.Append(
    2401                     wx.ID_ANY,
    2402                     help=obj.longFormatName,
    2403                     kind=wx.ITEM_NORMAL,
    2404                     text=obj.formatName)
    2405                 self.Bind(wx.EVT_MENU, obj.Exporter, id=item.GetId())
    2406                 self.ExportLookup[item.GetId()] = typ # lookup table for submenu item
    2407         item = imagemenu.Append(wx.ID_ANY,
    2408                         help='Export image controls and masks for multiple images',
    2409                         kind=wx.ITEM_NORMAL,
    2410                         text='Multiple image controls and masks')
    2411         self.Bind(wx.EVT_MENU, self.OnSaveMultipleImg, id=item.GetId())
    2412         #code to debug an Exporter. hard-code the routine below, to allow a reload before use
    2413         # def DebugExport(event):
    2414         #      print 'start reload'
    2415         #      reload(G2IO)
    2416         #      import G2export_pwdr as dev
    2417         #      reload(dev)
    2418         #      dev.ExportPowderFXYE(self).Exporter(event)
    2419         # item = menu.Append(
    2420         #     wx.ID_ANY,kind=wx.ITEM_NORMAL,
    2421         #     help="debug exporter",text="test Export FXYE")
    2422         # self.Bind(wx.EVT_MENU, DebugExport, id=item.GetId())
    2423         # # #self.ExportLookup[item.GetId()] = 'image'
    2424         # self.ExportLookup[item.GetId()] = 'powder'
    2425 
    2426 ###############################################################################
    2427 # Exporters
    2428 ###############################################################################
    2429                            
    2430     def _Add_ExportMenuItems(self,parent):
    2431         # item = parent.Append(
    2432         #     help='Select PWDR item to enable',id=wx.ID_ANY,
    2433         #     kind=wx.ITEM_NORMAL,
    2434         #     text='Export Powder Patterns...')
    2435         # self.ExportPattern.append(item)
    2436         # item.Enable(False)
    2437         # self.Bind(wx.EVT_MENU, self.OnExportPatterns, id=item.GetId())
    2438 
    2439         item = parent.Append(
    2440             help='',id=wx.ID_ANY,
    2441             kind=wx.ITEM_NORMAL,
    2442             text='Export All Peak Lists...')
    2443         self.ExportPeakList.append(item)
    2444         item.Enable(True)
    2445         self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=item.GetId())
    2446 
    2447         item = parent.Append(
    2448             help='',id=wx.ID_ANY,
    2449             kind=wx.ITEM_NORMAL,
    2450             text='Export HKLs...')
    2451         self.ExportHKL.append(item)
    2452         self.Bind(wx.EVT_MENU, self.OnExportHKL, id=item.GetId())
    2453 
    2454         item = parent.Append(
    2455             help='Select PDF item to enable',
    2456             id=wx.ID_ANY,
    2457             kind=wx.ITEM_NORMAL,
    2458             text='Export PDF...')
    2459         self.ExportPDF.append(item)
    2460         item.Enable(False)
    2461         self.Bind(wx.EVT_MENU, self.OnExportPDF, id=item.GetId())
    2462            
    2463     def FillMainMenu(self,menubar,addhelp=True):
    2464         '''Define contents of the main GSAS-II menu for the (main) data tree window.
    2465         For the mac, this is also called for the data item windows as well so that
    2466         the main menu items are data menu as well.
    2467         '''
    2468         File = wx.Menu(title='')
    2469         menubar.Append(menu=File, title='&File')
    2470         self._Add_FileMenuItems(File)
    2471         Data = wx.Menu(title='')
    2472         menubar.Append(menu=Data, title='Data')
    2473         self._Add_DataMenuItems(Data)
    2474         Calculate = wx.Menu(title='')       
    2475         menubar.Append(menu=Calculate, title='&Calculate')
    2476         self._Add_CalculateMenuItems(Calculate)
    2477         Import = wx.Menu(title='')       
    2478         menubar.Append(menu=Import, title='Import')
    2479         self._Add_ImportMenu_Image(Import)
    2480         self._Add_ImportMenu_Phase(Import)
    2481         self._Add_ImportMenu_powder(Import)
    2482         self._Add_ImportMenu_Sfact(Import)
    2483         self._Add_ImportMenu_smallangle(Import)
    2484         self._Add_ImportMenu_reflectometry(Import)
    2485         self._Add_ImportMenu_PDF(Import)
    2486 
    2487         #======================================================================
    2488         # Code to help develop/debug an importer, much is hard-coded below
    2489         # but module is reloaded before each use, allowing faster testing
    2490         # def DebugImport(event):
    2491         #     print 'start reload'
    2492         #     import G2phase_ISO as dev
    2493         #     reload(dev)
    2494         #     rd = dev.ISODISTORTPhaseReader()
    2495         #     self.ImportMenuId[event.GetId()] = rd
    2496         #     self.OnImportPhase(event)
    2497             # or ----------------------------------------------------------------------
    2498             #self.OnImportGeneric(rd,[],'test of ISODISTORTPhaseReader')
    2499             # special debug code
    2500             # or ----------------------------------------------------------------------
    2501             # filename = '/Users/toby/projects/branton/subgroup_cif.txt'
    2502             # fp = open(filename,'Ur')
    2503             # if not rd.ContentsValidator(fp):
    2504             #     print 'not validated'
    2505             #     # make a list of used phase ranId's
    2506             # phaseRIdList = []
    2507             # sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    2508             # if sub:
    2509             #     item, cookie = self.PatternTree.GetFirstChild(sub)
    2510             #     while item:
    2511             #         phaseName = self.PatternTree.GetItemText(item)
    2512             #         ranId = self.PatternTree.GetItemPyData(item).get('ranId')
    2513             #         if ranId: phaseRIdList.append(ranId)
    2514             #         item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    2515             # if rd.Reader(filename,fp,usedRanIdList=phaseRIdList):
    2516             #     print 'read OK'
    2517         # item = Import.Append(
    2518         #     wx.ID_ANY,kind=wx.ITEM_NORMAL,
    2519         #     help="debug importer",text="test importer")
    2520         # self.Bind(wx.EVT_MENU, DebugImport, id=item.GetId())
    2521         #======================================================================
    2522         self.ExportMenu = wx.Menu(title='')
    2523         menubar.Append(menu=self.ExportMenu, title='Export')
    2524         self._init_Exports(self.ExportMenu)
    2525         self._Add_ExportMenuItems(self.ExportMenu)
    2526         if GSASIIpath.GetConfigValue('Enable_logging'):
    2527             self.MacroMenu = wx.Menu(title='')
    2528             menubar.Append(menu=self.MacroMenu, title='Macro')
    2529             self._init_Macro()
    2530         if addhelp:
    2531             HelpMenu=G2G.MyHelp(self,includeTree=True,
    2532                 morehelpitems=[('&Tutorials','Tutorials'),])
    2533             menubar.Append(menu=HelpMenu,title='&Help')
    2534            
    2535     def _init_ctrls(self, parent):
    2536         wx.Frame.__init__(self, name='GSASII', parent=parent,
    2537             size=wx.Size(700, 450),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
    2538             #size=wx.Size(400, 450),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
    2539         clientSize = wx.ClientDisplayRect()
    2540         Size = self.GetSize()
    2541         xPos = clientSize[2]-Size[0]
    2542         self.SetPosition(wx.Point(xPos,clientSize[1]))
    2543         self._init_Imports()
    2544         #initialize Menu item objects (these contain lists of menu items that are enabled or disabled)
    2545         self.MakePDF = []
    2546         self.Refine = []
    2547         self.SeqRefine = [] # pointer(s) to Sequential Refinement menu objects
    2548         #self.ExportPattern = []
    2549         self.ExportPeakList = []
    2550         self.ExportHKL = []
    2551         self.ExportPDF = []
    2552         self.ExportPhase = []
    2553         self.ExportCIF = []
    2554         #
    2555         self.GSASIIMenu = wx.MenuBar()
    2556         # create a list of all dataframe menus (appended in PrefillDataMenu)
    2557         self.dataMenuBars = [self.GSASIIMenu]
    2558         self.MacroStatusList = []
    2559         self.FillMainMenu(self.GSASIIMenu)
    2560         self.SetMenuBar(self.GSASIIMenu)
    2561         #self.Bind(wx.EVT_SIZE, self.OnSize)
    2562         self.Status = self.CreateStatusBar()
    2563         #self.mainPanel = GSASIIsplit(self,-1)
    2564         self.mainPanel = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_BORDER|wx.SP_LIVE_UPDATE)
    2565         self.mainPanel.SetMinimumPaneSize(100)
    2566         self.treePanel = wx.Panel(self.mainPanel, wx.ID_ANY,
    2567             style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
    2568         #self.dataPanel = wx.Panel(self.mainPanel, wx.ID_ANY,
    2569         #    style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
    2570         #self.mainPanel.SplitVertically(self.treePanel, self.dataPanel, 200)
    2571        
    2572         self.dataWindow = G2gd.DataWindow(self.mainPanel)
    2573         #self.dataWindow = wxscroll.ScrolledPanel(self.mainPanel,style=wx.BORDER_SUNKEN)
    2574         self.mainPanel.SplitVertically(self.treePanel, self.dataWindow, 200)
    2575        
    2576         wxID_PATTERNTREE = wx.NewId()
    2577         treeSizer = wx.BoxSizer()
    2578         self.treePanel.SetSizer(treeSizer)
    2579         self.PatternTree = G2G.G2TreeCtrl(id=wxID_PATTERNTREE,
    2580             parent=self.treePanel, size=self.treePanel.GetClientSize(),style=wx.TR_DEFAULT_STYLE )
    2581         treeSizer.Add(self.PatternTree,1,wx.EXPAND|wx.ALL,0)
    2582         self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,self.OnDataTreeSelChanged)
    2583         self.PatternTree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,self.OnDataTreeSelChanged)
    2584         self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
    2585             self.OnPatternTreeItemCollapsed, id=wxID_PATTERNTREE)
    2586         self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
    2587             self.OnPatternTreeItemExpanded, id=wxID_PATTERNTREE)
    2588         self.PatternTree.Bind(wx.EVT_TREE_DELETE_ITEM,
    2589             self.OnPatternTreeItemDelete, id=wxID_PATTERNTREE)
    2590         self.PatternTree.Bind(wx.EVT_TREE_KEY_DOWN,
    2591             self.OnPatternTreeKeyDown, id=wxID_PATTERNTREE)
    2592         self.PatternTree.Bind(wx.EVT_TREE_BEGIN_RDRAG,
    2593             self.OnPatternTreeBeginRDrag, id=wxID_PATTERNTREE)       
    2594         self.PatternTree.Bind(wx.EVT_TREE_END_DRAG,
    2595             self.OnPatternTreeEndDrag, id=wxID_PATTERNTREE)       
    2596         self.root = self.PatternTree.root       
    2597        
    2598         # def FillWindow(panel,sizer,size=1.):
    2599         #     sizer.Add(wx.StaticText(panel, wx.ID_ANY, "Panel Two: long line "+int(size*40)*'*', (5,5)))
    2600         #     for i in range(int(size*15)): sizer.Add(wx.StaticText(panel, wx.ID_ANY, "Line "+str(2+i), (5,5)))
    2601 
    2602         # dataSizer = wx.BoxSizer(wx.VERTICAL)
    2603         # FillWindow(self.dataWindow,dataSizer)
    2604         # self.dataWindow.SetSizer(dataSizer)
    2605         #self.dataWindow = G2gd.DataWindow(self.dataPanel)
    2606         #self.dataWindow.SetSize(self.dataPanel.GetClientSize())
    2607         #self.dataWindow.SetInitialSize()
    2608         self.dataWindow.SetupScrolling()
    2609         self.dataFrame = self.dataWindow        #kluge!!
    2610 #        self.SetDataSize()
    2611        
    2612        
    2613         plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \
    2614             style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
    2615         self.G2plotNB = G2plt.G2PlotNoteBook(plotFrame,G2frame=self)
    2616         plotFrame.Show()
    2617        
    2618     def __init__(self, parent):
    2619         self.ExportLookup = {}
    2620         self.exporterlist = []
    2621         self._init_ctrls(parent)
    2622         self.Image = wx.Image(
    2623             os.path.join(GSASIIpath.path2GSAS2,'gsas2.ico'),
    2624             wx.BITMAP_TYPE_ICO)
    2625         if "wxMSW" in wx.PlatformInfo:
    2626             img = self.Image.Scale(16, 16).ConvertToBitmap()
    2627         elif "wxGTK" in wx.PlatformInfo:
    2628             img = self.Image.Scale(22, 22).ConvertToBitmap()
    2629         else:
    2630             img = self.Image.ConvertToBitmap()
    2631         self.SetIcon(wx.IconFromBitmap(img))
    2632         self.Bind(wx.EVT_CLOSE, self.ExitMain)
    2633         # various defaults
    2634         self.oldFocus = None
    2635         self.GSASprojectfile = ''
    2636         self.undofile = ''
    2637         self.TreeItemDelete = False
    2638         self.plotStyle = {'qPlot':False,'dPlot':False,'sqrtPlot':False,'sqPlot':False}
    2639         self.Weight = False
    2640         self.IfPlot = False
    2641         self.DDShowAll = False
    2642         self.atmSel = ''
    2643         self.PatternId = 0
    2644         self.PickId = 0
    2645         self.PickIdText = None
    2646         self.PeakTable = []
    2647         self.LimitsTable = []
    2648         self.ifX20 = True   #use M20 /= (1+X20) in powder indexing, etc.
    2649         self.HKL = []
    2650         self.Lines = []
    2651         self.itemPicked = None
    2652         self.Interpolate = 'nearest'
    2653         self.ContourColor = GSASIIpath.GetConfigValue('Contour_color','Paired')
    2654         self.VcovColor = 'RdYlGn'
    2655         self.RamaColor = 'Blues'
    2656         self.Projection = 'equal area'
    2657         self.logPlot = False
    2658         self.plusPlot = True
    2659         self.ErrorBars = False
    2660         self.Contour = False
    2661         self.Legend = False
    2662         self.SinglePlot = True
    2663         self.Waterfall = False
    2664         self.selections= None
    2665         self.PDFselections = None
    2666         self.SubBack = False
    2667         self.seqReverse = False
    2668         self.seqLines = True #draw lines between points
    2669         self.plotView = 0
    2670         self.Image = 0
    2671         self.oldImagefile = '' # the name of the last image file read
    2672         self.oldImageTag = None # the name of the tag for multi-image files
    2673         self.PauseIntegration = False
    2674         self.ImageZ = []
    2675         self.Integrate = 0
    2676         self.imageDefault = {}
    2677         self.IntgOutList = [] # list of integration tree item Ids created in G2IO.SaveIntegration
    2678         self.AutointPWDRnames = [] # list of autoint created PWDR tree item names (to be deleted on a reset)
    2679         self.autoIntFrame = None
    2680         self.IntegratedList = [] # list of already integrated IMG tree items
    2681         self.Sngl = False
    2682         self.ifGetRing = False
    2683         self.MaskKey = ''           #trigger for making image masks
    2684         self.MskDelete = False      #trigger for mask delete
    2685         self.StrainKey = ''         #ditto for new strain d-zeros
    2686         self.EnablePlot = True
    2687         self.hist = ''              # selected histogram in Phase/Data tab
    2688         self.dirname = os.path.abspath(os.path.expanduser('~'))       #start in the users home directory by default; may be meaningless
    2689         self.TutorialImportDir = None  # location to read tutorial files, set when a tutorial is viewed
    2690         self.LastImportDir = None # last-used directory where an import was done
    2691         self.LastGPXdir = None    # directory where a GPX file was last read
    2692         self.LastExportDir = None  # the last directory used for exports, if any.
    2693         self.dataDisplayPhaseText = ''
    2694         self.lastTreeSetting = []
    2695         self.ExpandingAll = False
    2696         self.SeqTblHideList = []
    2697                
    2698         arg = sys.argv
    2699         if len(arg) > 1 and arg[1]:
    2700             self.GSASprojectfile = os.path.splitext(arg[1])[0]+'.gpx'
    2701             self.dirname = os.path.abspath(os.path.dirname(arg[1]))
    2702             if self.dirname: os.chdir(self.dirname)
    2703             try:
    2704                 self.StartProject()         #open the file if possible
     70            except:
     71                pass
     72            try:
     73                print "trying a user level PyOpenGl install"
     74                easy_install.main(['-f',os.path.split(__file__)[0],'--user',package])
    270575                return
    2706             except Exception:
    2707                 print 'Error opening or reading file',arg[1]
     76            except:
     77                print "Install of '+package+' failed. Please report this information:"
    270878                import traceback
    270979                print traceback.format_exc()
    2710                
    2711         if GSASIIpath.GetConfigValue('Starting_directory'):
    2712             try:
    2713                 pth = GSASIIpath.GetConfigValue('Starting_directory')
    2714                 pth = os.path.expanduser(pth)
    2715                 os.chdir(pth)
    2716                 self.LastGPXdir = pth
    2717             except:
    2718                 print('Ignoring Config Starting_directory value: '+
    2719                       GSASIIpath.GetConfigValue('Starting_directory'))
     80                sys.exit()
     81        from setuptools.command import easy_install
     82        install_with_easyinstall('PyOpenGl')
     83        print('*******************************************************')         
     84        print('OpenGL has been installed. Restarting GSAS-II')
     85        print('*******************************************************')         
     86        loc = os.path.dirname(__file__)
     87        import subprocess
     88        subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py')])
     89        sys.exit()
    272090
    2721     def GetTreeItemsList(self,item):
    2722         return self.PatternTree._getTreeItemsList(item)
    2723 
    2724     # def OnSize(self,event):
    2725     #     'Called to make PatternTree fill mainPanel'
    2726     #     print 'OnSize'
    2727     #     event.Skip()
    2728         # w,h = self.GetClientSizeTuple()
    2729         # self.dataWindow.SetupScrolling()
    2730         # self.mainPanel.SetSize(wx.Size(w,h))
    2731         # self.PatternTree.SetSize(wx.Size(w,h))
    2732         # self.dataWindow.SetSize(self.dataPanel.GetClientSize())
    2733        
    2734     def SetDataSize(self):
    2735         self.dataWindow.Layout()
    2736         self.dataWindow.SendSizeEvent()
    2737         # print 'SetDataSize'
    2738         # Size = self.GetSize()
    2739         # self.SetSize(Size)
    2740         # Size[1] += 1        #kluge to ensure scrollbar settings & window properly displayed
    2741         # self.SetSize(Size)
    2742                                
    2743     def OnDataTreeSelChanged(self, event):
    2744         '''Called when a data tree item is selected'''
    2745         if self.TreeItemDelete:
    2746             self.TreeItemDelete = False
    2747         else:
    2748             if self.ExpandingAll:
    2749                 if GSASIIpath.GetConfigValue('debug'): print('Skipping Tree selection due to ExpandAll')
    2750                 return
    2751             pltNum = self.G2plotNB.nb.GetSelection()
    2752             if pltNum >= 0:                         #to avoid the startup with no plot!
    2753                 self.G2plotNB.nb.GetPage(pltNum)
    2754             item = event.GetItem()
    2755             wx.CallAfter(G2gd.SelectDataTreeItem,self,item,self.oldFocus)
    2756             #if self.oldFocus: # now done via last parameter on SelectDataTreeItem
    2757             #    wx.CallAfter(self.oldFocus.SetFocus)
    2758        
    2759     def OnPatternTreeItemCollapsed(self, event):
    2760         'Called when a tree item is collapsed - all children will be collapsed'
    2761         self.PatternTree.CollapseAllChildren(event.GetItem())
    2762 
    2763     def OnPatternTreeItemExpanded(self, event):
    2764         'Called when a tree item is expanded'
    2765         self.OnDataTreeSelChanged(event)
    2766         event.Skip()
    2767        
    2768     def OnPatternTreeItemDelete(self, event):
    2769         'Called when a tree item is deleted -- not sure what this does'
    2770         self.TreeItemDelete = True
    2771 
    2772     def OnPatternTreeItemActivated(self, event):
    2773         'Called when a tree item is activated'
    2774         event.Skip()
    2775        
    2776     def OnPatternTreeBeginRDrag(self,event):
    2777         event.Allow()
    2778         self.BeginDragId = event.GetItem()
    2779         self.ParentId = self.PatternTree.GetItemParent(self.BeginDragId)
    2780         DragText = self.PatternTree.GetItemText(self.BeginDragId)
    2781         self.DragData = [[DragText,self.PatternTree.GetItemPyData(self.BeginDragId)],]
    2782         item, cookie = self.PatternTree.GetFirstChild(self.BeginDragId)
    2783         while item:     #G2 data tree has no sub children under a child of a tree item
    2784             name = self.PatternTree.GetItemText(item)
    2785             self.DragData.append([name,self.PatternTree.GetItemPyData(item)])
    2786             item, cookie = self.PatternTree.GetNextChild(self.BeginDragId, cookie)                           
    2787        
    2788     def OnPatternTreeEndDrag(self,event):
    2789         event.Allow()
    2790         self.EndDragId = event.GetItem()
    2791         try:
    2792             NewParent = self.PatternTree.GetItemParent(self.EndDragId)
    2793         except:
    2794             self.EndDragId = self.PatternTree.GetLastChild(self.root)
    2795             NewParent = self.root
    2796         if self.ParentId != NewParent:
    2797             self.ErrorDialog('Drag not allowed','Wrong parent for item dragged')
    2798         else:
    2799             Name,Item = self.DragData[0]
    2800             NewId = self.PatternTree.InsertItem(self.ParentId,self.EndDragId,Name,data=None)
    2801             self.PatternTree.SetItemPyData(NewId,Item)
    2802             for name,item in self.DragData[1:]:     #loop over children
    2803                 Id = self.PatternTree.AppendItem(parent=NewId,text=name)
    2804                 self.PatternTree.SetItemPyData(Id,item)
    2805             self.PatternTree.Delete(self.BeginDragId)
    2806             G2gd.SelectDataTreeItem(self,NewId)
    2807        
    2808     def OnPatternTreeKeyDown(self,event): #doesn't exactly work right with Shift key down
    2809         'Allows stepping through the tree with the up/down arrow keys'
    2810         self.oldFocus = wx.Window.FindFocus()
    2811         keyevt = event.GetKeyEvent()
    2812         key = event.GetKeyCode()
    2813         item = self.PatternTree.GetSelection()
    2814         if type(item) is int: return # is this the toplevel in tree?
    2815         name = self.PatternTree.GetItemText(item)
    2816         parent = self.PatternTree.GetItemParent(item)
    2817         if key == wx.WXK_UP:
    2818             if keyevt.GetModifiers() == wx.MOD_SHIFT and parent != self.root:
    2819                 if type(parent) is int: return # is this the toplevel in tree?
    2820                 prev = self.PatternTree.GetPrevSibling(parent)
    2821                 NewId = G2gd.GetPatternTreeItemId(self,prev,name)
    2822                 if NewId:
    2823                     self.PatternTree.Collapse(parent)
    2824                     self.PatternTree.Expand(prev)
    2825                     self.oldFocus = wx.Window.FindFocus()
    2826                     wx.CallAfter(self.PatternTree.SelectItem,NewId)
    2827                 else:
    2828                     wx.CallAfter(self.PatternTree.SelectItem,item)
    2829             elif sys.platform == "win32":   
    2830                 self.PatternTree.GetPrevSibling(item)
    2831                 self.PatternTree.SelectItem(item)
    2832             else:
    2833                 item = self.PatternTree.GetPrevSibling(item)
    2834                 if item.IsOk(): self.PatternTree.SelectItem(item)
    2835         elif key == wx.WXK_DOWN:
    2836             if keyevt.GetModifiers() == wx.MOD_SHIFT and parent != self.root:
    2837                 next = self.PatternTree.GetNextSibling(parent)
    2838                 NewId = G2gd.GetPatternTreeItemId(self,next,name)
    2839                 if NewId:
    2840                     self.PatternTree.Collapse(parent)
    2841                     self.PatternTree.Expand(next)
    2842                     self.oldFocus = wx.Window.FindFocus()
    2843                     wx.CallAfter(self.PatternTree.SelectItem,NewId)
    2844                 else:
    2845                     wx.CallAfter(self.PatternTree.SelectItem,item)
    2846             elif sys.platform == "win32":   
    2847                 self.PatternTree.GetNextSibling(item)
    2848                 self.PatternTree.SelectItem(item)
    2849             else:   
    2850                 item = self.PatternTree.GetNextSibling(item)
    2851                 if item.IsOk(): self.PatternTree.SelectItem(item)
    2852                
    2853     def OnReadPowderPeaks(self,event):
    2854         'Bound to menu Data/Read Powder Peaks'
    2855         self.CheckNotebook()
    2856         pth = G2G.GetImportPath(self)
    2857         if not pth: pth = '.'
    2858         dlg = wx.FileDialog(self, 'Choose file with peak list', pth, '',
    2859             'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN)
    2860         try:
    2861             if dlg.ShowModal() == wx.ID_OK:
    2862                 self.HKL = []
    2863                 self.powderfile = dlg.GetPath()
    2864                 comments,peaks,limits,wave = G2IO.GetPowderPeaks(self.powderfile)
    2865                 Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+os.path.basename(self.powderfile))
    2866                 data = ['PKS',wave,0.0]
    2867                 names = ['Type','Lam','Zero']
    2868                 codes = [0,0,0]
    2869                 inst = [G2IO.makeInstDict(names,data,codes),{}]
    2870                 self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),inst)
    2871                 self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
    2872                 self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(limits),limits])
    2873                 self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[peaks,[]])
    2874                 self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
    2875                 self.PatternTree.Expand(Id)
    2876                 self.PatternTree.SelectItem(Id)
    2877                 os.chdir(dlg.GetDirectory())           # to get Mac/Linux to change directory!
    2878         finally:
    2879             dlg.Destroy()
    2880                        
    2881     # def OnImageRead(self,event):
    2882     #     '''Called to read in an image in any known format. *** Depreciated. ***
    2883     #     '''
    2884     #     G2G.G2MessageBox(self,'Please use the Import/Image/... menu item rather than this','depreciating menu item')
    2885 
    2886     def CheckNotebook(self):
    2887         '''Make sure the data tree has the minimally expected controls.
    2888         '''
    2889         if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
    2890             sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
    2891             self.PatternTree.SetItemPyData(sub,[''])
    2892         if not G2gd.GetPatternTreeItemId(self,self.root,'Controls'):
    2893             sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
    2894             self.PatternTree.SetItemPyData(sub,copy.copy(G2obj.DefaultControls))
    2895         if not G2gd.GetPatternTreeItemId(self,self.root,'Covariance'):
    2896             sub = self.PatternTree.AppendItem(parent=self.root,text='Covariance')
    2897             self.PatternTree.SetItemPyData(sub,{})
    2898         if not G2gd.GetPatternTreeItemId(self,self.root,'Constraints'):
    2899             sub = self.PatternTree.AppendItem(parent=self.root,text='Constraints')
    2900             self.PatternTree.SetItemPyData(sub,{'Hist':[],'HAP':[],'Phase':[]})
    2901         if not G2gd.GetPatternTreeItemId(self,self.root,'Restraints'):
    2902             sub = self.PatternTree.AppendItem(parent=self.root,text='Restraints')
    2903             self.PatternTree.SetItemPyData(sub,{})
    2904         if not G2gd.GetPatternTreeItemId(self,self.root,'Rigid bodies'):
    2905             sub = self.PatternTree.AppendItem(parent=self.root,text='Rigid bodies')
    2906             self.PatternTree.SetItemPyData(sub,{'Vector':{'AtInfo':{}},
    2907                 'Residue':{'AtInfo':{}},'RBIds':{'Vector':[],'Residue':[]}})
    2908                
    2909     class CopyDialog(wx.Dialog):
    2910         '''Creates a dialog for copying control settings between
    2911         data tree items'''
    2912         def __init__(self,parent,title,text,data):
    2913             wx.Dialog.__init__(self,parent,-1,title,
    2914                 pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
    2915             self.data = data
    2916             panel = wx.Panel(self)
    2917             mainSizer = wx.BoxSizer(wx.VERTICAL)
    2918             topLabl = wx.StaticText(panel,-1,text)
    2919             mainSizer.Add((10,10),1)
    2920             mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
    2921             mainSizer.Add((10,10),1)
    2922             ncols = len(data)/40+1
    2923             dataGridSizer = wx.FlexGridSizer(cols=ncols,hgap=2,vgap=2)
    2924             for id,item in enumerate(self.data):
    2925                 ckbox = wx.CheckBox(panel,id,item[1])
    2926                 ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange)                   
    2927                 dataGridSizer.Add(ckbox,0,wx.LEFT,10)
    2928             mainSizer.Add(dataGridSizer,0,wx.EXPAND)
    2929             OkBtn = wx.Button(panel,-1,"Ok")
    2930             OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
    2931             cancelBtn = wx.Button(panel,-1,"Cancel")
    2932             cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
    2933             btnSizer = wx.BoxSizer(wx.HORIZONTAL)
    2934             btnSizer.Add((20,20),1)
    2935             btnSizer.Add(OkBtn)
    2936             btnSizer.Add((20,20),1)
    2937             btnSizer.Add(cancelBtn)
    2938             btnSizer.Add((20,20),1)
    2939            
    2940             mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
    2941             panel.SetSizer(mainSizer)
    2942             panel.Fit()
    2943             self.Fit()
    2944        
    2945         def OnCopyChange(self,event):
    2946             id = event.GetId()
    2947             self.data[id][0] = self.FindWindowById(id).GetValue()       
    2948            
    2949         def OnOk(self,event):
    2950             parent = self.GetParent()
    2951             parent.Raise()
    2952             self.EndModal(wx.ID_OK)             
    2953            
    2954         def OnCancel(self,event):
    2955             parent = self.GetParent()
    2956             parent.Raise()
    2957             self.EndModal(wx.ID_CANCEL)             
    2958            
    2959         def GetData(self):
    2960             return self.data
    2961        
    2962     class SumDialog(wx.Dialog):
    2963         '''Allows user to supply scale factor(s) when summing data -
    2964         TODO: CAN WE PREVIEW RESULT HERE?'''
    2965         def __init__(self,parent,title,text,dataType,data,dataList):
    2966             wx.Dialog.__init__(self,parent,-1,title,size=(400,250),
    2967                 pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
    2968             self.plotFrame = wx.Frame(self,-1,'Sum Plots',size=wx.Size(700,600), \
    2969                 style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
    2970             self.G2plotNB = G2plt.G2PlotNoteBook(self.plotFrame,G2frame=self)
    2971             self.data = data
    2972             self.dataList = dataList
    2973             self.dataType = dataType
    2974             size = (450,350)
    2975             panel = wxscroll.ScrolledPanel(self, wx.ID_ANY,size=size,
    2976                 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
    2977             mainSizer = wx.BoxSizer(wx.VERTICAL)
    2978             topLabl = wx.StaticText(panel,-1,text)
    2979             mainSizer.Add((10,10),1)
    2980             mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
    2981             mainSizer.Add((10,10),1)
    2982             self.dataGridSizer = wx.FlexGridSizer(cols=2,hgap=2,vgap=2)
    2983             for id,item in enumerate(self.data[:-1]):
    2984                 name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(300,20))
    2985                 name.SetEditable(False)
    2986 #        azmthOff = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,data,'azmthOff',nDig=(10,2),typeHint=float,OnLeave=OnAzmthOff)
    2987                 scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
    2988                 scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
    2989                 scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
    2990                 self.dataGridSizer.Add(scale,0,wx.LEFT,10)
    2991                 self.dataGridSizer.Add(name,0,wx.RIGHT,10)
    2992             if self.dataType:
    2993                 self.dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+self.dataType),0, \
    2994                     wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
    2995                 self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(300,20),style=wx.TE_PROCESS_ENTER)
    2996                 self.name.Bind(wx.EVT_TEXT_ENTER,self.OnNameChange)
    2997                 self.name.Bind(wx.EVT_KILL_FOCUS,self.OnNameChange)
    2998                 self.dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
    2999                 self.dataGridSizer.Add(wx.StaticText(panel,label='All scales value: '),0,  \
    3000                     wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
    3001 #        azmthOff = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,data,'azmthOff',nDig=(10,2),typeHint=float,OnLeave=OnAzmthOff)
    3002                 allScale = wx.TextCtrl(panel,value='',style=wx.TE_PROCESS_ENTER)
    3003                 allScale.Bind(wx.EVT_TEXT_ENTER,self.OnAllScale)
    3004                 allScale.Bind(wx.EVT_KILL_FOCUS,self.OnAllScale)
    3005                 self.dataGridSizer.Add(allScale,0,WACV)
    3006             mainSizer.Add(self.dataGridSizer,0,wx.EXPAND)
    3007             OkBtn = wx.Button(panel,-1,"Ok")
    3008             OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
    3009             cancelBtn = wx.Button(panel,-1,"Cancel")
    3010             cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
    3011             btnSizer = wx.FlexGridSizer(0,3,10,20)
    3012             if self.dataType =='PWDR':
    3013                 TestBtn = wx.Button(panel,-1,"Test")
    3014                 TestBtn.Bind(wx.EVT_BUTTON, self.OnTest)
    3015                 btnSizer.Add(TestBtn)
    3016             btnSizer.Add(OkBtn)
    3017             btnSizer.Add(cancelBtn)
    3018            
    3019             panel.SetSizer(mainSizer)
    3020             panel.SetAutoLayout(1)
    3021             panel.SetupScrolling()
    3022             mainSizer.Add((10,10),1)
    3023             mainSizer.Add(btnSizer,0,wx.CENTER)
    3024             panel.SetSizer(mainSizer)
    3025             panel.Fit()
    3026             self.Fit()
    3027 
    3028         def OnScaleChange(self,event):
    3029             event.Skip()
    3030             id = event.GetId()
    3031             value = self.FindWindowById(id).GetValue()
    3032             try:
    3033                 self.data[id][0] = float(value)
    3034                 self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0]))
    3035             except ValueError:
    3036                 if value and '-' not in value[0]:
    3037                     print 'bad input - numbers only'
    3038                     self.FindWindowById(id).SetValue('0.000')
    3039                    
    3040         def OnAllScale(self,event):
    3041             event.Skip()
    3042             id = event.GetId()
    3043             try:
    3044                 scale = float(self.FindWindowById(id).GetValue())
    3045                 self.FindWindowById(id).SetValue('%.3f'%(scale))
    3046                 entries = self.dataGridSizer.GetChildren()
    3047                 for i,item in enumerate(self.data[:-1]):
    3048                     item[0] = scale
    3049                     entries[2*i].GetWindow().SetValue('%.3f'%(scale))
    3050                  
    3051             except ValueError:
    3052                 print 'bad input - numbers only'
    3053                 self.FindWindowById(id).SetValue('')
    3054                    
    3055            
    3056         def OnNameChange(self,event):
    3057             event.Skip()
    3058             self.data[-1] = self.name.GetValue()
    3059            
    3060         def OnTest(self,event):
    3061             lenX = 0
    3062             Xminmax = [0,0]
    3063             XY = []
    3064             Xsum = []
    3065             Ysum = []
    3066             Vsum = []
    3067             result = self.data
    3068             for i,item in enumerate(result[:-1]):
    3069                 scale,name = item
    3070                 data = self.dataList[i]
    3071                 if scale:
    3072                     x,y,w,yc,yb,yd = data   #numpy arrays!
    3073                     XY.append([x,scale*y])
    3074                     v = 1./w
    3075                     if lenX:
    3076                         if lenX != len(x):
    3077                             self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
    3078                                 '\nExpected:'+str(lenX)+ \
    3079                                 '\nFound:   '+str(len(x))+'\nfor '+name)
    3080                             self.OnCancel(event)
    3081                     else:
    3082                         lenX = len(x)
    3083                     if Xminmax[1]:
    3084                         if Xminmax != [x[0],x[-1]]:
    3085                             self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
    3086                                 '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
    3087                                 '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
    3088                             self.OnCancel(event)
    3089                         else:
    3090                             for j,yi in enumerate(y):
    3091                                  Ysum[j] += scale*yi
    3092                                  Vsum[j] += abs(scale)*v[j]
    3093                     else:
    3094                         Xminmax = [x[0],x[-1]]
    3095                         Xsum = x
    3096                         Ysum = scale*y
    3097                         Vsum = abs(scale*v)
    3098             Wsum = 1./np.array(Vsum)
    3099             YCsum = np.zeros(lenX)
    3100             YBsum = np.zeros(lenX)
    3101             YDsum = np.zeros(lenX)
    3102             XY.append([Xsum,Ysum])
    3103             self.result = [Xsum,Ysum,Wsum,YCsum,YBsum,YDsum]
    3104             # N.B. PlotXY expects the first arg to point to G2frame. In this case, we
    3105             # create a duplicate (temporary) Plot notebook window that is a child of the
    3106             # modal SumDialog dialog (self). This nicely gets deleted when the dialog is destroyed,
    3107             # but the plot window is not fully functional, at least on the Mac.
    3108             G2plt.PlotXY(self,XY,lines=True,Title='Sum:'+self.data[-1],labelY='Intensity',)
    3109             self.plotFrame.Show()
    3110                        
    3111         def OnOk(self,event):
    3112             if self.dataType == 'PWDR': self.OnTest(event)
    3113             parent = self.GetParent()
    3114             parent.Raise()
    3115             self.EndModal(wx.ID_OK)             
    3116            
    3117         def OnCancel(self,event):
    3118             parent = self.GetParent()
    3119             parent.Raise()
    3120             self.EndModal(wx.ID_CANCEL)             
    3121            
    3122         def GetData(self):
    3123             if self.dataType == 'PWDR':
    3124                 return self.data,self.result
    3125             else:
    3126                 return self.data
    3127                        
    3128     def OnPwdrSum(self,event):
    3129         'Sum together powder data(?)'
    3130         TextList = []
    3131         DataList = []
    3132         Names = []
    3133         Inst = None
    3134         Comments = ['Sum equals: \n']
    3135         if self.PatternTree.GetCount():
    3136             item, cookie = self.PatternTree.GetFirstChild(self.root)
    3137             while item:
    3138                 name = self.PatternTree.GetItemText(item)
    3139                 Names.append(name)
    3140                 if 'PWDR' in name:
    3141                     TextList.append([0.0,name])
    3142                     DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
    3143                     if not Inst:
    3144                         Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
    3145                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3146             if len(TextList) < 2:
    3147                 self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
    3148                 return
    3149             TextList.append('default_sum_name')               
    3150             dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList,DataList)
    3151             try:
    3152                 if dlg.ShowModal() == wx.ID_OK:
    3153                     result,sumData = dlg.GetData()
    3154                     Xsum,Ysum,Wsum,YCsum,YBsum,YDsum = sumData
    3155                     Xminmax = [Xsum[0],Xsum[-1]]
    3156                     outname = 'PWDR '+result[-1]
    3157                     Id = 0
    3158                     if outname in Names:
    3159                         dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
    3160                         try:
    3161                             if dlg2.ShowModal() == wx.ID_OK:
    3162                                 Id = G2gd.GetPatternTreeItemId(self,self.root,name)
    3163                                 self.PatternTree.Delete(Id)
    3164                         finally:
    3165                             dlg2.Destroy()
    3166                     Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
    3167                     if Id:
    3168                         Sample = G2obj.SetDefaultSample()
    3169                         Ymin = np.min(Ysum)
    3170                         Ymax = np.max(Ysum)
    3171                         valuesdict = {
    3172                             'wtFactor':1.0,
    3173                             'Dummy':False,
    3174                             'ranId':ran.randint(0,sys.maxint),
    3175                             'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax,
    3176                             'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax]
    3177                             }
    3178                         self.PatternTree.SetItemPyData(Id,[valuesdict,[np.array(Xsum),np.array(Ysum),np.array(Wsum),
    3179                             np.array(YCsum),np.array(YBsum),np.array(YDsum)]])
    3180                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
    3181                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
    3182                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
    3183                             {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
    3184                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
    3185                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
    3186                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),{'peaks':[],'sigDict':{}})
    3187                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[[],[]])
    3188                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
    3189                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
    3190                         self.PatternTree.SelectItem(Id)
    3191                         self.PatternTree.Expand(Id)
    3192             finally:
    3193                 dlg.Destroy()
    3194 
    3195     def OnImageSum(self,event):
    3196         'Sum together image data'
    3197         TextList = []
    3198         DataList = []
    3199         IdList = []
    3200         Names = []
    3201         Comments = ['Sum equals: \n']
    3202         if self.PatternTree.GetCount():
    3203             item, cookie = self.PatternTree.GetFirstChild(self.root)
    3204             while item:
    3205                 name = self.PatternTree.GetItemText(item)
    3206                 Names.append(name)
    3207                 if 'IMG' in name:
    3208                     TextList.append([0.0,name])
    3209                     DataList.append(self.PatternTree.GetImageLoc(item))        #Size,Image,Tag
    3210                     IdList.append(item)
    3211                     Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
    3212                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3213             if len(TextList) < 2:
    3214                 self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
    3215                 return
    3216             TextList.append('default_sum_name')               
    3217             dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList,DataList)
    3218             try:
    3219                 if dlg.ShowModal() == wx.ID_OK:
    3220                     imSize = 0
    3221                     result = dlg.GetData()
    3222                     First = True
    3223                     Found = False
    3224                     for i,item in enumerate(result[:-1]):
    3225                         scale,name = item
    3226                         if scale:
    3227                             Found = True                               
    3228                             Comments.append("%10.3f %s" % (scale,' * '+name))
    3229                             Npix,imagefile,imagetag = DataList[i]
    3230                             imagefile = G2IO.GetCheckImageFile(self,IdList[i])[1]
    3231                             image = G2IO.GetImageData(self,imagefile,imageOnly=True,ImageTag=imagetag)
    3232                             if First:
    3233                                 newImage = np.zeros_like(image)
    3234                                 First = False
    3235                             if imSize:
    3236                                 if imSize != Npix:
    3237                                     self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
    3238                                         '\nExpected:'+str(imSize)+ \
    3239                                         '\nFound:   '+str(Npix)+'\nfor '+name)
    3240                                     return
    3241                                 newImage = newImage+scale*image
    3242                             else:
    3243                                 imSize = Npix
    3244                                 newImage = newImage+scale*image
    3245                             del(image)
    3246                     if not Found:
    3247                         self.ErrorDialog('Image sum error','No nonzero image multipliers found')
    3248                         return
    3249                        
    3250                        
    3251                     newImage = np.array(newImage,dtype=np.int32)                       
    3252                     outname = 'IMG '+result[-1]
    3253                     Id = 0
    3254                     if outname in Names:
    3255                         dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
    3256                         try:
    3257                             if dlg2.ShowModal() == wx.ID_OK:
    3258                                 Id = G2gd.GetPatternTreeItemId(self,self.root,name)
    3259                         finally:
    3260                             dlg2.Destroy()
    3261                     else:
    3262                         Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
    3263                     if Id:
    3264                         pth = G2G.GetExportPath(self)
    3265                         dlg = wx.FileDialog(self, 'Choose sum image filename', pth,outname.split('IMG ')[1],
    3266                             'G2img files (*.G2img)|*.G2img',
    3267                             wx.SAVE|wx.FD_OVERWRITE_PROMPT)
    3268                         if dlg.ShowModal() == wx.ID_OK:
    3269                             newimagefile = dlg.GetPath()
    3270                             newimagefile = G2IO.FileDlgFixExt(dlg,newimagefile)
    3271                             G2IO.PutG2Image(newimagefile,Comments,Data,Npix,newImage)
    3272                             Imax = np.amax(newImage)
    3273                             Imin = np.amin(newImage)
    3274                             newImage = []
    3275                             self.PatternTree.SetItemPyData(Id,[imSize,newimagefile])
    3276                             self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
    3277                         del(newImage)
    3278                         if self.imageDefault:
    3279                             Data = copy.copy(self.imageDefault)
    3280                         Data['formatName'] = 'GSAS-II image'
    3281                         Data['showLines'] = True
    3282                         Data['ring'] = []
    3283                         Data['rings'] = []
    3284                         Data['cutoff'] = 10
    3285                         Data['pixLimit'] = 20
    3286                         Data['ellipses'] = []
    3287                         Data['calibrant'] = ''
    3288                         Data['range'] = [(Imin,Imax),[Imin,Imax]]
    3289                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
    3290                         Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Frames':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
    3291                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
    3292                         self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Stress/Strain'),
    3293                             {'Type':'True','d-zero':[],'Sample phi':0.0,'Sample z':0.0,'Sample load':0.0})
    3294                         self.PatternTree.SelectItem(Id)
    3295                         self.PatternTree.Expand(Id)
    3296                         self.PickId = G2gd.GetPatternTreeItemId(self,self.root,outname)
    3297                         self.Image = self.PickId
    3298             finally:
    3299                 dlg.Destroy()
    3300                      
    3301     def OnAddPhase(self,event):
    3302         'Add a new, empty phase to the tree. Called by Data/Add Phase menu'
    3303         if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
    3304             sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
    3305         else:
    3306             sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    3307         PhaseName = ''
    3308         dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
    3309             style=wx.OK)
    3310         if dlg.ShowModal() == wx.ID_OK:
    3311             PhaseName = dlg.GetValue()
    3312         dlg.Destroy()
    3313         sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
    3314         E,SGData = G2spc.SpcGroup('P 1')
    3315         self.PatternTree.SetItemPyData(sub,G2obj.SetNewPhase(Name=PhaseName,SGData=SGData))
    3316         G2gd.SelectDataTreeItem(self,sub) #bring up new phase General tab
    3317        
    3318     def OnDeletePhase(self,event):
    3319         'Delete a phase from the tree. Called by Data/Delete Phase menu'
    3320         #Hmm, also need to delete this phase from Reflection Lists for each PWDR histogram
    3321         if self.dataFrame:
    3322             self.dataFrame.Clear()
    3323         TextList = []
    3324         DelList = []
    3325         DelItemList = []
    3326         if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
    3327             sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    3328         else:
    3329             return
    3330         if sub:
    3331             item, cookie = self.PatternTree.GetFirstChild(sub)
    3332             while item:
    3333                 TextList.append(self.PatternTree.GetItemText(item))
    3334                 item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
    3335             dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
    3336             try:
    3337                 if dlg.ShowModal() == wx.ID_OK:
    3338                     result = dlg.GetSelections()
    3339                     for i in result: DelList.append([i,TextList[i]])
    3340                     item, cookie = self.PatternTree.GetFirstChild(sub)
    3341                     i = 0
    3342                     while item:
    3343                         if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
    3344                         item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    3345                         i += 1
    3346                     for item in DelItemList:
    3347                         name = self.PatternTree.GetItemText(item)
    3348                         self.PatternTree.Delete(item)
    3349                         self.G2plotNB.Delete(name)
    3350                     item, cookie = self.PatternTree.GetFirstChild(self.root)
    3351                     while item:
    3352                         name = self.PatternTree.GetItemText(item)
    3353                         if 'PWDR' in name:
    3354                             Id = G2gd.GetPatternTreeItemId(self,item, 'Reflection Lists')
    3355                             refList = self.PatternTree.GetItemPyData(Id)
    3356                             if len(refList):
    3357                                 for i,item in DelList:
    3358                                     if item in refList:
    3359                                         del(refList[item])
    3360 #                            self.PatternTree.SetItemPyData(Id,refList)
    3361                         elif 'HKLF' in name:
    3362                             data = self.PatternTree.GetItemPyData(item)
    3363                             data[0] = {}
    3364 #                            self.PatternTree.SetItemPyData(item,data)
    3365                            
    3366                         item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3367             finally:
    3368                 dlg.Destroy()
    3369                
    3370     def OnRenameData(self,event):
    3371         'Renames an existing phase. Called by Data/Rename Phase menu'
    3372         name = self.PatternTree.GetItemText(self.PickId)     
    3373         if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
    3374             if 'Bank' in name:
    3375                 names = name.split('Bank')
    3376                 names[1] = ' Bank'+names[1]
    3377             elif 'Azm' in name:
    3378                 names = name.split('Azm')
    3379                 names[1] = ' Azm'+names[1]
    3380             else:
    3381                 names = [name,'']
    3382             dataType = names[0][:names[0].index(' ')+1]                 #includes the ' '
    3383             dlg = wx.TextEntryDialog(self,'Data name: '+name,'Change data name',
    3384                 defaultValue=names[0][names[0].index(' ')+1:])
    3385             try:
    3386                 if dlg.ShowModal() == wx.ID_OK:
    3387                     name = dataType+dlg.GetValue()+names[1]
    3388                     self.PatternTree.SetItemText(self.PickId,name)
    3389             finally:
    3390                 dlg.Destroy()
    3391        
    3392     def GetFileList(self,fileType,skip=None):        #potentially useful?
    3393         'Appears unused. Note routine of same name in GSASIIpwdGUI'
    3394         fileList = []
    3395         Source = ''
    3396         id, cookie = self.PatternTree.GetFirstChild(self.root)
    3397         while id:
    3398             name = self.PatternTree.GetItemText(id)
    3399             if fileType in name:
    3400                 if id == skip:
    3401                     Source = name
    3402                 else:
    3403                     fileList.append([False,name,id])
    3404             id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3405         if skip:
    3406             return fileList,Source
    3407         else:
    3408             return fileList
    3409            
    3410     def OnDataDelete(self, event):
    3411         '''Delete one or more histograms from data tree. Called by the
    3412         Data/DeleteData menu
    3413         '''
    3414         TextList = []
    3415         DelList = []
    3416         DelItemList = []
    3417         nItems = {'PWDR':0,'SASD':0,'REFD':0,'IMG':0,'HKLF':0,'PDF':0}
    3418         PDFnames = []
    3419         if self.PatternTree.GetCount():
    3420             item, cookie = self.PatternTree.GetFirstChild(self.root)
    3421             while item:
    3422                 name = self.PatternTree.GetItemText(item)
    3423                 if name not in ['Notebook','Controls','Covariance','Constraints',
    3424                     'Restraints','Phases','Rigid bodies'] and 'Sequential' not in name:
    3425                     if 'PWDR' in name[:4]: nItems['PWDR'] += 1
    3426                     if 'SASD' in name[:4]: nItems['SASD'] += 1
    3427                     if 'REFD' in name[:4]: nItems['REFD'] += 1
    3428                     if 'IMG' in name[:3]:  nItems['IMG'] += 1
    3429                     if 'HKLF' in name[:4]: nItems['HKLF'] += 1
    3430                     if 'PDF' in name[:3]:
    3431                         PDFnames.append(name)
    3432                         nItems['PDF'] += 1
    3433                     TextList.append(name)
    3434                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3435             for pdfName in PDFnames:
    3436                 try:
    3437                     TextList.remove('PWDR'+pdfName[4:])
    3438                 except ValueError:
    3439                     print 'PWDR'+pdfName[4:]+' for '+pdfName+' not found'
    3440             dlg = G2G.G2MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
    3441             try:
    3442                 if dlg.ShowModal() == wx.ID_OK:
    3443                     result = dlg.GetSelections()
    3444                     for i in result: DelList.append(TextList[i])
    3445                     item, cookie = self.PatternTree.GetFirstChild(self.root)
    3446                     while item:
    3447                         itemName = self.PatternTree.GetItemText(item)
    3448                         if itemName in DelList:
    3449                             if 'PWDR' in itemName[:4]: nItems['PWDR'] -= 1
    3450                             elif 'SASD' in itemName[:4]: nItems['SASD'] -= 1
    3451                             elif 'REFD' in itemName[:4]: nItems['REFD'] -= 1
    3452                             elif 'IMG' in itemName[:3]: nItems['IMG'] -= 1
    3453                             elif 'HKLF' in itemName[:4]: nItems['HKLF'] -= 1
    3454                             elif 'PDF' in itemName[:3]: nItems['PDF'] -= 1
    3455                             DelItemList.append(item)
    3456                         item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3457                     for item in DelItemList:
    3458                         self.PatternTree.Delete(item)
    3459                     self.PickId = 0
    3460                     self.PickIdText = None
    3461                     self.PatternId = 0
    3462                     if nItems['PWDR']:
    3463                         wx.CallAfter(G2plt.PlotPatterns,self,True)
    3464                     else:
    3465                         self.G2plotNB.Delete('Powder Patterns')
    3466                     if not nItems['IMG']:
    3467                         self.G2plotNB.Delete('2D Powder Image')
    3468                     if not nItems['HKLF']:
    3469                         self.G2plotNB.Delete('Structure Factors')
    3470                         if '3D Structure Factors' in self.G2plotNB.plotList:
    3471                             self.G2plotNB.Delete('3D Structure Factors')
    3472             finally:
    3473                 dlg.Destroy()
    3474 
    3475     def OnFileOpen(self, event, filename=None):
    3476         '''Gets a GSAS-II .gpx project file in response to the
    3477         File/Open Project menu button
    3478         '''
    3479         result = wx.ID_OK
    3480         self.EnablePlot = False
    3481         if self.PatternTree.GetChildrenCount(self.root,False):
    3482             if self.dataFrame:
    3483                 self.dataFrame.ClearData()
    3484             dlg = wx.MessageDialog(
    3485                 self,
    3486                 'Do you want to overwrite the current project? '+
    3487                 'Any unsaved changes in current project will be lost. Press OK to continue.',
    3488                 'Overwrite?',  wx.OK | wx.CANCEL)
    3489             try:
    3490                 result = dlg.ShowModal()
    3491                 if result == wx.ID_OK:
    3492                     self.PatternTree.DeleteChildren(self.root)
    3493                     self.GSASprojectfile = ''
    3494                     self.HKL = []
    3495                     if self.G2plotNB.plotList:
    3496                         self.G2plotNB.clear()
    3497             finally:
    3498                 dlg.Destroy()
    3499         if result != wx.ID_OK: return
    3500 
    3501         if not filename:
    3502             if self.LastGPXdir:
    3503                 pth = self.LastGPXdir
    3504             else:
    3505                 pth = '.'
    3506             dlg = wx.FileDialog(self, 'Choose GSAS-II project file', pth,
    3507                 wildcard='GSAS-II project file (*.gpx)|*.gpx',style=wx.OPEN)
    3508             try:
    3509                 if dlg.ShowModal() != wx.ID_OK: return
    3510                 self.GSASprojectfile = dlg.GetPath()
    3511                 self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
    3512                 self.dirname = dlg.GetDirectory()
    3513             finally:
    3514                 dlg.Destroy()
    3515         else:
    3516             self.GSASprojectfile = os.path.splitext(filename)[0]+'.gpx'
    3517             self.dirname = os.path.split(filename)[0]
    3518 
    3519         try:
    3520             self.StartProject()         #open the file if possible
    3521         except:
    3522             print '\nError opening file ',filename
    3523             import traceback
    3524             print traceback.format_exc()
    3525        
    3526     def StartProject(self):
    3527         '''Opens a GSAS-II project file & selects the 1st available data set to
    3528         display (PWDR, HKLF, REFD or SASD)
    3529         '''
    3530        
    3531         Id = 0
    3532         phaseId = None
    3533         G2IO.ProjFileOpen(self)
    3534         self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
    3535         self.PatternTree.Expand(self.root)
    3536         self.HKL = []
    3537         item, cookie = self.PatternTree.GetFirstChild(self.root)
    3538         while item and not Id:
    3539             name = self.PatternTree.GetItemText(item)
    3540             if name[:4] in ['PWDR','HKLF','IMG ','PDF ','SASD','REFD']:
    3541                 Id = item
    3542             elif name == "Phases":
    3543                 phaseId = item
    3544             elif name == 'Controls':
    3545                 data = self.PatternTree.GetItemPyData(item)
    3546                 if data:
    3547                     for item in self.Refine: item.Enable(True)
    3548                     self.EnableSeqRefineMenu()
    3549             item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3550         if phaseId: # show all phases
    3551             self.PatternTree.Expand(phaseId)
    3552         if Id:
    3553             self.EnablePlot = True
    3554             self.PatternTree.SelectItem(Id)
    3555             self.PatternTree.Expand(Id)
    3556         elif phaseId:
    3557             self.PatternTree.SelectItem(phaseId)
    3558         self.CheckNotebook()
    3559         if self.dirname: os.chdir(self.dirname)           # to get Mac/Linux to change directory!
    3560         pth = os.path.split(os.path.abspath(self.GSASprojectfile))[0]
    3561         if GSASIIpath.GetConfigValue('Save_paths'): G2G.SaveGPXdirectory(pth)
    3562         self.LastGPXdir = pth
    3563 
    3564     def OnFileClose(self, event):
    3565         '''Clears the data tree in response to the
    3566         File/New Project menu button. User is given option to save
    3567         the project.
    3568         '''
    3569 #        dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL)
    3570         try:
    3571             result = dlg.ShowModal()
    3572             if result == wx.ID_OK:
    3573                 self.OnFileSaveMenu(event)
    3574             if result != wx.ID_CANCEL:
    3575                 self.GSASprojectfile = ''
    3576                 self.PatternTree.SetItemText(self.root,'Loaded Data: ')
    3577                 self.PatternTree.DeleteChildren(self.root)
    3578                 if self.HKL: self.HKL = []
    3579                 if self.G2plotNB.plotList:
    3580                     self.G2plotNB.clear()
    3581         finally:
    3582             dlg.Destroy()
    3583 
    3584     def OnFileSave(self, event):
    3585         '''Save the current project in response to the
    3586         File/Save Project menu button
    3587         '''
    3588        
    3589         if self.GSASprojectfile:
    3590             self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
    3591             self.CheckNotebook()
    3592             G2IO.ProjFileSave(self)
    3593         else:
    3594             self.OnFileSaveas(event)
    3595 
    3596     def OnFileSaveas(self, event):
    3597         '''Save the current project in response to the
    3598         File/Save as menu button
    3599         '''
    3600         if GSASIIpath.GetConfigValue('Starting_directory'):
    3601             pth = GSASIIpath.GetConfigValue('Starting_directory')
    3602             pth = os.path.expanduser(pth)
    3603         elif self.LastGPXdir:
    3604             pth = self.LastGPXdir
    3605         else:
    3606             pth = '.'
    3607         dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', pth, '',
    3608             'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
    3609         try:
    3610             if dlg.ShowModal() == wx.ID_OK:
    3611                 self.GSASprojectfile = dlg.GetPath()
    3612                 self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
    3613                 self.PatternTree.SetItemText(self.root,'Saving project as'+self.GSASprojectfile)
    3614                 self.SetTitle("GSAS-II data tree: "+os.path.split(self.GSASprojectfile)[1])
    3615                 self.CheckNotebook()
    3616                 G2IO.ProjFileSave(self)
    3617                 os.chdir(dlg.GetDirectory())           # to get Mac/Linux to change directory!
    3618         finally:
    3619             dlg.Destroy()
    3620            
    3621     def ExpandAll(self,event):
    3622         '''Expand all tree items or those of a single type
    3623         '''
    3624         txt = self.GetMenuBar().GetLabel(event.Id)
    3625         if txt == 'all':
    3626             self.ExpandingAll = True
    3627             try:
    3628                 self.PatternTree.ExpandAll()
    3629             finally:
    3630                 self.ExpandingAll = False
    3631         else:
    3632             self.ExpandingAll = True
    3633             try:
    3634                 item, cookie = self.PatternTree.GetFirstChild(self.root)
    3635                 while item:
    3636                     name = self.PatternTree.GetItemText(item)
    3637                     if name.startswith(txt+' '): self.PatternTree.Expand(item)
    3638                     item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3639             finally:
    3640                 self.ExpandingAll = False
    3641 
    3642     def MoveTreeItems(self,event):
    3643         '''Move tree items of a single type to the end of the tree
    3644         '''
    3645         txt = self.GetMenuBar().GetLabel(event.Id)
    3646         # make a list of items to copy
    3647         copyList = []
    3648         item, cookie = self.PatternTree.GetFirstChild(self.root)
    3649         while item:
    3650             if self.PatternTree.GetItemText(item).startswith(txt+' '):
    3651                 copyList.append(item)
    3652             item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3653        
    3654         self.ExpandingAll = True
    3655         try:
    3656             for item in copyList:
    3657                 name = self.PatternTree.GetItemText(item)
    3658                 newId = self.PatternTree.AppendItem(self.root,name)
    3659                 self.PatternTree.SetItemPyData(newId,self.PatternTree.GetItemPyData(item))
    3660                 chld, chldcookie = self.PatternTree.GetFirstChild(item)
    3661                 while chld:
    3662                     chname = self.PatternTree.GetItemText(chld)
    3663                     newCh = self.PatternTree.AppendItem(newId,chname)
    3664                     self.PatternTree.SetItemPyData(newCh,self.PatternTree.GetItemPyData(chld))
    3665                     chld, chldcookie = self.PatternTree.GetNextChild(item, chldcookie)
    3666                 self.PatternTree.Delete(item)
    3667         finally:
    3668             self.ExpandingAll = False
    3669         G2gd.SelectDataTreeItem(self,self.root)
    3670            
    3671     def ExitMain(self, event):
    3672         '''Called if the main window is closed'''
    3673         if self.G2plotNB:
    3674             self.G2plotNB.Destroy()
    3675         if self.dataFrame:
    3676             self.dataFrame.Destroy()
    3677         if self.undofile:
    3678             os.remove(self.undofile)
    3679         sys.exit()
    3680        
    3681     def OnFileExit(self, event):
    3682         '''Called in response to the File/Quit menu button'''
    3683         if self.G2plotNB:
    3684             self.G2plotNB.Destroy()
    3685         if self.dataFrame:
    3686             self.dataFrame.Destroy()
    3687         self.Close()
    3688        
    3689     def OnExportPeakList(self,event):
    3690         nptand = lambda x: np.tan(x*math.pi/180.)
    3691         pth = G2G.GetExportPath(self)
    3692         dlg = wx.FileDialog(self, 'Choose output peak list file name', pth, '',
    3693             '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
    3694         try:
    3695             if dlg.ShowModal() == wx.ID_OK:
    3696                 self.peaklistfile = dlg.GetPath()
    3697                 self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile)
    3698                 file = open(self.peaklistfile,'w')               
    3699                 item, cookie = self.PatternTree.GetFirstChild(self.root)
    3700                 while item:
    3701                     name = self.PatternTree.GetItemText(item)
    3702                     if 'PWDR' in name:
    3703                         item2, cookie2 = self.PatternTree.GetFirstChild(item)
    3704                         wave = 0.0
    3705                         while item2:
    3706                             name2 = self.PatternTree.GetItemText(item2)
    3707                             if name2 == 'Instrument Parameters':
    3708                                 Inst = self.PatternTree.GetItemPyData(item2)[0]
    3709                                 Type = Inst['Type'][0]
    3710                                 if 'T' not in Type:
    3711                                     wave = G2mth.getWave(Inst)
    3712                             elif name2 == 'Peak List':
    3713                                 pkdata = self.PatternTree.GetItemPyData(item2)
    3714                                 peaks = pkdata['peaks']
    3715                                 sigDict = pkdata['sigDict']
    3716                             item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
    3717                         file.write("#%s \n" % (name+' Peak List'))
    3718                         if wave:
    3719                             file.write('#wavelength = %10.6f\n'%(wave))
    3720                         if 'T' in Type:
    3721                             file.write('#%9s %10s %10s %12s %10s %10s %10s %10s %10s\n'%('pos','dsp','esd','int','alp','bet','sig','gam','FWHM'))                                   
    3722                         else:
    3723                             file.write('#%9s %10s %10s %12s %10s %10s %10s\n'%('pos','dsp','esd','int','sig','gam','FWHM'))
    3724                         for ip,peak in enumerate(peaks):
    3725                             dsp = G2lat.Pos2dsp(Inst,peak[0])
    3726                             if 'T' in Type:  #TOF - more cols
    3727                                 esds = {'pos':0.,'int':0.,'alp':0.,'bet':0.,'sig':0.,'gam':0.}
    3728                                 for name in esds.keys():
    3729                                     esds[name] = sigDict.get('%s%d'%(name,ip),0.)
    3730                                 sig = np.sqrt(peak[8])
    3731                                 gam = peak[10]
    3732                                 esddsp = G2lat.Pos2dsp(Inst,esds['pos'])
    3733                                 FWHM = G2pwd.getgamFW(gam,sig)      #to get delta-TOF from Gam(peak)
    3734                                 file.write("%10.2f %10.5f %10.5f %12.2f %10.3f %10.3f %10.3f %10.3f %10.3f\n" % \
    3735                                     (peak[0],dsp,esddsp,peak[2],np.sqrt(max(0.0001,peak[4])),peak[6],peak[8],peak[10],FWHM))
    3736                             else:               #CW
    3737                                 #get esds from sigDict for each peak & put in output - esds for sig & gam from UVWXY?
    3738                                 esds = {'pos':0.,'int':0.,'sig':0.,'gam':0.}
    3739                                 for name in esds.keys():
    3740                                     esds[name] = sigDict.get('%s%d'%(name,ip),0.)
    3741                                 sig = np.sqrt(peak[4]) #var -> sig
    3742                                 gam = peak[6]
    3743                                 esddsp = 0.5*esds['pos']*dsp/nptand(peak[0]/2.)
    3744                                 FWHM = G2pwd.getgamFW(gam,sig)      #to get delta-2-theta in deg. from Gam(peak)
    3745                                 file.write("%10.4f %10.5f %10.5f %12.2f %10.5f %10.5f %10.5f \n" % \
    3746                                     (peak[0],dsp,esddsp,peak[2],np.sqrt(max(0.0001,peak[4]))/100.,peak[6]/100.,FWHM/100.)) #convert to deg
    3747                     item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
    3748                 file.close()
    3749         finally:
    3750             dlg.Destroy()
    3751        
    3752     def OnExportHKL(self,event):
    3753         pth = G2G.GetExportPath(self)
    3754         dlg = wx.FileDialog(self, 'Choose output reflection list file name', pth, '',
    3755             '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
    3756         try:
    3757             if dlg.ShowModal() == wx.ID_OK:
    3758                 self.peaklistfile = dlg.GetPath()
    3759                 self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile)
    3760                 file = open(self.peaklistfile,'w')               
    3761                 item, cookie = self.PatternTree.GetFirstChild(self.root)
    3762                 while item:
    3763                     name = self.PatternTree.GetItemText(item)
    3764                     if 'PWDR' in name:
    3765                         item2, cookie2 = self.PatternTree.GetFirstChild(item)
    3766                         while item2:
    3767                             name2 = self.PatternTree.GetItemText(item2)
    3768                             if name2 == 'Reflection Lists':
    3769                                 data = self.PatternTree.GetItemPyData(item2)
    3770                                 phases = data.keys()
    3771                                 for phase in phases:
    3772                                     peaks = data[phase]
    3773                                     I100 = peaks['RefList'].T[8]*np.array([refl[11] for refl in peaks['RefList']])
    3774                                     Imax = np.max(I100)
    3775                                     if Imax:
    3776                                         I100 *= 100.0/Imax
    3777                                     file.write("%s %s %s \n" % (name,phase,' Reflection List'))
    3778                                     if 'T' in peaks.get('Type','PXC'):
    3779                                         file.write('%s \n'%('   h   k   l   m   d-space       TOF       wid     Fo**2     Fc**2     Icorr      Prfo     Trans      ExtP      I100'))
    3780                                     else:               
    3781                                         file.write('%s \n'%('   h   k   l   m   d-space   2-theta       wid     Fo**2     Fc**2     Icorr      Prfo     Trans      ExtP      I100'))
    3782                                     for ipk,peak in enumerate(peaks['RefList']):
    3783                                         if 'T' in peaks.get('Type','PXC'):
    3784                                             sig = np.sqrt(peak[6])
    3785                                             gam = peak[7]
    3786                                             FWHM = G2pwd.getgamFW(gam,sig)
    3787                                             file.write(" %3d %3d %3d %3d%10.5f%10.2f%10.5f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" % \
    3788                                                 (int(peak[0]),int(peak[1]),int(peak[2]),int(peak[3]),peak[4],peak[5],FWHM,peak[8],
    3789                                                 peak[9],peak[11],peak[12],peak[13],peak[14],I100[ipk]))
    3790                                         else:
    3791                                             sig = np.sqrt(peak[6])
    3792                                             gam = peak[7]
    3793                                             FWHM = G2pwd.getgamFW(gam,sig)
    3794                                             file.write(" %3d %3d %3d %3d%10.5f%10.5f%10.5f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" % \
    3795                                                 (int(peak[0]),int(peak[1]),int(peak[2]),int(peak[3]),peak[4],peak[5],FWHM/100.,
    3796                                                 peak[8],peak[9],peak[11],peak[12],peak[13],peak[14],I100[ipk]))
    3797                             item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
    3798                     item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
    3799                 file.close()
    3800         finally:
    3801             dlg.Destroy()
    3802        
    3803     def OnExportPDF(self,event):
    3804         #need S(Q) and G(R) to be saved here - probably best from selection?
    3805         names = G2pdG.GetFileList(self,'PDF')
    3806         exports = []
    3807         if names:
    3808             od = {'label_1':'Export I(Q)','value_1':False,'label_2':'Export S(Q)','value_2':False,
    3809                   'label_3':'Export F(Q)','value_3':False,'label_4':'Export G(R)','value_4':True,
    3810                   'label_5':'Make G(R) for pdfGUI','value_5':False}
    3811             dlg = G2G.G2MultiChoiceDialog(self,'Select','PDF patterns to export',names,extraOpts=od)
    3812             if dlg.ShowModal() == wx.ID_OK:
    3813                 sel = dlg.GetSelections()
    3814                 for x in sel:
    3815                     exports.append(names[x])
    3816             dlg.Destroy()
    3817         if exports:
    3818             PDFsaves = [od['value_1'],od['value_2'],od['value_3'],od['value_4'],od['value_5']]
    3819             G2IO.PDFSave(self,exports,PDFsaves)
    3820        
    3821     def OnMakePDFs(self,event):
    3822         '''Sets up PDF data structure filled with defaults; if found chemical formula is inserted
    3823         so a default PDF can be made.
    3824         '''
    3825         sind = lambda x: math.sin(x*math.pi/180.)
    3826         tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
    3827         tof2q = lambda t,C:2.0*math.pi*C/t
    3828         TextList = []
    3829         ElLists = []
    3830         Qlimits = []
    3831         Names = []
    3832         if self.PatternTree.GetCount():
    3833             id, cookie = self.PatternTree.GetFirstChild(self.root)
    3834             while id:
    3835                 name = self.PatternTree.GetItemText(id)
    3836                 Names.append(name)
    3837                 if 'PWDR' in name:
    3838                     TextList.append(name)
    3839                     Data = self.PatternTree.GetItemPyData(id)[1]
    3840                     pwdrMin = np.min(Data[1])
    3841                     Comments = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,id,'Comments'))
    3842                     Parms = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,id,'Instrument Parameters'))[0]
    3843                     fullLimits = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,id,'Limits'))[0]
    3844                     if 'C' in Parms['Type'][0]:
    3845                         wave = G2mth.getWave(Parms)
    3846                         qMax = tth2q(fullLimits[1],wave)
    3847                     else:   #'T'of
    3848                         qMax = tof2q(fullLimits[0],Parms['difC'][1])
    3849                     Qlimits.append([0.9*qMax,qMax])
    3850                     ElList = {}
    3851                     sumnum = 1.
    3852                     for item in Comments:           #grab chemical formula from Comments
    3853                         if 'formula' in item[:15].lower():
    3854                             formula = item.split('=')[1].split()
    3855                             try:
    3856                                 elems = formula[::2]
    3857                                 nums = formula[1::2]
    3858                                 Formula = zip(elems,nums)
    3859                                 sumnum = 0.
    3860                                 for [elem,num] in Formula:
    3861                                     ElData = G2elem.GetElInfo(elem,Parms)
    3862                                     ElData['FormulaNo'] = float(num)
    3863                                     sumnum += float(num)
    3864                                     ElList[elem] = ElData
    3865                                
    3866                             except ValueError:
    3867                                 ElData = G2elem.GetElInfo(formula[0],Parms)
    3868                                 ElData['FormulaNo'] = 1.0
    3869                                 ElList[elem] = ElData
    3870                     ElLists.append(ElList)
    3871                 id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
    3872             if len(TextList) < 1:
    3873                 self.ErrorDialog('Nothing to make PDFs for','There must be at least one "PWDR" pattern')
    3874                 return
    3875             dlg = G2G.G2MultiChoiceDialog(self,'Make PDF controls','Make PDF controls for:',TextList, wx.CHOICEDLG_STYLE)
    3876             try:
    3877                 if dlg.ShowModal() == wx.ID_OK:
    3878                     for i in dlg.GetSelections():
    3879                         PDFnames = G2gd.GetPatternTreeDataNames(self,['PDF ',])
    3880                         G2obj.CreatePDFitems(self,TextList[i],ElLists[i],Qlimits[i],sumnum,pwdrMin,PDFnames)
    3881                 for item in self.ExportPDF: item.Enable(True)
    3882             finally:
    3883                 dlg.Destroy()
    3884                
    3885     def GetPWDRdatafromTree(self,PWDRname):
    3886         ''' Returns powder data from GSASII tree
    3887 
    3888         :param str PWDRname: a powder histogram name as obtained from
    3889           :meth:`GSASIIstruct.GetHistogramNames`
    3890 
    3891         :returns: PWDRdata = powder data dictionary with
    3892           Powder data arrays, Limits, Instrument Parameters,
    3893           Sample Parameters           
    3894         '''
    3895         PWDRdata = {}
    3896         try:
    3897             PWDRdata.update(self.PatternTree.GetItemPyData(PWDRname)[0])            #wtFactor + ?
    3898         except ValueError:
    3899             PWDRdata['wtFactor'] = 1.0
    3900         PWDRdata['Data'] = self.PatternTree.GetItemPyData(PWDRname)[1]          #powder data arrays
    3901         PWDRdata['Limits'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Limits'))
    3902         PWDRdata['Background'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Background'))
    3903         PWDRdata['Instrument Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Instrument Parameters'))
    3904         PWDRdata['Sample Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Sample Parameters'))
    3905         PWDRdata['Reflection Lists'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Reflection Lists'))
    3906         if 'ranId' not in PWDRdata:  # patch, add a random Id
    3907             PWDRdata['ranId'] = ran.randint(0,sys.maxint)
    3908         if 'ranId' not in PWDRdata['Sample Parameters']:  # I hope this becomes obsolete at some point
    3909             PWDRdata['Sample Parameters']['ranId'] = PWDRdata['ranId']
    3910         return PWDRdata
    3911 
    3912     def GetHKLFdatafromTree(self,HKLFname):
    3913         ''' Returns single crystal data from GSASII tree
    3914 
    3915         :param str HKLFname: a single crystal histogram name as obtained
    3916           from
    3917           :meth:`GSASIIstruct.GetHistogramNames`
    3918 
    3919         :returns: HKLFdata = single crystal data list of reflections
    3920 
    3921         '''
    3922         HKLFdata = {}
    3923         HKLFdata.update(self.PatternTree.GetItemPyData(HKLFname)[0])            #wtFactor + ?
    3924 #        try:
    3925 #            HKLFdata.update(self.PatternTree.GetItemPyData(HKLFname)[0])            #wtFactor + ?
    3926 #        except ValueError:
    3927 #            HKLFdata['wtFactor'] = 1.0
    3928         HKLFdata['Data'] = self.PatternTree.GetItemPyData(HKLFname)[1]
    3929         HKLFdata['Instrument Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,HKLFname,'Instrument Parameters'))
    3930         return HKLFdata
    3931        
    3932     def GetPhaseData(self):
    3933         '''Returns a dict with defined phases.
    3934         Note routine :func:`GSASIIstrIO.GetPhaseData` also exists to
    3935         get same info from GPX file.
    3936         '''
    3937         phaseData = {}
    3938         if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
    3939             sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    3940         else:
    3941             print 'no phases found in GetPhaseData'
    3942             sub = None
    3943         if sub:
    3944             item, cookie = self.PatternTree.GetFirstChild(sub)
    3945             while item:
    3946                 phaseName = self.PatternTree.GetItemText(item)
    3947                 phaseData[phaseName] =  self.PatternTree.GetItemPyData(item)
    3948                 if 'ranId' not in phaseData[phaseName]:
    3949                     phaseData[phaseName]['ranId'] = ran.randint(0,sys.maxint)         
    3950                 item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    3951         return phaseData
    3952 
    3953     def GetPhaseInfofromTree(self):
    3954         '''Get the phase names and their rId values,
    3955         also the histograms used in each phase.
    3956 
    3957         :returns: (phaseRIdList, usedHistograms) where
    3958 
    3959           * phaseRIdList is a list of random Id values for each phase
    3960           * usedHistograms is a dict where the keys are the phase names
    3961             and the values for each key are a list of the histogram names
    3962             used in each phase.
    3963         '''
    3964         phaseRIdList = []
    3965         usedHistograms = {}
    3966         sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    3967         if sub:
    3968             item, cookie = self.PatternTree.GetFirstChild(sub)
    3969             while item:
    3970                 phaseName = self.PatternTree.GetItemText(item)
    3971                 ranId = self.PatternTree.GetItemPyData(item).get('ranId')
    3972                 if ranId: phaseRIdList.append(ranId)
    3973                 data = self.PatternTree.GetItemPyData(item)
    3974                 UseList = data['Histograms']
    3975                 usedHistograms[phaseName] = UseList.keys()
    3976                 item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    3977         return phaseRIdList,usedHistograms
    3978 
    3979     def GetPhaseNames(self):
    3980         '''Returns a list of defined phases.
    3981         Note routine :func:`GSASIIstrIO.GetPhaseNames` also exists to
    3982         get same info from GPX file.
    3983         '''
    3984         phaseNames = []
    3985         if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
    3986             sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
    3987         else:
    3988             print 'no phases found in GetPhaseNames'
    3989             sub = None
    3990         if sub:
    3991             item, cookie = self.PatternTree.GetFirstChild(sub)
    3992             while item:
    3993                 phase = self.PatternTree.GetItemText(item)
    3994                 phaseNames.append(phase)
    3995                 item, cookie = self.PatternTree.GetNextChild(sub, cookie)
    3996         return phaseNames
    3997    
    3998     def GetHistogramNames(self,hType):
    3999         """ Returns a list of histogram names found in the GSASII data tree
    4000         Note routine :func:`GSASIIstrIO.GetHistogramNames` also exists to
    4001         get same info from GPX file.
    4002        
    4003         :param str hType: list of histogram types
    4004         :return: list of histogram names
    4005        
    4006         """
    4007         HistogramNames = []
    4008         if self.PatternTree.GetCount():
    4009             item, cookie = self.PatternTree.GetFirstChild(self.root)
    4010             while item:
    4011                 name = self.PatternTree.GetItemText(item)
    4012                 if name[:4] in hType:
    4013                     HistogramNames.append(name)       
    4014                 item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
    4015 
    4016         return HistogramNames
    4017                    
    4018     def GetUsedHistogramsAndPhasesfromTree(self):
    4019         ''' Returns all histograms that are found in any phase
    4020         and any phase that uses a histogram.
    4021         This also assigns numbers to used phases and histograms by the
    4022         order they appear in the file.
    4023         Note routine :func:`GSASIIstrIO.GetUsedHistogramsAndPhasesfromTree` also exists to
    4024         get same info from GPX file.
    4025 
    4026         :returns: (Histograms,Phases)
    4027 
    4028             * Histograms = dictionary of histograms as {name:data,...}
    4029             * Phases = dictionary of phases that use histograms
    4030         '''
    4031         Histograms = {}
    4032         Phases = {}
    4033         phaseNames = self.GetPhaseNames()
    4034         phaseData = self.GetPhaseData()
    4035         histoList = self.GetHistogramNames(['PWDR','HKLF'])
    4036 
    4037         for phase in phaseData:
    4038             Phase = phaseData[phase]
    4039             pId = phaseNames.index(phase)
    4040             Phase['pId'] = pId
    4041             if Phase['Histograms']:
    4042                 if phase not in Phases:
    4043                     Phases[phase] = Phase
    4044                 for hist in Phase['Histograms']:
    4045                     if 'Use' not in Phase['Histograms'][hist]:      #patch: add Use flag as True
    4046                         Phase['Histograms'][hist]['Use'] = True         
    4047                     if hist not in Histograms and Phase['Histograms'][hist]['Use']:
    4048                         item = G2gd.GetPatternTreeItemId(self,self.root,hist)
    4049                         if item:
    4050                             if 'PWDR' in hist[:4]:
    4051                                 Histograms[hist] = self.GetPWDRdatafromTree(item)
    4052                             elif 'HKLF' in hist[:4]:
    4053                                 Histograms[hist] = self.GetHKLFdatafromTree(item)
    4054                             hId = histoList.index(hist)
    4055                             Histograms[hist]['hId'] = hId
    4056                         else: # would happen if a referenced histogram were renamed or deleted
    4057                             print('For phase "'+phase+
    4058                                   '" unresolved reference to histogram "'+hist+'"')
    4059         #G2obj.IndexAllIds(Histograms=Histograms,Phases=Phases)
    4060         G2obj.IndexAllIds(Histograms=Histograms,Phases=phaseData)
    4061         return Histograms,Phases
    4062        
    4063     def MakeLSParmDict(self):
    4064         '''Load all parameters used for computation from the tree into a
    4065         dict of paired values [value, refine flag]. Note that this is
    4066         different than the parmDict used in the refinement, which only has
    4067         values.
    4068 
    4069         Note that similar things are done in
    4070         :meth:`GSASIIIO.ExportBaseclass.loadParmDict` (from the tree) and
    4071         :func:`GSASIIstrMain.Refine` and :func:`GSASIIstrMain.SeqRefine` (from
    4072         a GPX file).
    4073 
    4074         :returns: (parmDict,varyList) where:
    4075 
    4076          * parmDict is a dict with values and refinement flags
    4077            for each parameter and
    4078          * varyList is a list of variables (refined parameters).
    4079         '''
    4080         parmDict = {}
    4081         Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree()
    4082         for phase in Phases:
    4083             if 'pId' not in Phases[phase]:
    4084                 self.ErrorDialog('View parameter error','You must run least squares at least once')
    4085                 raise Exception,'No pId for phase '+phase
    4086         rigidbodyDict = self.PatternTree.GetItemPyData(   
    4087             G2gd.GetPatternTreeItemId(self,self.root,'Rigid bodies'))
    4088         rbVary,rbDict = G2stIO.GetRigidBodyModels(rigidbodyDict,Print=False)
    4089         rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})
    4090         Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable,MFtable,maxSSwave = G2stIO.GetPhaseData(Phases,RestraintDict=None,rbIds=rbIds,Print=False)       
    4091         hapVary,hapDict,controlDict = G2stIO.GetHistogramPhaseData(Phases,Histograms,Print=False)
    4092         histVary,histDict,controlDict = G2stIO.GetHistogramData(Histograms,Print=False)
    4093         varyList = rbVary+phaseVary+hapVary+histVary
    4094         parmDict.update(rbDict)
    4095         parmDict.update(phaseDict)
    4096         parmDict.update(hapDict)
    4097         parmDict.update(histDict)
    4098         for parm in parmDict:
    4099             if parm.split(':')[-1] in ['Azimuth','Gonio. radius','Lam1','Lam2',
    4100                 'Omega','Chi','Phi','nDebye','nPeaks']:
    4101                 parmDict[parm] = [parmDict[parm],'-']
    4102             elif parm.split(':')[-2] in ['Ax','Ay','Az','SHmodel','SHord']:
    4103                 parmDict[parm] = [parmDict[parm],'-']
    4104             elif parm in varyList:
    4105                 parmDict[parm] = [parmDict[parm],'T']
    4106             else:
    4107                 parmDict[parm] = [parmDict[parm],'F']
    4108         # for i in parmDict: print i,'\t',parmDict[i]
    4109         # fl = open('parmDict.dat','wb')
    4110         # import cPickle
    4111         # cPickle.dump(parmDict,fl,1)
    4112         # fl.close()
    4113         return parmDict,varyList
    4114 
    4115     def OnShowLSParms(self,event):
    4116         '''Displays a window showing all parameters in the refinement.
    4117         Called from the Calculate/View LS Parms menu.
    4118         '''
    4119         try:
    4120             parmDict,varyList = self.MakeLSParmDict()
    4121         except:
    4122             print('Error retrieving parameters')
    4123             return
    4124         parmValDict = {}
    4125         for i in parmDict:
    4126             parmValDict[i] = parmDict[i][0]
    4127            
    4128         reqVaryList = tuple(varyList) # save requested variables
    4129         try:
    4130             # process constraints
    4131             sub = G2gd.GetPatternTreeItemId(self,self.root,'Constraints')
    4132             Constraints = self.PatternTree.GetItemPyData(sub)
    4133             constList = []
    4134             for item in Constraints:
    4135                 if item.startswith('_'): continue
    4136                 constList += Constraints[item]
    4137             G2mv.InitVars()
    4138             constrDict,fixedList,ignored = G2stIO.ProcessConstraints(constList)
    4139             groups,parmlist = G2mv.GroupConstraints(constrDict)
    4140             G2mv.GenerateConstraints(groups,parmlist,varyList,constrDict,fixedList,parmValDict)
    4141             G2mv.Map2Dict(parmValDict,varyList)
    4142         except:
    4143             pass
    4144         dlg = G2gd.ShowLSParms(self,'Least Squares Parameters',parmValDict,varyList,reqVaryList)
    4145         dlg.ShowModal()
    4146         dlg.Destroy()
    4147 
    4148     def OnRefine(self,event):
    4149         '''Perform a refinement.
    4150         Called from the Calculate/Refine menu.
    4151         '''
    4152         Id = G2gd.GetPatternTreeItemId(self,self.root,'Sequential results')
    4153         if Id:
    4154             dlg = wx.MessageDialog(
    4155                 self,
    4156                 'Your last refinement was sequential. Continue with "Refine", removing previous sequential results?',
    4157                 'Remove sequential results?',wx.OK|wx.CANCEL)
    4158             if dlg.ShowModal() == wx.ID_OK:
    4159                 self.PatternTree.Delete(Id)
    4160                 dlg.Destroy()
    4161             else:
    4162                 dlg.Destroy()
    4163                 return
    4164         self.OnFileSave(event)
    4165         # check that constraints are OK here
    4166         errmsg, warnmsg = G2stIO.ReadCheckConstraints(self.GSASprojectfile)
    4167         if errmsg:
    4168             self.ErrorDialog('Refinement error',errmsg)
    4169             return
    4170         if warnmsg:
    4171             print('Conflict between refinment flag settings and constraints:\n'+
    4172                 warnmsg+'\nRefinement not possible')
    4173             self.ErrorDialog('Refinement Flag Error',
    4174                 'Conflict between refinement flag settings and constraints:\n'+
    4175                 warnmsg+'\nRefinement not possible')
    4176             return
    4177         dlg = wx.ProgressDialog('Residual','All data Rw =',101.0,
    4178             style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT,
    4179             parent=self)
    4180         Size = dlg.GetSize()
    4181         if 50 < Size[0] < 500: # sanity check on size, since this fails w/Win & wx3.0
    4182             dlg.SetSize((int(Size[0]*1.2),Size[1])) # increase size a bit along x
    4183         dlg.CenterOnParent()
    4184         Rw = 100.00
    4185         self.SaveTreeSetting()
    4186         self.PatternTree.SaveExposedItems()       
    4187         try:
    4188             OK,Msg = G2stMn.Refine(self.GSASprojectfile,dlg)    #Msg is Rvals dict if Ok=True
    4189         finally:
    4190             dlg.Update(101.) # forces the Auto_Hide; needed after move w/Win & wx3.0
    4191             dlg.Destroy()
    4192             wx.Yield()
    4193         if OK:
    4194             Rw = Msg['Rwp']
    4195             lamMax = Msg.get('lamMax',0.001)
    4196             lst = os.path.splitext(os.path.abspath(self.GSASprojectfile))[0]
    4197             text = u'Detailed results are in '+lst+'.lst\n\nLoad new result?'
    4198             if lamMax >= 10.:
    4199                 text += '\nWARNING: Steepest descents dominates;'+   \
    4200                 ' minimum may not have been reached\nor result may be false minimum.'+  \
    4201                 ' You should reconsider your parameter suite'
    4202             dlg2 = wx.MessageDialog(self,text,'Refinement results, Rw =%.3f'%(Rw),wx.OK|wx.CANCEL)
    4203             try:
    4204                 if dlg2.ShowModal() == wx.ID_OK:
    4205                     self.PatternTree.DeleteChildren(self.root)
    4206                     self.HKL = []
    4207                     G2IO.ProjFileOpen(self,False)
    4208                     self.PatternTree.RestoreExposedItems()       
    4209                     self.ResetPlots()
    4210             finally:
    4211                 dlg2.Destroy()
    4212         else:
    4213             self.ErrorDialog('Refinement error',Msg)
    4214        
    4215     def SaveTreeSetting(self):
    4216         'Save the last tree setting'
    4217         oldId =  self.PatternTree.GetSelection()        #retain current selection
    4218         oldPath = self.GetTreeItemsList(oldId)
    4219         self.lastTreeSetting = oldPath
    4220         # note that for reasons unclear, it does not seem necessary to reload the Atoms tab
    4221         #parentName = ''
    4222         #tabId = None
    4223         # parentId = self.PatternTree.GetItemParent(oldId)
    4224         # if parentId:
    4225         #     parentName = self.PatternTree.GetItemText(parentId)     #find the current data tree name
    4226         #     if 'Phases' in parentName:
    4227         #         tabId = self.dataDisplay.GetSelection()
    4228         #self.lastTreeSetting = oldPath,tabId
    4229         #GSASIIpath.IPyBreak()
    4230        
    4231     def TestResetPlot(self,event):
    4232         '''Debug code to test cleaning up plots after a refinement'''
    4233         #for i in range(self.G2plotNB.nb.GetPageCount()):
    4234         #    [self.G2plotNB.nb.GetPageText(i)
    4235         # save current tree item and (if needed) atoms tab
    4236         self.SaveTreeSetting()
    4237         self.ResetPlots()
    4238        
    4239     def ResetPlots(self):
    4240         '''This reloads the current tree item, often drawing a plot. It refreshes any plots
    4241         that have registered a refresh routine (see G2plotNB.RegisterRedrawRoutine)
    4242         and deletes all plots that have not been refreshed and
    4243         require one (see G2plotNB.SetNoDelete).
    4244         '''
    4245         lastRaisedPlotTab = self.G2plotNB.lastRaisedPlotTab # save the last page saved
    4246         #print 'lastRaisedPlotTab=',lastRaisedPlotTab
    4247         self.G2plotNB.lastRaisedPlotTab = None
    4248         # mark displayed plots as invalid
    4249         for lbl,frame in zip(self.G2plotNB.plotList,self.G2plotNB.panelList):
    4250             frame.plotInvalid = True
    4251         # reload current tree item, triggering the routine to redraw the data window and possibly a plot
    4252         #oldPath,tabId = self.lastTreeSetting
    4253         oldPath = self.lastTreeSetting
    4254         Id = self.root
    4255         for txt in oldPath:
    4256             Id = G2gd.GetPatternTreeItemId(self, Id, txt)
    4257         self.PickIdText = None  #force reload of page
    4258         if Id:
    4259             self.PickId = Id
    4260             self.PatternTree.SelectItem(Id)
    4261         # update other self-updating plots
    4262 #        for lbl,frame in zip(self.G2plotNB.plotList,self.G2plotNB.panelList):
    4263 #            if frame.plotInvalid and frame.replotFunction:
    4264 #                frame.replotFunction(*frame.replotArgs,**frame.replotKWargs)
    4265         # delete any remaining plots that are still invalid and need a refresh
    4266         for lbl,frame in zip(self.G2plotNB.plotList,self.G2plotNB.panelList):
    4267             if frame.plotInvalid and frame.plotRequiresRedraw:
    4268                 self.G2plotNB.Delete(lbl)
    4269         # put the previously last-raised tab on top, if present. If not, use the one corresponding to
    4270         # the last tree item to be selected
    4271         wx.CallAfter(self.G2plotNB.RaiseLastPage,lastRaisedPlotTab,self.G2plotNB.lastRaisedPlotTab)
    4272        
    4273     def OnSeqRefine(self,event):
    4274         '''Perform a sequential refinement.
    4275         Called from the Calculate/Sequential refine menu.
    4276         '''
    4277         Id = G2gd.GetPatternTreeItemId(self,self.root,'Sequential results')
    4278         if not Id:
    4279             Id = self.PatternTree.AppendItem(self.root,text='Sequential results')
    4280             self.PatternTree.SetItemPyData(Id,{})           
    4281         self.G2plotNB.Delete('Sequential refinement')    #clear away probably invalid plot
    4282         Controls = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.root, 'Controls'))
    4283         if not Controls.get('Seq Data'):
    4284             print('Error: a sequential refinement has not been set up')
    4285             return
    4286         Controls['ShowCell'] = True
    4287         self.OnFileSave(event)
    4288         # check that constraints are OK here
    4289         errmsg, warnmsg = G2stIO.ReadCheckConstraints(self.GSASprojectfile)
    4290         if errmsg:
    4291             self.ErrorDialog('Refinement error',errmsg)
    4292             return
    4293         if warnmsg:
    4294             print('Conflict between refinment flag settings and constraints:\n'+
    4295                   warnmsg+'\nRefinement not possible')
    4296             self.ErrorDialog('Refinement Flag Error',
    4297                              'Conflict between refinment flag settings and constraints:\n'+
    4298                              warnmsg+'\nRefinement not possible')
    4299             return
    4300         self.PatternTree.SaveExposedItems()       
    4301         dlg = wx.ProgressDialog('Residual for histogram 0','Powder profile Rwp =',101.0,
    4302             style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT,
    4303             parent=self)           
    4304         Size = dlg.GetSize()
    4305         if 50 < Size[0] < 500: # sanity check on size, since this fails w/Win & wx3.0
    4306             dlg.SetSize((int(Size[0]*1.2),Size[1])) # increase size a bit along x
    4307         dlg.CenterOnParent()
    4308         try:
    4309             OK,Msg = G2stMn.SeqRefine(self.GSASprojectfile,dlg,G2plt.SequentialPlotPattern,self)     #Msg is Rvals dict if Ok=True
    4310         finally:
    4311             dlg.Update(101.) # forces the Auto_Hide; needed after move w/Win & wx3.0
    4312             dlg.Destroy()
    4313             wx.Yield()
    4314         if OK:
    4315             dlg = wx.MessageDialog(self,'Load new result?','Refinement results',wx.OK|wx.CANCEL)
    4316             try:
    4317                 if dlg.ShowModal() == wx.ID_OK:
    4318                     self.PickIdText = None  #force reload of PickId contents
    4319                     self.PatternTree.DeleteChildren(self.root)
    4320                     if len(self.HKL): self.HKL = []
    4321                     if self.G2plotNB.plotList:
    4322                         self.G2plotNB.clear()
    4323                     G2IO.ProjFileOpen(self,False)
    4324                     self.PatternTree.RestoreExposedItems()
    4325                     self.ResetPlots()
    4326                     Id = G2gd.GetPatternTreeItemId(self,self.root,'Sequential results')
    4327                     self.PatternTree.SelectItem(Id)
    4328             finally:
    4329                 dlg.Destroy()
    4330             self.SeqTblHideList = []
    4331         else:
    4332             self.ErrorDialog('Sequential refinement error',Msg)
    4333        
    4334     def ErrorDialog(self,title,message,parent=None, wtype=wx.OK):
    4335         'Display an error message'
    4336         result = None
    4337         if parent is None:
    4338             dlg = wx.MessageDialog(self, message, title,  wtype)
    4339         else:
    4340             dlg = wx.MessageDialog(parent, message, title,  wtype)
    4341             dlg.CenterOnParent() # not working on Mac
    4342         try:
    4343             result = dlg.ShowModal()
    4344         finally:
    4345             dlg.Destroy()
    4346         return result
    4347    
    4348     def OnSaveMultipleImg(self,event):
    4349         '''Select and save multiple image parameter and mask files
    4350         '''
    4351         G2IO.SaveMultipleImg(self)
    4352        
    4353 class GSASIImain(wx.App):
    4354     '''Defines a wxApp for GSAS-II
    4355 
    4356     Creates a wx frame (self.main) which contains the display of the
    4357     data tree.
    4358     '''
    4359     def OnInit(self):
    4360         '''Called automatically when the app is created.'''
    4361         import platform
    4362         if '2.7' not in sys.version[:5]:
    4363             dlg = wx.MessageDialog(None,
    4364                 'GSAS-II requires Python 2.7.x\n Yours is '+sys.version.split()[0],
    4365                 'Python version error',  wx.OK)
    4366             try:
    4367                 dlg.ShowModal()
    4368             finally:
    4369                 dlg.Destroy()
    4370             sys.exit()
    4371         self.main = GSASII(None)
    4372         self.SetTopWindow(self.main)
    4373         # save the current package versions
    4374         self.main.PackageVersions = []
    4375         self.main.PackageVersions.append(['Python',sys.version.split()[0]])
    4376         for p in (wx,mpl,np,sp,ogl):
    4377             self.main.PackageVersions.append([p.__name__,p.__version__])
    4378         try:
    4379             self.main.PackageVersions.append([Image.__name__,Image.VERSION])
    4380         except:
    4381             try:
    4382                 from PIL import PILLOW_VERSION
    4383                 self.main.PackageVersions.append([Image.__name__,PILLOW_VERSION])
    4384             except:
    4385                 pass
    4386         self.main.PackageVersions.append(['Platform',sys.platform+' '+platform.architecture()[0]+' '+platform.machine()])
    4387        
    4388         return True
    4389     # def MacOpenFile(self, filename):
    4390     #     '''Called on Mac every time a file is dropped on the app when it is running,
    4391     #     treat this like a File/Open project menu action.
    4392     #     Should be ignored on other platforms
    4393     #     '''
    4394     #     # PATCH: Canopy 1.4 script main seems dropped on app; ignore .py files
    4395     #     print 'MacOpen',filename
    4396     #     if os.path.splitext(filename)[1] == '.py': return
    4397     #     # end PATCH
    4398     #     self.main.OnFileOpen(None,filename)
    4399     # removed because this gets triggered when a file is on the command line in canopy 1.4 -- not likely used anyway
    4400        
    4401 def main():
    4402     '''Start up the GSAS-II application'''
    4403     #application = GSASIImain() # don't redirect output, someday we
    4404     # may want to do this if we can
    4405     application = GSASIImain(0)
    4406     if GSASIIpath.GetConfigValue('wxInspector'):
    4407         import wx.lib.inspection as wxeye
    4408         wxeye.InspectionTool().Show()
    4409 
    4410     #application.main.OnRefine(None)
    4411     application.SetAppDisplayName('GSAS-II')
    4412     #application.GetTopWindow().dataWindow.SendSizeEvent()
    4413     #application.GetTopWindow().treePanel.SendSizeEvent()
    4414     #application.GetTopWindow().SendSizeEvent()
    4415     application.GetTopWindow().Show(True)
    4416     application.MainLoop()
    4417    
    4418 if __name__ == '__main__':
     91    # load the GSAS routines
     92    import GSASIIpath
     93    GSASIIpath.SetVersionNumber("$Revision$")
     94    import GSASIIIO as G2IO
     95    import GSASIIElem as G2elem
     96    import GSASIIgrid as G2gd
     97    import GSASIIctrls as G2G
     98    import GSASIIplot as G2plt
     99    import GSASIIpwd as G2pwd
     100    import GSASIIpwdGUI as G2pdG
     101    import GSASIIspc as G2spc
     102    import GSASIIstrMain as G2stMn
     103    import GSASIIstrIO as G2stIO
     104    import GSASIImath as G2mth
     105    import GSASIImapvars as G2mv
     106    import GSASIIobj as G2obj
     107    import GSASIIlattice as G2lat
     108    import GSASIIlog as log
     109#                GSASIIpath.IPyBreak()
    4419110    # print versions
    4420111    print "Python module versions loaded:"
     
    4449140    print "This is GSAS-II revision "+str(GSASIIpath.GetVersionNumber())+'\n'
    4450141    GSASIIpath.InvokeDebugOpts()
    4451     main() # start the GUI
     142    G2gd.GSASIImain() # start the GUI
  • branch/2frame/GSASIIctrls.py

    r2895 r2899  
    27762776        parent.Raise()
    27772777        self.EndModal(wx.ID_OK)
     2778
     2779################################################################################
     2780class DisAglDialog(wx.Dialog):
     2781    '''Distance/Angle Controls input dialog. After
     2782    :meth:`ShowModal` returns, the results are found in
     2783    dict :attr:`self.data`, which is accessed using :meth:`GetData`.
     2784
     2785    :param wx.Frame parent: reference to parent frame (or None)
     2786    :param dict data: a dict containing the current
     2787      search ranges or an empty dict, which causes default values
     2788      to be used.
     2789      Will be used to set element `DisAglCtls` in
     2790      :ref:`Phase Tree Item <Phase_table>`
     2791    :param dict default:  A dict containing the default
     2792      search ranges for each element.
     2793    :param bool Reset: if True (default), show Reset button
     2794    :param bool Angle: if True (default), show angle radii
     2795    '''
     2796    def __init__(self,parent,data,default,Reset=True,Angle=True):
     2797        text = 'Distance Angle Controls'
     2798        if not Angle:
     2799            text = 'Distance Controls'
     2800        wx.Dialog.__init__(self,parent,wx.ID_ANY,text,
     2801            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
     2802        self.default = default
     2803        self.Reset = Reset
     2804        self.Angle = Angle
     2805        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
     2806        self._default(data,self.default)
     2807        self.Draw(self.data)
     2808               
     2809    def _default(self,data,default):
     2810        '''Set starting values for the search values, either from
     2811        the input array or from defaults, if input is null
     2812        '''
     2813        if data:
     2814            self.data = copy.deepcopy(data) # don't mess with originals
     2815        else:
     2816            self.data = {}
     2817            self.data['Name'] = default['Name']
     2818            self.data['Factors'] = [0.85,0.85]
     2819            self.data['AtomTypes'] = default['AtomTypes']
     2820            self.data['BondRadii'] = default['BondRadii'][:]
     2821            self.data['AngleRadii'] = default['AngleRadii'][:]
     2822
     2823    def Draw(self,data):
     2824        '''Creates the contents of the dialog. Normally called
     2825        by :meth:`__init__`.
     2826        '''
     2827        self.panel.Destroy()
     2828        self.panel = wx.Panel(self)
     2829        mainSizer = wx.BoxSizer(wx.VERTICAL)
     2830        mainSizer.Add(wx.StaticText(self.panel,-1,'Controls for phase '+data['Name']),
     2831            0,WACV|wx.LEFT,10)
     2832        mainSizer.Add((10,10),1)
     2833       
     2834        ncol = 3
     2835        if not self.Angle:
     2836            ncol=2
     2837        radiiSizer = wx.FlexGridSizer(0,ncol,5,5)
     2838        radiiSizer.Add(wx.StaticText(self.panel,-1,' Type'),0,WACV)
     2839        radiiSizer.Add(wx.StaticText(self.panel,-1,'Bond radii'),0,WACV)
     2840        if self.Angle:
     2841            radiiSizer.Add(wx.StaticText(self.panel,-1,'Angle radii'),0,WACV)
     2842        self.objList = {}
     2843        for id,item in enumerate(self.data['AtomTypes']):
     2844            radiiSizer.Add(wx.StaticText(self.panel,-1,' '+item),0,WACV)
     2845            bRadii = ValidatedTxtCtrl(self.panel,data['BondRadii'],id,nDig=(10,3))
     2846            radiiSizer.Add(bRadii,0,WACV)
     2847            if self.Angle:
     2848                aRadii = ValidatedTxtCtrl(self.panel,data['AngleRadii'],id,nDig=(10,3))
     2849                radiiSizer.Add(aRadii,0,WACV)
     2850        mainSizer.Add(radiiSizer,0,wx.EXPAND)
     2851        if self.Angle:
     2852            factorSizer = wx.FlexGridSizer(0,2,5,5)
     2853            Names = ['Bond','Angle']
     2854            for i,name in enumerate(Names):
     2855                factorSizer.Add(wx.StaticText(self.panel,-1,name+' search factor'),0,WACV)
     2856                bondFact = ValidatedTxtCtrl(self.panel,data['Factors'],i,nDig=(10,3))
     2857                factorSizer.Add(bondFact)
     2858            mainSizer.Add(factorSizer,0,wx.EXPAND)
     2859       
     2860        OkBtn = wx.Button(self.panel,-1,"Ok")
     2861        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
     2862        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
     2863        btnSizer.Add((20,20),1)
     2864        btnSizer.Add(OkBtn)
     2865        if self.Reset:
     2866            ResetBtn = wx.Button(self.panel,-1,'Reset')
     2867            ResetBtn.Bind(wx.EVT_BUTTON, self.OnReset)
     2868            btnSizer.Add(ResetBtn)
     2869        btnSizer.Add((20,20),1)
     2870        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
     2871        self.panel.SetSizer(mainSizer)
     2872        self.panel.Fit()
     2873        self.Fit()
     2874   
     2875    def GetData(self):
     2876        'Returns the values from the dialog'
     2877        return self.data
     2878       
     2879    def OnOk(self,event):
     2880        'Called when the OK button is pressed'
     2881        parent = self.GetParent()
     2882        parent.Raise()
     2883        self.EndModal(wx.ID_OK)             
     2884       
     2885    def OnReset(self,event):
     2886        'Called when the Reset button is pressed'
     2887        data = {}
     2888        self._default(data,self.default)
     2889        self.Draw(self.data)
     2890               
     2891################################################################################
     2892class ShowLSParms(wx.Dialog):
     2893    '''Create frame to show least-squares parameters
     2894    '''
     2895    def __init__(self,parent,title,parmDict,varyList,fullVaryList,
     2896                 size=(375,430)):
     2897       
     2898        wx.Dialog.__init__(self,parent,wx.ID_ANY,title,size=size,
     2899                           style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
     2900        self.panel = wxscroll.ScrolledPanel(self)         #just a dummy - gets destroyed in DrawPanel!
     2901        self.parmChoice = 'Phase'
     2902        self.parmDict = parmDict
     2903        self.varyList = varyList
     2904        self.fullVaryList = fullVaryList
     2905
     2906        self.parmNames = parmDict.keys()
     2907        self.parmNames.sort()
     2908        splitNames = [item.split(':') for item in self.parmNames if len(item) > 3 and not isinstance(self.parmDict[item],basestring)]
     2909        self.globNames = [':'.join(item) for item in splitNames if not item[0] and not item[1]]
     2910        self.globVars = list(set([' ',]+[item[2] for item in splitNames if not item[0] and not item[1]]))
     2911        self.globVars.sort()
     2912        self.hisNames = [':'.join(item) for item in splitNames if not item[0] and item[1]]
     2913        self.hisNums = list(set([int(item.split(':')[1]) for item in self.hisNames]))
     2914        self.hisNums.sort()
     2915        self.hisNums = [' ',]+[str(item) for item in self.hisNums]
     2916        self.hisVars = list(set([' ',]+[item[2] for item in splitNames if not item[0]]))
     2917        self.hisVars.sort()
     2918        self.phasNames = [':'.join(item) for item in splitNames if not item[1] and 'is' not in item[2]]
     2919        self.phasNums = [' ',]+list(set([item.split(':')[0] for item in self.phasNames]))
     2920        if '' in self.phasNums: self.phasNums.remove('')
     2921        self.phasVars = list(set([' ',]+[item[2] for item in splitNames if not item[1] and 'is' not in item[2]]))
     2922        self.phasVars.sort()
     2923        self.phasNums.sort()
     2924        self.hapNames = [':'.join(item) for item in splitNames if item[0] and item[1]]
     2925        self.hapVars = list(set([' ',]+[item[2] for item in splitNames if item[0] and item[1]]))
     2926        self.hapVars.sort()
     2927        self.hisNum = ' '
     2928        self.phasNum = ' '
     2929        self.varName = ' '
     2930        self.listSel = 'Refined'
     2931        self.DrawPanel()
     2932       
     2933           
     2934    def DrawPanel(self):
     2935           
     2936        def _OnParmSel(event):
     2937            self.parmChoice = parmSel.GetStringSelection()
     2938            self.varName = ' '
     2939            wx.CallLater(100,self.DrawPanel)
     2940           
     2941        def OnPhasSel(event):
     2942            event.Skip()
     2943            self.phasNum = phasSel.GetValue()
     2944            self.varName = ' '
     2945            wx.CallLater(100,self.DrawPanel)
     2946
     2947        def OnHistSel(event):
     2948            event.Skip()
     2949            self.hisNum = histSel.GetValue()
     2950            self.varName = ' '
     2951            wx.CallLater(100,self.DrawPanel)
     2952           
     2953        def OnVarSel(event):
     2954            self.varName = varSel.GetValue()
     2955            self.phasNum = ' '
     2956            self.hisNum = ' '
     2957            wx.CallLater(100,self.DrawPanel)
     2958           
     2959        def OnListSel(event):
     2960            self.listSel = listSel.GetStringSelection()
     2961            wx.CallLater(100,self.DrawPanel)
     2962
     2963        if self.panel:
     2964            #self.panel.DestroyChildren() # Bad on Mac: deletes scroll bars
     2965            sizer = self.panel.GetSizer()
     2966            if sizer: sizer.DeleteWindows()
     2967
     2968        mainSizer = wx.BoxSizer(wx.VERTICAL)
     2969        num = len(self.varyList)
     2970        mainSizer.Add(wx.StaticText(self.panel,label=' Number of refined variables: '+str(num)),0)
     2971        if len(self.varyList) != len(self.fullVaryList):
     2972            num = len(self.fullVaryList) - len(self.varyList)
     2973            mainSizer.Add(wx.StaticText(self.panel,label=' + '+str(num)+' parameters are varied via constraints'))
     2974        choiceDict = {'Global':self.globNames,'Phase':self.phasNames,'Phase/Histo':self.hapNames,'Histogram':self.hisNames}
     2975        choice = ['Phase','Phase/Histo','Histogram']
     2976        if len(self.globNames):
     2977            choice += ['Global',]
     2978        parmSizer = wx.FlexGridSizer(0,3,5,5)
     2979        parmSel = wx.RadioBox(self.panel,wx.ID_ANY,'Parameter type:',choices=choice,
     2980            majorDimension=1,style=wx.RA_SPECIFY_COLS)
     2981        parmSel.Bind(wx.EVT_RADIOBOX,_OnParmSel)
     2982        parmSel.SetStringSelection(self.parmChoice)
     2983        parmSizer.Add(parmSel,0)
     2984        numSizer = wx.BoxSizer(wx.VERTICAL)
     2985        numSizer.Add((5,25),0)
     2986        if self.parmChoice in ['Phase','Phase/Histo'] and len(self.phasNums) > 1:
     2987            numSizer.Add(wx.StaticText(self.panel,label='Phase'),0)
     2988            phasSel = wx.ComboBox(self.panel,choices=self.phasNums,value=self.phasNum,
     2989                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     2990            phasSel.Bind(wx.EVT_COMBOBOX,OnPhasSel)
     2991            numSizer.Add(phasSel,0)
     2992        if self.parmChoice in ['Histogram','Phase/Histo'] and len(self.hisNums) > 1:
     2993            numSizer.Add(wx.StaticText(self.panel,label='Histogram'),0)
     2994            histSel = wx.ComboBox(self.panel,choices=self.hisNums,value=self.hisNum,
     2995                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     2996            histSel.Bind(wx.EVT_COMBOBOX,OnHistSel)
     2997#            histSel = wx.TextCtrl(self.panel,size=(50,25),value='0',style=wx.TE_PROCESS_ENTER)
     2998#            histSel.Bind(wx.EVT_TEXT_ENTER,OnHistSel)
     2999#            histSel.Bind(wx.EVT_KILL_FOCUS,OnHistSel)
     3000            numSizer.Add(histSel,0)
     3001        parmSizer.Add(numSizer)
     3002        varSizer = wx.BoxSizer(wx.VERTICAL)
     3003        if self.parmChoice in ['Phase',]:
     3004            varSel = wx.ComboBox(self.panel,choices=self.phasVars,value=self.varName,
     3005                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     3006            varSel.Bind(wx.EVT_COMBOBOX,OnVarSel)
     3007        elif self.parmChoice in ['Histogram',]:
     3008            varSel = wx.ComboBox(self.panel,choices=self.hisVars,value=self.varName,
     3009                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     3010            varSel.Bind(wx.EVT_COMBOBOX,OnVarSel)
     3011        elif self.parmChoice in ['Phase/Histo',]:
     3012            varSel = wx.ComboBox(self.panel,choices=self.hapVars,value=self.varName,
     3013                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     3014            varSel.Bind(wx.EVT_COMBOBOX,OnVarSel)
     3015        if self.parmChoice != 'Global':
     3016            varSizer.Add(wx.StaticText(self.panel,label='Parameter'))
     3017            varSizer.Add(varSel,0)
     3018        parmSizer.Add(varSizer,0)
     3019        mainSizer.Add(parmSizer,0)
     3020        listChoice = ['All','Refined']
     3021        listSel = wx.RadioBox(self.panel,wx.ID_ANY,'Parameter type:',choices=listChoice,
     3022            majorDimension=0,style=wx.RA_SPECIFY_COLS)
     3023        listSel.SetStringSelection(self.listSel)
     3024        listSel.Bind(wx.EVT_RADIOBOX,OnListSel)
     3025        mainSizer.Add(listSel,0)
     3026        subSizer = wx.FlexGridSizer(cols=4,hgap=2,vgap=2)
     3027        subSizer.Add((-1,-1))
     3028        subSizer.Add(wx.StaticText(self.panel,wx.ID_ANY,'Parameter name  '))
     3029        subSizer.Add(wx.StaticText(self.panel,wx.ID_ANY,'refine?'))
     3030        subSizer.Add(wx.StaticText(self.panel,wx.ID_ANY,'value'),0,wx.ALIGN_RIGHT)
     3031        explainRefine = False
     3032        for name in choiceDict[self.parmChoice]:
     3033            # skip entries without numerical values
     3034            if isinstance(self.parmDict[name],basestring): continue
     3035            if 'Refined' in self.listSel and (name not in self.fullVaryList
     3036                                              ) and (name not in self.varyList):
     3037                continue
     3038            if 'Phase' in self.parmChoice:
     3039                if self.phasNum != ' ' and name.split(':')[0] != self.phasNum: continue
     3040            if 'Histo' in self.parmChoice:
     3041                if self.hisNum != ' ' and name.split(':')[1] != self.hisNum: continue
     3042            if (self.varName != ' ') and (self.varName not in name): continue
     3043            try:
     3044                value = G2py3.FormatSigFigs(self.parmDict[name])
     3045            except TypeError:
     3046                value = str(self.parmDict[name])+' -?' # unexpected
     3047                #continue
     3048            v = G2obj.getVarDescr(name)
     3049            if v is None or v[-1] is None:
     3050                subSizer.Add((-1,-1))
     3051            else:               
     3052                ch = HelpButton(self.panel,G2obj.fmtVarDescr(name))
     3053                subSizer.Add(ch,0,wx.LEFT|wx.RIGHT|WACV|wx.ALIGN_CENTER,1)
     3054            subSizer.Add(wx.StaticText(self.panel,wx.ID_ANY,str(name)))
     3055            if name in self.varyList:
     3056                subSizer.Add(wx.StaticText(self.panel,label='R'))   #TODO? maybe a checkbox for one stop refinemnt flag setting?
     3057            elif name in self.fullVaryList:
     3058                subSizer.Add(wx.StaticText(self.panel,label='C'))
     3059                explainRefine = True
     3060            else:
     3061                subSizer.Add((-1,-1))
     3062            subSizer.Add(wx.StaticText(self.panel,label=value),0,wx.ALIGN_RIGHT)
     3063
     3064        mainSizer.Add(subSizer,0)
     3065        if explainRefine:
     3066            mainSizer.Add(
     3067                wx.StaticText(self.panel,label='"R" indicates a refined variable\n'+
     3068                    '"C" indicates generated from a constraint'),0, wx.ALL,0)
     3069        # make OK button
     3070        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
     3071        btn = wx.Button(self.panel, wx.ID_CLOSE,"Close")
     3072        btn.Bind(wx.EVT_BUTTON,self._onClose)
     3073        btnsizer.Add(btn)
     3074        mainSizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 5)
     3075        # Allow window to be enlarged but not made smaller
     3076        self.panel.SetSizer(mainSizer)
     3077        self.panel.SetAutoLayout(1)
     3078        self.panel.SetupScrolling()
     3079        self.panel.SetMinSize(self.GetSize())
     3080
     3081    def _onClose(self,event):
     3082        self.EndModal(wx.ID_CANCEL)
    27783083
    27793084################################################################################
  • branch/2frame/GSASIIexprGUI.py

    r2868 r2899  
    702702        self.pName = Phases.keys()[0]
    703703        DisAglCtls = {}
    704         dlg = G2gd.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
     704        dlg = G2G.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
    705705        if dlg.ShowModal() == wx.ID_OK:
    706706            Phases[self.pName]['General']['DisAglCtls'] = dlg.GetData()
     
    717717            self.Oatom = ''
    718718            DisAglCtls = {}
    719             dlg = G2gd.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
     719            dlg = G2G.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
    720720            if dlg.ShowModal() == wx.ID_OK:
    721721                self.Phases[self.pName]['General']['DisAglCtls'] = dlg.GetData()
     
    823823        self.pName = Phases.keys()[0]
    824824        DisAglCtls = {}
    825         dlg = G2gd.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
     825        dlg = G2G.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
    826826        if dlg.ShowModal() == wx.ID_OK:
    827827            Phases[self.pName]['General']['DisAglCtls'] = dlg.GetData()
     
    838838            self.Oatom = ''
    839839            DisAglCtls = {}
    840             dlg = G2gd.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
     840            dlg = G2G.DisAglDialog(self.panel,DisAglCtls,self.Phases[self.pName]['General'],Reset=False)
    841841            if dlg.ShowModal() == wx.ID_OK:
    842842                self.Phases[self.pName]['General']['DisAglCtls'] = dlg.GetData()
  • branch/2frame/GSASIIgrid.py

    r2898 r2899  
    1313
    1414'''
     15import time
     16import math
     17import random as ran
     18import copy
     19import sys
     20import os
     21import glob
     22import random as ran
     23import imp
     24import inspect
     25import numpy as np
     26import numpy.ma as ma
     27import matplotlib as mpl
     28import OpenGL as ogl
     29import scipy as sp
     30import scipy.optimize as so
    1531import wx
    1632import wx.grid as wg
     
    1834#import wx.aui
    1935import wx.lib.scrolledpanel as wxscroll
    20 import time
    21 import copy
    22 import sys
    23 import os
    24 import random as ran
    25 import numpy as np
    26 import numpy.ma as ma
    27 import scipy.optimize as so
    2836import GSASIIpath
    2937GSASIIpath.SetVersionNumber("$Revision$")
     
    5159cosd = lambda x: np.cos(x*np.pi/180.)
    5260
    53 # Define a short name for convenience
     61# Define short names for convenience
    5462WACV = wx.ALIGN_CENTER_VERTICAL
    55 [ wxID_FOURCALC, wxID_FOURSEARCH, wxID_FOURCLEAR, wxID_PEAKSMOVE, wxID_PEAKSCLEAR,
    56     wxID_CHARGEFLIP, wxID_PEAKSUNIQUE, wxID_PEAKSDELETE, wxID_PEAKSDA,
    57     wxID_PEAKSDISTVP, wxID_PEAKSVIEWPT, wxID_FINDEQVPEAKS,wxID_SHOWBONDS,wxID_MULTIMCSA,
    58     wxID_SINGLEMCSA,wxID_4DCHARGEFLIP,wxID_TRANSFORMSTRUCTURE,
    59 ] = [wx.NewId() for item in range(17)]
    60 
    61 [ wxID_PWDRADD, wxID_HKLFADD, wxID_PWDANALYSIS, wxID_PWDCOPY, wxID_PLOTCTRLCOPY,
    62     wxID_DATADELETE,wxID_DATACOPY,wxID_DATACOPYFLAGS,wxID_DATASELCOPY,wxID_DATAUSE,
    63 ] = [wx.NewId() for item in range(10)]
    64 
    65 [ wxID_ATOMSEDITADD, wxID_ATOMSEDITINSERT, wxID_ATOMSEDITDELETE,
    66     wxID_ATOMSMODIFY, wxID_ATOMSTRANSFORM, wxID_ATOMSVIEWADD, wxID_ATOMVIEWINSERT,
    67     wxID_RELOADDRAWATOMS,wxID_ATOMSDISAGL,wxID_ATOMMOVE,wxID_MAKEMOLECULE,
    68     wxID_ASSIGNATMS2RB,wxID_ATOMSPDISAGL, wxID_ISODISP,wxID_ADDHATOM,wxID_UPDATEHATOM,
    69     wxID_WAVEVARY,wxID_ATOMSROTATE, wxID_ATOMSDENSITY, wxID_VALIDPROTEIN,
    70     wxID_ATOMSSETALL, wxID_ATOMSSETSEL,
    71 ] = [wx.NewId() for item in range(22)]
    72 
    73 [ wxID_DRAWATOMSTYLE, wxID_DRAWATOMLABEL, wxID_DRAWATOMCOLOR, wxID_DRAWATOMRESETCOLOR,
    74     wxID_DRAWVIEWPOINT, wxID_DRAWTRANSFORM, wxID_DRAWDELETE, wxID_DRAWFILLCELL,
    75     wxID_DRAWADDEQUIV, wxID_DRAWFILLCOORD, wxID_DRAWDISAGLTOR,  wxID_DRAWPLANE,
    76     wxID_DRAWDISTVP, wxID_DRAWADDSPHERE,wxID_DRWAEDITRADII,
    77 ] = [wx.NewId() for item in range(15)]
    78 
    79 [ wxID_DRAWRESTRBOND, wxID_DRAWRESTRANGLE, wxID_DRAWRESTRPLANE, wxID_DRAWRESTRCHIRAL,
    80 ] = [wx.NewId() for item in range(4)]
    81 
    82 [ wxID_ADDMCSAATOM,wxID_ADDMCSARB,wxID_CLEARMCSARB,wxID_MOVEMCSA,wxID_MCSACLEARRESULTS,
    83 ] = [wx.NewId() for item in range(5)]
    84 
    85 [ wxID_CLEARTEXTURE,wxID_REFINETEXTURE,
    86 ] = [wx.NewId() for item in range(2)]
    87 
    88 [ wxID_LOADDIFFAX,wxID_LAYERSIMULATE,wxID_SEQUENCESIMULATE, wxID_LAYERSFIT, wxID_COPYPHASE,
    89 ] = [wx.NewId() for item in range(5)]
    90 
    91 [ wxID_PAWLEYLOAD, wxID_PAWLEYESTIMATE, wxID_PAWLEYUPDATE, wxID_PAWLEYSELALL, wxID_PAWLEYSELNONE,
    92   wxID_PAWLEYSELTOGGLE, wxID_PAWLEYSET,
    93 ] = [wx.NewId() for item in range(7)]
    94 
    95 [ wxID_IMCALIBRATE,wxID_IMRECALIBRATE,wxID_IMINTEGRATE, wxID_IMCLEARCALIB,wxID_IMRECALIBALL, 
    96     wxID_IMCOPYCONTROLS, wxID_INTEGRATEALL, wxID_IMSAVECONTROLS, wxID_IMLOADCONTROLS, wxID_IMAUTOINTEG,
    97     wxID_IMCOPYSELECTED, wxID_SAVESELECTEDCONTROLS, wxID_IMXFERCONTROLS,wxID_IMRESETDIST,
    98 ] = [wx.NewId() for item in range(14)]
    99 
    100 [ wxID_MASKCOPY, wxID_MASKSAVE, wxID_MASKLOAD, wxID_NEWMASKSPOT,wxID_NEWMASKARC,wxID_NEWMASKRING,
    101     wxID_NEWMASKFRAME, wxID_NEWMASKPOLY,wxID_MASKLOADNOT,wxID_FINDSPOTS,wxID_DELETESPOTS
    102 ] = [wx.NewId() for item in range(11)]
    103 
    104 [ wxID_STRSTACOPY, wxID_STRSTAFIT, wxID_STRSTASAVE, wxID_STRSTALOAD,wxID_STRSTSAMPLE,
    105     wxID_APPENDDZERO,wxID_STRSTAALLFIT,wxID_UPDATEDZERO,wxID_STRSTAPLOT,wxID_STRRINGSAVE,
    106 ] = [wx.NewId() for item in range(10)]
    107 
    108 [ wxID_BACKCOPY,wxID_LIMITCOPY, wxID_SAMPLECOPY, wxID_SAMPLECOPYSOME, wxID_BACKFLAGCOPY, wxID_SAMPLEFLAGCOPY,
    109     wxID_SAMPLESAVE, wxID_SAMPLELOAD,wxID_ADDEXCLREGION,wxID_SETSCALE,wxID_SAMPLE1VAL,wxID_ALLSAMPLELOAD,
    110     wxID_MAKEBACKRDF,wxID_RESCALEALL,
    111 ] = [wx.NewId() for item in range(14)]
    112 
    113 [ wxID_INSTPRMRESET,wxID_CHANGEWAVETYPE,wxID_INSTCOPY, wxID_INSTFLAGCOPY, wxID_INSTLOAD,
    114     wxID_INSTSAVE, wxID_INST1VAL, wxID_INSTCALIB,wxID_INSTSAVEALL,
    115 ] = [wx.NewId() for item in range(9)]
    116 
    117 [ wxID_UNDO,wxID_LSQPEAKFIT,wxID_LSQONECYCLE,wxID_RESETSIGGAM,wxID_CLEARPEAKS,wxID_AUTOSEARCH,
    118     wxID_PEAKSCOPY, wxID_SEQPEAKFIT,
    119 ] = [wx.NewId() for item in range(8)]
    120 
    121 [  wxID_INDXRELOAD, wxID_INDEXPEAKS, wxID_REFINECELL, wxID_COPYCELL, wxID_MAKENEWPHASE,
    122     wxID_EXPORTCELLS,
    123 ] = [wx.NewId() for item in range(6)]
    124 
    125 [ wxID_CONSTRAINTADD,wxID_EQUIVADD,wxID_HOLDADD,wxID_FUNCTADD,wxID_ADDRIDING,
    126   wxID_CONSPHASE, wxID_CONSHIST, wxID_CONSHAP, wxID_CONSGLOBAL,wxID_EQUIVALANCEATOMS,
    127 ] = [wx.NewId() for item in range(10)]
    128 
    129 [ wxID_RESTRAINTADD, wxID_RESTSELPHASE,wxID_RESTDELETE, wxID_RESRCHANGEVAL,
    130     wxID_RESTCHANGEESD,wxID_AARESTRAINTADD,wxID_AARESTRAINTPLOT,
    131 ] = [wx.NewId() for item in range(7)]
    132 
    133 [ wxID_RIGIDBODYADD,wxID_DRAWDEFINERB,wxID_RIGIDBODYIMPORT,wxID_RESIDUETORSSEQ,
    134     wxID_AUTOFINDRESRB,wxID_GLOBALRESREFINE,wxID_RBREMOVEALL,wxID_COPYRBPARMS,
    135     wxID_GLOBALTHERM,wxID_VECTORBODYADD
    136 ] = [wx.NewId() for item in range(10)]
    137 
    138 [ wxID_RENAMESEQSEL,wxID_SAVESEQSEL,wxID_SAVESEQSELCSV,wxID_SAVESEQCSV,wxID_PLOTSEQSEL,
    139   wxID_ORGSEQSEL,wxADDSEQVAR,wxDELSEQVAR,wxEDITSEQVAR,wxCOPYPARFIT,wxID_AVESEQSEL,
    140   wxADDPARFIT,wxDELPARFIT,wxEDITPARFIT,wxDOPARFIT,wxADDSEQDIST,wxADDSEQANGLE,wxID_ORGSEQINC,
    141 ] = [wx.NewId() for item in range(18)]
    142 
    143 [ wxID_MODELCOPY,wxID_MODELFIT,wxID_MODELADD,wxID_ELEMENTADD,wxID_ELEMENTDELETE,
    144     wxID_ADDSUBSTANCE,wxID_LOADSUBSTANCE,wxID_DELETESUBSTANCE,wxID_COPYSUBSTANCE,
    145     wxID_MODELUNDO,wxID_MODELFITALL,wxID_MODELCOPYFLAGS,wxID_RELOADSUBSTANCES,
    146     wxID_MODELPLOT,
    147 ] = [wx.NewId() for item in range(14)]
    148 
    149 [ wxID_SELECTPHASE,wxID_PWDHKLPLOT,wxID_PWD3DHKLPLOT,wxID_3DALLHKLPLOT,wxID_MERGEHKL,
    150 ] = [wx.NewId() for item in range(5)]
    151 
    152 [ wxID_PDFCOPYCONTROLS, wxID_PDFSAVECONTROLS, wxID_PDFLOADCONTROLS, wxID_PDFCOMPUTE,
    153     wxID_PDFCOMPUTEALL, wxID_PDFADDELEMENT, wxID_PDFDELELEMENT, wxID_PDFPKSFIT,
    154     wxID_PDFPKSFITALL,wxID_PDFCOPYPEAKS,wxID_CLEARPDFPEAKS,
    155 ] = [wx.NewId() for item in range(11)]
    156 
    157 [ wxID_MCRON,wxID_MCRLIST,wxID_MCRSAVE,wxID_MCRPLAY,
    158 ] = [wx.NewId() for item in range(4)]
    159 
    160 
    161 
    16263VERY_LIGHT_GREY = wx.Colour(235,235,235)
     64
     65# define Ids for wx menu items
     66def Define_wxId(*args):
     67    '''routine to create unique global wx Id symbols in current module.
     68    '''
     69    for arg in args:
     70        if arg in globals():
     71            if GSASIIpath.GetConfigValue('debug'): print arg,'already defined'
     72            continue
     73        exec('global '+arg+';'+arg+' = wx.NewId()')
     74
     75# probably a good idea to move these to where they are used for cleaner code
     76Define_wxId('wxID_FOURCALC', 'wxID_FOURSEARCH', 'wxID_FOURCLEAR', 'wxID_PEAKSMOVE', 'wxID_PEAKSCLEAR',
     77    'wxID_CHARGEFLIP', 'wxID_PEAKSUNIQUE', 'wxID_PEAKSDELETE', 'wxID_PEAKSDA',
     78    'wxID_PEAKSDISTVP', 'wxID_PEAKSVIEWPT', 'wxID_FINDEQVPEAKS', 'wxID_SHOWBONDS', 'wxID_MULTIMCSA',
     79    'wxID_SINGLEMCSA', 'wxID_4DCHARGEFLIP', 'wxID_TRANSFORMSTRUCTURE',)
     80
     81Define_wxId('wxID_PWDRADD', 'wxID_HKLFADD', 'wxID_PWDANALYSIS', 'wxID_PWDCOPY', 'wxID_PLOTCTRLCOPY',
     82    'wxID_DATADELETE', 'wxID_DATACOPY', 'wxID_DATACOPYFLAGS', 'wxID_DATASELCOPY', 'wxID_DATAUSE',)
     83
     84Define_wxId('wxID_ATOMSEDITADD', 'wxID_ATOMSEDITINSERT', 'wxID_ATOMSEDITDELETE',
     85    'wxID_ATOMSMODIFY', 'wxID_ATOMSTRANSFORM', 'wxID_ATOMSVIEWADD', 'wxID_ATOMVIEWINSERT',
     86    'wxID_RELOADDRAWATOMS', 'wxID_ATOMSDISAGL', 'wxID_ATOMMOVE', 'wxID_MAKEMOLECULE',
     87    'wxID_ASSIGNATMS2RB', 'wxID_ATOMSPDISAGL', 'wxID_ISODISP', 'wxID_ADDHATOM', 'wxID_UPDATEHATOM',
     88    'wxID_WAVEVARY', 'wxID_ATOMSROTATE', 'wxID_ATOMSDENSITY', 'wxID_VALIDPROTEIN',
     89    'wxID_ATOMSSETALL', 'wxID_ATOMSSETSEL',)
     90
     91Define_wxId('wxID_DRAWATOMSTYLE', 'wxID_DRAWATOMLABEL', 'wxID_DRAWATOMCOLOR', 'wxID_DRAWATOMRESETCOLOR',
     92    'wxID_DRAWVIEWPOINT', 'wxID_DRAWTRANSFORM', 'wxID_DRAWDELETE', 'wxID_DRAWFILLCELL',
     93    'wxID_DRAWADDEQUIV', 'wxID_DRAWFILLCOORD', 'wxID_DRAWDISAGLTOR', ' wxID_DRAWPLANE',
     94    'wxID_DRAWDISTVP', 'wxID_DRAWADDSPHERE', 'wxID_DRWAEDITRADII',)
     95
     96Define_wxId('wxID_DRAWRESTRBOND', 'wxID_DRAWRESTRANGLE', 'wxID_DRAWRESTRPLANE', 'wxID_DRAWRESTRCHIRAL',)
     97
     98Define_wxId('wxID_ADDMCSAATOM', 'wxID_ADDMCSARB', 'wxID_CLEARMCSARB', 'wxID_MOVEMCSA', 'wxID_MCSACLEARRESULTS',)
     99
     100Define_wxId('wxID_CLEARTEXTURE', 'wxID_REFINETEXTURE',)
     101
     102Define_wxId('wxID_LOADDIFFAX', 'wxID_LAYERSIMULATE', 'wxID_SEQUENCESIMULATE', 'wxID_LAYERSFIT', 'wxID_COPYPHASE',)
     103
     104Define_wxId('wxID_PAWLEYLOAD', 'wxID_PAWLEYESTIMATE', 'wxID_PAWLEYUPDATE', 'wxID_PAWLEYSELALL', 'wxID_PAWLEYSELNONE',
     105  'wxID_PAWLEYSELTOGGLE', 'wxID_PAWLEYSET',)
     106
     107Define_wxId('wxID_IMCALIBRATE', 'wxID_IMRECALIBRATE', 'wxID_IMINTEGRATE', 'wxID_IMCLEARCALIB', 'wxID_IMRECALIBALL',
     108    'wxID_IMCOPYCONTROLS', 'wxID_INTEGRATEALL', 'wxID_IMSAVECONTROLS', 'wxID_IMLOADCONTROLS', 'wxID_IMAUTOINTEG',
     109    'wxID_IMCOPYSELECTED', 'wxID_SAVESELECTEDCONTROLS', 'wxID_IMXFERCONTROLS', 'wxID_IMRESETDIST',)
     110
     111Define_wxId('wxID_MASKCOPY', 'wxID_MASKSAVE', 'wxID_MASKLOAD', 'wxID_NEWMASKSPOT', 'wxID_NEWMASKARC', 'wxID_NEWMASKRING',
     112    'wxID_NEWMASKFRAME', 'wxID_NEWMASKPOLY', 'wxID_MASKLOADNOT', 'wxID_FINDSPOTS', 'wxID_DELETESPOTS',)
     113
     114Define_wxId('wxID_STRSTACOPY', 'wxID_STRSTAFIT', 'wxID_STRSTASAVE', 'wxID_STRSTALOAD', 'wxID_STRSTSAMPLE',
     115    'wxID_APPENDDZERO', 'wxID_STRSTAALLFIT', 'wxID_UPDATEDZERO', 'wxID_STRSTAPLOT', 'wxID_STRRINGSAVE',)
     116
     117Define_wxId('wxID_BACKCOPY', 'wxID_LIMITCOPY', 'wxID_SAMPLECOPY', 'wxID_SAMPLECOPYSOME', 'wxID_BACKFLAGCOPY', 'wxID_SAMPLEFLAGCOPY',
     118    'wxID_SAMPLESAVE', 'wxID_SAMPLELOAD', 'wxID_ADDEXCLREGION', 'wxID_SETSCALE', 'wxID_SAMPLE1VAL', 'wxID_ALLSAMPLELOAD',
     119    'wxID_MAKEBACKRDF', 'wxID_RESCALEALL',)
     120
     121Define_wxId('wxID_INSTPRMRESET', 'wxID_CHANGEWAVETYPE', 'wxID_INSTCOPY', 'wxID_INSTFLAGCOPY', 'wxID_INSTLOAD',
     122    'wxID_INSTSAVE', 'wxID_INST1VAL', 'wxID_INSTCALIB', 'wxID_INSTSAVEALL',)
     123
     124Define_wxId('wxID_UNDO', 'wxID_LSQPEAKFIT', 'wxID_LSQONECYCLE', 'wxID_RESETSIGGAM', 'wxID_CLEARPEAKS', 'wxID_AUTOSEARCH',
     125    'wxID_PEAKSCOPY', 'wxID_SEQPEAKFIT',)
     126
     127Define_wxId(' wxID_INDXRELOAD', 'wxID_INDEXPEAKS', 'wxID_REFINECELL', 'wxID_COPYCELL', 'wxID_MAKENEWPHASE',
     128    'wxID_EXPORTCELLS',)
     129
     130Define_wxId('wxID_CONSTRAINTADD', 'wxID_EQUIVADD', 'wxID_HOLDADD', 'wxID_FUNCTADD', 'wxID_ADDRIDING',
     131  'wxID_CONSPHASE', 'wxID_CONSHIST', 'wxID_CONSHAP', 'wxID_CONSGLOBAL', 'wxID_EQUIVALANCEATOMS',)
     132
     133Define_wxId('wxID_RESTRAINTADD', 'wxID_RESTSELPHASE', 'wxID_RESTDELETE', 'wxID_RESRCHANGEVAL',
     134    'wxID_RESTCHANGEESD', 'wxID_AARESTRAINTADD', 'wxID_AARESTRAINTPLOT',)
     135
     136Define_wxId('wxID_RIGIDBODYADD', 'wxID_DRAWDEFINERB', 'wxID_RIGIDBODYIMPORT', 'wxID_RESIDUETORSSEQ',
     137    'wxID_AUTOFINDRESRB', 'wxID_GLOBALRESREFINE', 'wxID_RBREMOVEALL', 'wxID_COPYRBPARMS',
     138    'wxID_GLOBALTHERM', 'wxID_VECTORBODYADD')
     139
     140Define_wxId('wxID_RENAMESEQSEL', 'wxID_SAVESEQSEL', 'wxID_SAVESEQSELCSV', 'wxID_SAVESEQCSV', 'wxID_PLOTSEQSEL',
     141  'wxID_ORGSEQSEL', 'wxADDSEQVAR', 'wxDELSEQVAR', 'wxEDITSEQVAR', 'wxCOPYPARFIT', 'wxID_AVESEQSEL',
     142  'wxADDPARFIT', 'wxDELPARFIT', 'wxEDITPARFIT', 'wxDOPARFIT', 'wxADDSEQDIST', 'wxADDSEQANGLE', 'wxID_ORGSEQINC',)
     143
     144Define_wxId('wxID_MODELCOPY', 'wxID_MODELFIT', 'wxID_MODELADD', 'wxID_ELEMENTADD', 'wxID_ELEMENTDELETE',
     145    'wxID_ADDSUBSTANCE', 'wxID_LOADSUBSTANCE', 'wxID_DELETESUBSTANCE', 'wxID_COPYSUBSTANCE',
     146    'wxID_MODELUNDO', 'wxID_MODELFITALL', 'wxID_MODELCOPYFLAGS', 'wxID_RELOADSUBSTANCES',
     147    'wxID_MODELPLOT',)
     148
     149Define_wxId('wxID_SELECTPHASE', 'wxID_PWDHKLPLOT', 'wxID_PWD3DHKLPLOT', 'wxID_3DALLHKLPLOT', 'wxID_MERGEHKL',)
     150
     151Define_wxId('wxID_PDFCOPYCONTROLS', 'wxID_PDFSAVECONTROLS', 'wxID_PDFLOADCONTROLS', 'wxID_PDFCOMPUTE',
     152    'wxID_PDFCOMPUTEALL', 'wxID_PDFADDELEMENT', 'wxID_PDFDELELEMENT', 'wxID_PDFPKSFIT',
     153    'wxID_PDFPKSFITALL', 'wxID_PDFCOPYPEAKS', 'wxID_CLEARPDFPEAKS',)
     154
     155Define_wxId('wxID_MCRON', 'wxID_MCRLIST', 'wxID_MCRSAVE', 'wxID_MCRPLAY',)
    163156
    164157commonTrans = {'abc':np.eye(3),'a-cb':np.array([[1.,0.,0.],[0.,0.,-1.],[0.,1.,0.]]),
     
    176169    'P->I','I->P','P->F','F->P','H->R','R->H','R->O','O->R','abc*','setting 1->2']          #don't put any new ones after the setting one!
    177170
     171def SetDefaultDData(dType,histoName,NShkl=0,NDij=0):
     172    if dType in ['SXC','SNC']:
     173        return {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
     174            'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
     175            'Extinction':['Lorentzian','None', {'Tbar':0.1,'Cos2TM':0.955,
     176            'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}],
     177            'Flack':[0.0,False]}
     178    elif dType == 'SNT':
     179        return {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
     180            'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
     181            'Extinction':['Lorentzian','None', {
     182            'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}]}
     183    elif 'P' in dType:
     184        return {'Histogram':histoName,'Show':False,'Scale':[1.0,False],
     185            'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{},[],0.1],
     186            'Size':['isotropic',[1.,1.,1.],[False,False,False],[0,0,1],
     187                [1.,1.,1.,0.,0.,0.],6*[False,]],
     188            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
     189                NShkl*[0.01,],NShkl*[False,]],
     190            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
     191            'Extinction':[0.0,False],'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}}
     192
    178193################################################################################
    179 #### GSAS-II class definitions
     194#### class definitions used for main GUI
    180195################################################################################
    181196
    182 # Should SymOpDialog, DisAglDialog etc. be moved to GSASIIctrls?
    183 
    184 class SGMagSpinBox(wx.Dialog):
    185     ''' Special version of MessageBox that displays magnetic spin text
    186     '''
    187     def __init__(self,parent,title,text,table,names,spins,):
    188         wx.Dialog.__init__(self,parent,wx.ID_ANY,title,pos=wx.DefaultPosition,
    189             style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,size=wx.Size(420,350))
    190         self.text = text
    191         self.table = table
    192         self.names = names
    193         self.spins = spins
    194         self.panel = wxscroll.ScrolledPanel(self)
    195         mainSizer = wx.BoxSizer(wx.VERTICAL)
    196         mainSizer.Add((0,10))
    197         first = text[0].split(':')[-1].strip()
    198         cents = [0,]
    199         if 'P' != first[0]:
    200             cents = text[-1].split(';')
    201         for line in text:
    202             mainSizer.Add(wx.StaticText(self.panel,label='     %s     '%(line)),0,WACV)
    203         ncol = self.table[0].count(',')+2
    204         for ic,cent in enumerate(cents):
    205             if cent:
    206                 cent = cent.strip(' (').strip(')+\n')
    207                 mainSizer.Add(wx.StaticText(self.panel,label=' for (%s)+'%(cent)),0,WACV)
    208             tableSizer = wx.FlexGridSizer(0,2*ncol+3,0,0)
    209             for j,item in enumerate(self.table):
    210                 flds = item.split(')')[1]
    211                 tableSizer.Add(wx.StaticText(self.panel,label='  (%2d)  '%(j+1)),0,WACV|wx.ALIGN_LEFT)           
    212                 flds = flds.replace(' ','').split(',')
    213                 for i,fld in enumerate(flds):
    214                     if i < ncol-1:
    215                         text = wx.StaticText(self.panel,label='%s, '%(fld))
    216                         tableSizer.Add(text,0,WACV|wx.ALIGN_RIGHT)
    217                     else:
    218                         text = wx.StaticText(self.panel,label='%s '%(fld))
    219                         tableSizer.Add(text,0,WACV|wx.ALIGN_RIGHT)
    220                 text = wx.StaticText(self.panel,label=' (%s) '%(self.names[j]))
    221                 if self.spins[j+ic*len(self.table)] < 0:
    222                     text.SetForegroundColour('Red')
    223                 tableSizer.Add(text,0,WACV|wx.ALIGN_RIGHT)
    224                 if not j%2:
    225                     tableSizer.Add((20,0))
    226             mainSizer.Add(tableSizer,0,wx.ALIGN_CENTER)
    227            
    228         btnsizer = wx.StdDialogButtonSizer()
    229         OKbtn = wx.Button(self.panel, wx.ID_OK)
    230         OKbtn.SetDefault()
    231         btnsizer.AddButton(OKbtn)
    232         btnsizer.Realize()
    233         mainSizer.Add((0,10))
    234         mainSizer.Add(btnsizer,0,wx.ALIGN_CENTER)
    235         self.panel.SetSizer(mainSizer)
    236         size = np.array(self.GetSize())
    237         self.panel.SetupScrolling()
    238         size = [size[0]-5,size[1]-20]       #this fiddling is needed for older wx!
    239         self.panel.SetSize(size)
    240         self.panel.SetAutoLayout(1)
    241 
    242     def Show(self):
    243         '''Use this method after creating the dialog to post it
    244         '''
    245         self.ShowModal()
    246         return   
    247 
    248 ################################################################################
    249 class SymOpDialog(wx.Dialog):
    250     '''Class to select a symmetry operator
    251     '''
    252     def __init__(self,parent,SGData,New=True,ForceUnit=False):
    253         wx.Dialog.__init__(self,parent,-1,'Select symmetry operator',
    254             pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
    255         panel = wx.Panel(self)
    256         self.SGData = SGData
    257         self.New = New
    258         self.Force = ForceUnit
    259         self.OpSelected = [0,0,0,[0,0,0],False,False]
    260         mainSizer = wx.BoxSizer(wx.VERTICAL)
    261         if ForceUnit:
    262             choice = ['No','Yes']
    263             self.force = wx.RadioBox(panel,-1,'Force to unit cell?',choices=choice)
    264             self.force.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
    265             mainSizer.Add(self.force,0,WACV|wx.TOP,5)
    266 #        if SGData['SGInv']:
    267         choice = ['No','Yes']
    268         self.inv = wx.RadioBox(panel,-1,'Choose inversion?',choices=choice)
    269         self.inv.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
    270         mainSizer.Add(self.inv,0,WACV)
    271         if SGData['SGLatt'] != 'P':
    272             LattOp = G2spc.Latt2text(SGData['SGLatt']).split(';')
    273             self.latt = wx.RadioBox(panel,-1,'Choose cell centering?',choices=LattOp)
    274             self.latt.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
    275             mainSizer.Add(self.latt,0,WACV)
    276         if SGData['SGLaue'] in ['-1','2/m','mmm','4/m','4/mmm']:
    277             Ncol = 2
    278         else:
    279             Ncol = 3
    280         OpList = []
    281         for Opr in SGData['SGOps']:
    282             OpList.append(G2spc.MT2text(Opr))
    283         self.oprs = wx.RadioBox(panel,-1,'Choose space group operator?',choices=OpList,
    284             majorDimension=Ncol)
    285         self.oprs.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
    286         mainSizer.Add(self.oprs,0,WACV|wx.BOTTOM,5)
    287         mainSizer.Add(wx.StaticText(panel,-1,"   Choose unit cell?"),0,WACV)
    288         cellSizer = wx.BoxSizer(wx.HORIZONTAL)
    289         cellName = ['X','Y','Z']
    290         self.cell = []
    291         for i in range(3):
    292             self.cell.append(wx.SpinCtrl(panel,-1,cellName[i],size=wx.Size(50,20)))
    293             self.cell[-1].SetRange(-3,3)
    294             self.cell[-1].SetValue(0)
    295             self.cell[-1].Bind(wx.EVT_SPINCTRL, self.OnOpSelect)
    296             cellSizer.Add(self.cell[-1],0,WACV)
    297         mainSizer.Add(cellSizer,0,WACV|wx.BOTTOM,5)
    298         if self.New:
    299             choice = ['No','Yes']
    300             self.new = wx.RadioBox(panel,-1,'Generate new positions?',choices=choice)
    301             self.new.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
    302             mainSizer.Add(self.new,0,WACV)
    303 
    304         OkBtn = wx.Button(panel,-1,"Ok")
    305         OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
    306         cancelBtn = wx.Button(panel,-1,"Cancel")
    307         cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
    308         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
    309         btnSizer.Add((20,20),1)
    310         btnSizer.Add(OkBtn)
    311         btnSizer.Add((20,20),1)
    312         btnSizer.Add(cancelBtn)
    313         btnSizer.Add((20,20),1)
    314 
    315         mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
    316         panel.SetSizer(mainSizer)
    317         panel.Fit()
    318         self.Fit()
    319 
    320     def OnOpSelect(self,event):
    321 #        if self.SGData['SGInv']:
    322         self.OpSelected[0] = self.inv.GetSelection()
    323         if self.SGData['SGLatt'] != 'P':
    324             self.OpSelected[1] = self.latt.GetSelection()
    325         self.OpSelected[2] = self.oprs.GetSelection()
    326         for i in range(3):
    327             self.OpSelected[3][i] = float(self.cell[i].GetValue())
    328         if self.New:
    329             self.OpSelected[4] = self.new.GetSelection()
    330         if self.Force:
    331             self.OpSelected[5] = self.force.GetSelection()
    332 
    333     def GetSelection(self):
    334         return self.OpSelected
    335 
    336     def OnOk(self,event):
    337         parent = self.GetParent()
    338         parent.Raise()
    339         self.EndModal(wx.ID_OK)
    340 
    341     def OnCancel(self,event):
    342         parent = self.GetParent()
    343         parent.Raise()
    344         self.EndModal(wx.ID_CANCEL)
    345        
    346 ################################################################################
    347 class SphereEnclosure(wx.Dialog):
    348     ''' Add atoms within sphere of enclosure to drawing
    349    
    350     :param wx.Frame parent: reference to parent frame (or None)
    351     :param general: general data (includes drawing data)
    352     :param atoms: drawing atoms data
    353     :param indx: list of selected atoms (may be empty)
    354    
    355     '''
    356     def __init__(self,parent,general,drawing,indx):
    357         wx.Dialog.__init__(self,parent,wx.ID_ANY,'Setup phase transformation',
    358             pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
    359         self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
    360         self.General = general
    361         self.Drawing = drawing
    362         self.indx = indx
    363         self.Sphere = [1.0,]
    364         self.centers = []
    365         self.atomTypes = [[item,True] for item in self.General['AtomTypes']]
    366        
    367         self.Draw()
    368        
    369     def Draw(self):
    370        
    371         def OnAtomType(event):
    372             Obj = event.GetEventObject()
    373             id = Ind[Obj.GetId()]
    374             self.atomTypes[id][1] = Obj.GetValue()
    375        
    376         self.panel.Destroy()
    377         self.panel = wx.Panel(self)
    378         mainSizer = wx.BoxSizer(wx.VERTICAL)
    379         mainSizer.Add(wx.StaticText(self.panel,label=' Sphere of enclosure controls:'),0,WACV)
    380         topSizer = wx.BoxSizer(wx.HORIZONTAL)
    381         atoms = []
    382         if len(self.indx):
    383             topSizer.Add(wx.StaticText(self.panel,label=' Sphere centered at atoms: '),0,WACV)
    384             cx,ct,cs = self.Drawing['atomPtrs'][:3]
    385             for id in self.indx:
    386                 atom = self.Drawing['Atoms'][id]
    387                 self.centers.append(atom[cx:cx+3])
    388                 atoms.append('%s(%s)'%(atom[ct-1],atom[cs-1]))
    389             topSizer.Add(wx.ComboBox(self.panel,choices=atoms,value=atoms[0],
    390                 style=wx.CB_READONLY|wx.CB_DROPDOWN),0,WACV)
    391         else:
    392             topSizer.Add(wx.StaticText(self.panel,label=' Sphere centered at drawing view point'),0,WACV)
    393             self.centers.append(self.Drawing['viewPoint'][0])
    394         mainSizer.Add(topSizer,0,WACV)
    395         sphereSizer = wx.BoxSizer(wx.HORIZONTAL)
    396         sphereSizer.Add(wx.StaticText(self.panel,label=' Sphere radius: '),0,WACV)
    397         radius = G2G.ValidatedTxtCtrl(self.panel,self.Sphere,0,nDig=(10,3),size=(65,25))
    398         sphereSizer.Add(radius,0,WACV)
    399         mainSizer.Add(sphereSizer,0,WACV)
    400         mainSizer.Add(wx.StaticText(self.panel,label=' Target selected atoms:'),0,WACV)
    401         atSizer = wx.BoxSizer(wx.HORIZONTAL)
    402         Ind = {}
    403         for i,item in enumerate(self.atomTypes):
    404             atm = wx.CheckBox(self.panel,label=item[0])
    405             atm.SetValue(item[1])
    406             atm.Bind(wx.EVT_CHECKBOX, OnAtomType)
    407             Ind[atm.GetId()] = i
    408             atSizer.Add(atm,0,WACV)
    409         mainSizer.Add(atSizer,0,WACV)
    410        
    411         OkBtn = wx.Button(self.panel,-1,"Ok")
    412         OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
    413         cancelBtn = wx.Button(self.panel,-1,"Cancel")
    414         cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
    415         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
    416         btnSizer.Add((20,20),1)
    417         btnSizer.Add(OkBtn)
    418         btnSizer.Add((20,20),1)
    419         btnSizer.Add(cancelBtn)
    420         btnSizer.Add((20,20),1)
    421        
    422         mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
    423         self.panel.SetSizer(mainSizer)
    424         self.panel.Fit()
    425         self.Fit()
    426        
    427     def GetSelection(self):
    428         used = []
    429         for atm in self.atomTypes:
    430             if atm[1]:
    431                 used.append(str(atm[0]))
    432         return self.centers,self.Sphere[0],used
    433 
    434     def OnOk(self,event):
    435         parent = self.GetParent()
    436         parent.Raise()
    437         self.EndModal(wx.ID_OK)
    438 
    439     def OnCancel(self,event):
    440         parent = self.GetParent()
    441         parent.Raise()
    442         self.EndModal(wx.ID_CANCEL)
    443        
    444 ################################################################################
    445 class TransformDialog(wx.Dialog):
    446     ''' Phase transformation
    447    
    448     :param wx.Frame parent: reference to parent frame (or None)
    449     :param phase: phase data
    450    
    451     #NB: commonNames & commonTrans defined at top of this file
    452     '''
    453     def __init__(self,parent,phase):
    454         wx.Dialog.__init__(self,parent,wx.ID_ANY,'Setup phase transformation',
    455             pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
    456         self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
    457         self.Phase = copy.deepcopy(phase)   #will be a new phase!
    458 #        self.Super = phase['General']['Super']
    459 #        if self.Super:
    460 #            self.Trans = np.eye(4)
    461 #            self.Vec = np.zeros(4)
    462 #        else:
    463         self.Trans = np.eye(3)
    464         self.Vec = np.zeros(3)
    465         self.oldSpGrp = phase['General']['SGData']['SpGrp']
    466         self.oldSGdata = phase['General']['SGData']
    467         self.newSpGrp = self.Phase['General']['SGData']['SpGrp']
    468         self.oldCell = phase['General']['Cell'][1:8]
    469         self.newCell = self.Phase['General']['Cell'][1:8]
    470         self.Common = 'abc'
    471         self.ifMag = False
    472         self.ifConstr = True
    473         self.Draw()
    474 
    475     def Draw(self):
    476                
    477         def OnCommon(event):
    478             Obj = event.GetEventObject()
    479             self.Common = Obj.GetValue()
    480             if '*' in self.Common:
    481                 A,B = G2lat.cell2AB(self.oldCell[:6])
    482                 self.newCell[2:5] = [A[2,2],90.,90.]
    483                 a,b = G2lat.cell2AB(self.newCell[:6])
    484                 self.Trans = np.inner(a.T,B)    #correct!
    485                 self.ifConstr = False
    486                 self.newSpGrp = 'P 1'
    487                 SGErr,SGData = G2spc.SpcGroup(self.newSpGrp)
    488                 self.Phase['General']['SGData'] = SGData
    489             else:
    490                 if self.Common == commonNames[-1]:      #change setting
    491                     self.Vec = G2spc.spg2origins[self.oldSpGrp]
    492                     self.newSpGrp = self.oldSpGrp
    493                 else:
    494                     self.Trans = commonTrans[self.Common]
    495                     if 'R' == self.Common[-1]:
    496                         self.newSpGrp += ' r'
    497                         SGErr,SGData = G2spc.SpcGroup(self.newSpGrp)
    498                 &nb