Changeset 3000


Ignore:
Timestamp:
Aug 11, 2017 5:34:54 PM (4 years ago)
Author:
toby
Message:

make the two frame version the trunk as we hit version 3000

Location:
trunk
Files:
8 deleted
35 edited
6 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/AllBinaries

  • trunk/GSASII.py

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

    r2871 r3000  
    1818Also includes base classes for data import routines.
    1919
     20This module needs some work to separate wx from non-wx routines
    2021'''
    2122"""GSASIIIO: functions for IO of data
     
    3233import GSASIIpath
    3334GSASIIpath.SetVersionNumber("$Revision$")
    34 import GSASIIgrid as G2gd
     35import GSASIIdataGUI as G2gd
    3536import GSASIIobj as G2obj
    3637import GSASIIlattice as G2lat
     
    4243import GSASIIstrIO as G2stIO
    4344import GSASIImapvars as G2mv
    44 import GSASIIctrls as G2G
     45import GSASIIctrlGUI as G2G
    4546import os
    4647import os.path as ospath
     
    7879    '''
    7980    return re.sub('\s+', ' ', val).strip()
    80 
    81 def makeInstDict(names,data,codes):
    82     inst = dict(zip(names,zip(data,data,codes)))
    83     for item in inst:
    84         inst[item] = list(inst[item])
    85     return inst
    8681
    8782def FileDlgFixExt(dlg,file):
     
    153148
    154149    '''
    155     Npix,Imagefile,imagetag = G2frame.PatternTree.GetImageLoc(treeId)
     150    Npix,Imagefile,imagetag = G2frame.GPXtree.GetImageLoc(treeId)
    156151    if isinstance(Imagefile,list):
    157152        imagefile,imagetag = Imagefile
     
    169164                print 'found image file '+os.path.join(G2frame.dirname,fil)
    170165                imagefile = os.path.join(G2frame.dirname,fil)
    171                 G2frame.PatternTree.UpdateImageLoc(treeId,imagefile)
     166                G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
    172167                return Npix,imagefile,imagetag
    173168            pth,enddir = os.path.split(pth)
     
    177172        #      & GPX was  .../A/B/C/refs/fil.gpx but is now .../NEW/TEST/TEST1
    178173        #    will look for .../NEW/TEST/TEST1/imgs/ima.ge, .../NEW/TEST/imgs/ima.ge, .../NEW/imgs/ima.ge and so on
    179         Controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
     174        Controls = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Controls'))
    180175        gpxPath = Controls.get('LastSavedAs','').replace('\\','/').split('/') # blank in older .GPX files
    181176        imgPath = imagefile.replace('\\','/').split('/')
     
    193188                print 'found image file '+os.path.join(pth,fil)
    194189                imagefile = os.path.join(pth,fil)
    195                 G2frame.PatternTree.UpdateImageLoc(treeId,imagefile)
     190                G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
    196191                return Npix,imagefile,imagetag
    197192            pth,enddir = os.path.split(pth)
     
    208203            if dlg.ShowModal() == wx.ID_OK:
    209204                imagefile = dlg.GetPath()
    210                 G2frame.PatternTree.UpdateImageLoc(treeId,imagefile)
     205                G2frame.GPXtree.UpdateImageLoc(treeId,imagefile)
    211206            else:
    212207                imagefile = False
     
    282277    ImageTag (where there is more than one image in the file), if defined.
    283278    '''
    284     ImgNames = G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
     279    ImgNames = G2gd.GetGPXtreeDataNames(G2frame,['IMG ',])
    285280    TreeLbl = 'IMG '+os.path.basename(imagefile)
    286281    ImageTag = Data.get('ImageTag')
     
    291286        imageInfo = imagefile
    292287    TreeName = G2obj.MakeUniqueLabel(TreeLbl,ImgNames)
    293     Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text=TreeName)
    294     G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Comments'),Comments)
     288    Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=TreeName)
     289    G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Comments'),Comments)
    295290    Imax = np.amax(Image)
    296291    if G2frame.imageDefault:
     
    339334    Data['setDefault'] = False
    340335    Data['range'] = [(0,Imax),[0,Imax]]
    341     G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Image Controls'),Data)
     336    G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Image Controls'),Data)
    342337    Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Frames':[],'Thresholds':[(0,Imax),[0,Imax]]}
    343     G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Masks'),Masks)
    344     G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Stress/Strain'),
     338    G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Masks'),Masks)
     339    G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Stress/Strain'),
    345340        {'Type':'True','d-zero':[],'Sample phi':0.0,'Sample z':0.0,'Sample load':0.0})
    346     G2frame.PatternTree.SetItemPyData(Id,[Npix,imageInfo])
     341    G2frame.GPXtree.SetItemPyData(Id,[Npix,imageInfo])
    347342    G2frame.PickId = Id
    348343    G2frame.PickIdText = G2frame.GetTreeItemsList(G2frame.PickId)
     
    495490
    496491def SaveMultipleImg(G2frame):
    497     if not G2frame.PatternTree.GetCount():
     492    if not G2frame.GPXtree.GetCount():
    498493        print 'no images!'
    499494        return
    500     choices = G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
     495    choices = G2gd.GetGPXtreeDataNames(G2frame,['IMG ',])
    501496    if len(choices) == 1:
    502497        names = choices
     
    510505    if not names: return
    511506    for name in names:
    512         Id = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, name)
    513         Npix,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(Id)
     507        Id = G2gd.GetGPXtreeItemId(G2frame, G2frame.root, name)
     508        Npix,imagefile,imagetag = G2frame.GPXtree.GetImageLoc(Id)
    514509        imroot = os.path.splitext(imagefile)[0]
    515510        if imagetag:
    516511            imroot += '_' + str(imagetag)
    517         Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Image Controls'))
     512        Data = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id, 'Image Controls'))
    518513        print('Writing '+imroot+'.imctrl')
    519514        File = open(imroot+'.imctrl','w')
     
    527522            File.write(key+':'+str(Data[key])+'\n')
    528523        File.close()
    529         mask = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Masks'))
     524        mask = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id, 'Masks'))
    530525        G2imG.CleanupMasks(mask)
    531526        print('Writing '+imroot+'.immask')
     
    551546    file = open(G2frame.GSASprojectfile,'rb')
    552547    if showProvenance: print 'loading from file: ',G2frame.GSASprojectfile
     548    #G2frame.SetTitle("GSAS-II data tree: "+
     549    #                 os.path.split(G2frame.GSASprojectfile)[1])
    553550    G2frame.SetTitle("GSAS-II data tree: "+
    554                      os.path.split(G2frame.GSASprojectfile)[1])
     551                     os.path.split(G2frame.GSASprojectfile)[1],1)
    555552    wx.BeginBusyCursor()
    556553    try:
     
    562559            datum = data[0]
    563560           
    564             Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text=datum[0])
     561            Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=datum[0])
    565562            if datum[0].startswith('PWDR'):               
    566563                if 'ranId' not in datum[1][0]: # patch: add random Id if not present
    567564                    datum[1][0]['ranId'] = ran.randint(0,sys.maxint)
    568                 G2frame.PatternTree.SetItemPyData(Id,datum[1][:3])  #temp. trim off junk (patch?)
     565                G2frame.GPXtree.SetItemPyData(Id,datum[1][:3])  #temp. trim off junk (patch?)
    569566            elif datum[0].startswith('HKLF'):
    570567                if 'ranId' not in datum[1][0]: # patch: add random Id if not present
    571568                    datum[1][0]['ranId'] = ran.randint(0,sys.maxint)
    572                 G2frame.PatternTree.SetItemPyData(Id,datum[1])
     569                G2frame.GPXtree.SetItemPyData(Id,datum[1])
    573570            else:
    574                 G2frame.PatternTree.SetItemPyData(Id,datum[1])             
     571                G2frame.GPXtree.SetItemPyData(Id,datum[1])             
    575572                if datum[0] == 'Controls' and 'LastSavedUsing' in datum[1]:
    576573                    LastSavedUsing = datum[1]['LastSavedUsing']
     
    591588                    continue
    592589#end PDF cleanup
    593                 sub = G2frame.PatternTree.AppendItem(Id,datus[0])
     590                sub = G2frame.GPXtree.AppendItem(Id,datus[0])
    594591#patch
    595592                if datus[0] == 'Instrument Parameters' and len(datus[1]) == 1:
     
    601598                        datus[1][0][item] = list(datus[1][0][item])
    602599#end patch
    603                 G2frame.PatternTree.SetItemPyData(sub,datus[1])
     600                G2frame.GPXtree.SetItemPyData(sub,datus[1])
    604601            if 'PDF ' in datum[0][:4] and oldPDF:
    605                 sub = G2frame.PatternTree.AppendItem(Id,'PDF Peaks')
    606                 G2frame.PatternTree.SetItemPyData(sub,{'Limits':[1.,5.],'Background':[2,[0.,-0.2*np.pi],False],'Peaks':[]})
     602                sub = G2frame.GPXtree.AppendItem(Id,'PDF Peaks')
     603                G2frame.GPXtree.SetItemPyData(sub,{'Limits':[1.,5.],'Background':[2,[0.,-0.2*np.pi],False],'Peaks':[]})
    607604            if datum[0].startswith('IMG'):                   #retrieve image default flag & data if set
    608                 Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Image Controls'))
     605                Data = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id,'Image Controls'))
    609606                if Data['setDefault']:
    610607                    G2frame.imageDefault = Data               
     
    622619    finally:
    623620        wx.EndBusyCursor()
    624         G2frame.Status.SetStatusText('Mouse RB click item to refresh/raise; RB drag/drop to reorder')
     621        G2frame.Status.SetStatusText('Mouse RB drag/drop to reorder',0)
    625622   
    626623def ProjFileSave(G2frame):
    627624    'Save a GSAS-II project file'
    628     if not G2frame.PatternTree.IsEmpty():
     625    if not G2frame.GPXtree.IsEmpty():
    629626        file = open(G2frame.GSASprojectfile,'wb')
    630627        print 'save to file: ',G2frame.GSASprojectfile
     
    632629        # (Controls should always be created at this point)
    633630        try:
    634             Controls = G2frame.PatternTree.GetItemPyData(
    635                 G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
     631            Controls = G2frame.GPXtree.GetItemPyData(
     632                G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Controls'))
    636633            Controls['LastSavedAs'] = os.path.abspath(G2frame.GSASprojectfile)
    637634            Controls['LastSavedUsing'] = str(GSASIIpath.GetVersionNumber())
     
    641638        wx.BeginBusyCursor()
    642639        try:
    643             item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
     640            item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.root)
    644641            while item:
    645642                data = []
    646                 name = G2frame.PatternTree.GetItemText(item)
    647                 data.append([name,G2frame.PatternTree.GetItemPyData(item)])
    648                 item2, cookie2 = G2frame.PatternTree.GetFirstChild(item)
     643                name = G2frame.GPXtree.GetItemText(item)
     644                data.append([name,G2frame.GPXtree.GetItemPyData(item)])
     645                item2, cookie2 = G2frame.GPXtree.GetFirstChild(item)
    649646                while item2:
    650                     name = G2frame.PatternTree.GetItemText(item2)
    651                     data.append([name,G2frame.PatternTree.GetItemPyData(item2)])
    652                     item2, cookie2 = G2frame.PatternTree.GetNextChild(item, cookie2)                           
    653                 item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                           
     647                    name = G2frame.GPXtree.GetItemText(item2)
     648                    data.append([name,G2frame.GPXtree.GetItemPyData(item2)])
     649                    item2, cookie2 = G2frame.GPXtree.GetNextChild(item, cookie2)                           
     650                item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie)                           
    654651                cPickle.dump(data,file,1)
    655652            file.close()
     
    666663    X = G2frame.Integrate[2][:-1]
    667664    N = len(X)
    668     Id = G2frame.PatternTree.GetItemParent(PickId)
    669     name = G2frame.PatternTree.GetItemText(Id)
     665    Id = G2frame.GPXtree.GetItemParent(PickId)
     666    name = G2frame.GPXtree.GetItemText(Id)
    670667    name = name.replace('IMG ',data['type']+' ')
    671     Comments = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Comments'))
     668    Comments = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,Id, 'Comments'))
    672669    if 'PWDR' in name:
    673670        names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
     
    692689    for i,azm in enumerate(azms[:-1]):
    693690        Aname = name+" Azm= %.2f"%((azm+dazm)%360.)
    694         item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
     691        item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.root)
    695692        # if Overwrite delete any duplicate
    696         if Overwrite and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,Aname):
     693        if Overwrite and G2gd.GetGPXtreeItemId(G2frame,G2frame.root,Aname):
    697694            print('Replacing '+Aname)
    698             item = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,Aname)
    699             G2frame.PatternTree.Delete(item)
     695            item = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,Aname)
     696            G2frame.GPXtree.Delete(item)
    700697        else:
    701698            nOcc = 0
    702699            while item:
    703                 Name = G2frame.PatternTree.GetItemText(item)
     700                Name = G2frame.GPXtree.GetItemText(item)
    704701                if Aname in Name:
    705702                    nOcc += 1
    706                 item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
     703                item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie)
    707704            if nOcc:
    708705                Aname += '(%d)'%(nOcc)
     
    729726        Ymax = np.max(Y)
    730727        W = np.where(Y>0.,1./Y,1.e-6)                    #probably not true
    731         Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text=Aname)
     728        Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=Aname)
    732729        G2frame.IntgOutList.append(Id)
    733         G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
    734         G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
     730        G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Comments'),Comments)                   
     731        G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
    735732        if 'PWDR' in Aname:
    736             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0],
     733            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0],
    737734                {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
    738735        inst = [dict(zip(names,zip(parms,parms,codes))),{}]
    739736        for item in inst[0]:
    740737            inst[0][item] = list(inst[0][item])
    741         G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Instrument Parameters'),inst)
     738        G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Instrument Parameters'),inst)
    742739        if 'PWDR' in Aname:
    743             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
    744             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Peak List'),{'sigDict':{},'peaks':[]})
    745             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Index Peak List'),[[],[]])
    746             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Unit Cells List'),[])
    747             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Reflection Lists'),{})
     740            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Sample Parameters'),Sample)
     741            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Peak List'),{'sigDict':{},'peaks':[]})
     742            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Index Peak List'),[[],[]])
     743            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Unit Cells List'),[])
     744            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Reflection Lists'),{})
    748745        elif 'SASD' in Aname:             
    749             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Substances'),G2pdG.SetDefaultSubstances())
    750             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
    751             G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Models'),G2pdG.SetDefaultSASDModel())
     746            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Substances'),G2pdG.SetDefaultSubstances())
     747            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Sample Parameters'),Sample)
     748            G2frame.GPXtree.SetItemPyData(G2frame.GPXtree.AppendItem(Id,text='Models'),G2pdG.SetDefaultSASDModel())
    752749        valuesdict = {
    753750            'wtFactor':1.0,
     
    757754            'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax]
    758755            }
    759         G2frame.PatternTree.SetItemPyData(
     756        G2frame.GPXtree.SetItemPyData(
    760757            Id,[valuesdict,
    761758                [np.array(X),np.array(Y),np.array(W),np.zeros(N),np.zeros(N),np.zeros(N)]])
     
    794791    import scipy.interpolate as scintp
    795792    for export in exports:
    796         PickId = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, export)
    797         PDFControls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame, PickId,'PDF Controls'))
     793        PickId = G2gd.GetGPXtreeItemId(G2frame, G2frame.root, export)
     794        PDFControls = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame, PickId,'PDF Controls'))
    798795        if PDFsaves[0]:     #I(Q)
    799796            iqfilename = ospath.join(G2frame.dirname,export.replace(' ','_')[5:]+'.iq')
     
    853850       
    854851        if PDFsaves[4]: #pdfGUI file for G(R)
    855             pId = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, 'PWDR'+export[4:])
    856             Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame, pId,'Instrument Parameters'))[0]
    857             Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame, pId,'Limits'))
     852            pId = G2gd.GetGPXtreeItemId(G2frame, G2frame.root, 'PWDR'+export[4:])
     853            Inst = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame, pId,'Instrument Parameters'))[0]
     854            Limits = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame, pId,'Limits'))
    858855            grfilename = ospath.join(G2frame.dirname,export.replace(' ','_')[5:]+'.gr')
    859856            grdata = PDFControls['G(R)'][1]
     
    956953    selections are placed in self.chosen when OK is pressed
    957954
    958     Also see GSASIIctrls
     955    Also see GSASIIctrlGUI
    959956    '''
    960957    def __init__(self,choicelist,headinglist,
     
    12211218
    12221219    This class is subclassed in the various exports/G2export_*.py files. Those files
    1223     are imported in :meth:`GSASII.GSASII._init_Exports` which defines the
     1220    are imported in :meth:`GSASIIdataGUI.GSASII._init_Exports` which defines the
    12241221    appropriate menu items for each one and the .Exporter method is called
    12251222    directly from the menu item.
     
    14631460        consDict = {}
    14641461        Histograms,Phases = self.G2frame.GetUsedHistogramsAndPhasesfromTree()
    1465         if self.G2frame.PatternTree.IsEmpty(): return # nothing to do
    1466         item, cookie = self.G2frame.PatternTree.GetFirstChild(self.G2frame.root)
     1462        if self.G2frame.GPXtree.IsEmpty(): return # nothing to do
     1463        item, cookie = self.G2frame.GPXtree.GetFirstChild(self.G2frame.root)
    14671464        while item:
    1468             name = self.G2frame.PatternTree.GetItemText(item)
     1465            name = self.G2frame.GPXtree.GetItemText(item)
    14691466            if name == 'Rigid bodies':
    1470                  rigidbodyDict = self.G2frame.PatternTree.GetItemPyData(item)
     1467                 rigidbodyDict = self.G2frame.GPXtree.GetItemPyData(item)
    14711468            elif name == 'Covariance':
    1472                  covDict = self.G2frame.PatternTree.GetItemPyData(item)
     1469                 covDict = self.G2frame.GPXtree.GetItemPyData(item)
    14731470            elif name == 'Constraints':
    1474                  consDict = self.G2frame.PatternTree.GetItemPyData(item)
    1475             item, cookie = self.G2frame.PatternTree.GetNextChild(self.G2frame.root, cookie)
     1471                 consDict = self.G2frame.GPXtree.GetItemPyData(item)
     1472            item, cookie = self.G2frame.GPXtree.GetNextChild(self.G2frame.root, cookie)
    14761473        rbVary,rbDict =  G2stIO.GetRigidBodyModels(rigidbodyDict,Print=False)
    14771474        self.parmDict.update(rbDict)
     
    15431540        self.SeqRefdata = None
    15441541        self.SeqRefhist = None
    1545         if self.G2frame.PatternTree.IsEmpty(): return # nothing to do
     1542        if self.G2frame.GPXtree.IsEmpty(): return # nothing to do
    15461543        histType = None       
    15471544        if self.currentExportType == 'phase':
    15481545            # if exporting phases load them here
    1549             sub = G2gd.GetPatternTreeItemId(self.G2frame,self.G2frame.root,'Phases')
     1546            sub = G2gd.GetGPXtreeItemId(self.G2frame,self.G2frame.root,'Phases')
    15501547            if not sub:
    15511548                print 'no phases found'
    15521549                return True
    1553             item, cookie = self.G2frame.PatternTree.GetFirstChild(sub)
     1550            item, cookie = self.G2frame.GPXtree.GetFirstChild(sub)
    15541551            while item:
    1555                 phaseName = self.G2frame.PatternTree.GetItemText(item)
    1556                 self.Phases[phaseName] =  self.G2frame.PatternTree.GetItemPyData(item)
    1557                 item, cookie = self.G2frame.PatternTree.GetNextChild(sub, cookie)
     1552                phaseName = self.G2frame.GPXtree.GetItemText(item)
     1553                self.Phases[phaseName] =  self.G2frame.GPXtree.GetItemPyData(item)
     1554                item, cookie = self.G2frame.GPXtree.GetNextChild(sub, cookie)
    15581555            return
    15591556        elif self.currentExportType == 'single':
     
    15651562
    15661563        if histType: # Loading just one kind of tree entry
    1567             item, cookie = self.G2frame.PatternTree.GetFirstChild(self.G2frame.root)
     1564            item, cookie = self.G2frame.GPXtree.GetFirstChild(self.G2frame.root)
    15681565            while item:
    1569                 name = self.G2frame.PatternTree.GetItemText(item)
     1566                name = self.G2frame.GPXtree.GetItemText(item)
    15701567                if name.startswith(histType):
    15711568                    if self.Histograms.get(name): # there is already an item with this name
     
    15811578                    # element contains refinement results, carry
    15821579                    # that over too now.
    1583                     self.Histograms[name]['Data'] = self.G2frame.PatternTree.GetItemPyData(item)[1]
    1584                     self.Histograms[name][0] = self.G2frame.PatternTree.GetItemPyData(item)[0]
    1585                     item2, cookie2 = self.G2frame.PatternTree.GetFirstChild(item)
     1580                    self.Histograms[name]['Data'] = self.G2frame.GPXtree.GetItemPyData(item)[1]
     1581                    self.Histograms[name][0] = self.G2frame.GPXtree.GetItemPyData(item)[0]
     1582                    item2, cookie2 = self.G2frame.GPXtree.GetFirstChild(item)
    15861583                    while item2:
    1587                         child = self.G2frame.PatternTree.GetItemText(item2)
    1588                         self.Histograms[name][child] = self.G2frame.PatternTree.GetItemPyData(item2)
    1589                         item2, cookie2 = self.G2frame.PatternTree.GetNextChild(item, cookie2)
    1590                 item, cookie = self.G2frame.PatternTree.GetNextChild(self.G2frame.root, cookie)
     1584                        child = self.G2frame.GPXtree.GetItemText(item2)
     1585                        self.Histograms[name][child] = self.G2frame.GPXtree.GetItemPyData(item2)
     1586                        item2, cookie2 = self.G2frame.GPXtree.GetNextChild(item, cookie2)
     1587                item, cookie = self.G2frame.GPXtree.GetNextChild(self.G2frame.root, cookie)
    15911588            # index powder and single crystal histograms by number
    15921589            for hist in self.Histograms:
     
    16061603        # else standard load: using all interlinked phases and histograms
    16071604        self.Histograms,self.Phases = self.G2frame.GetUsedHistogramsAndPhasesfromTree()
    1608         item, cookie = self.G2frame.PatternTree.GetFirstChild(self.G2frame.root)
     1605        item, cookie = self.G2frame.GPXtree.GetFirstChild(self.G2frame.root)
    16091606        while item:
    1610             name = self.G2frame.PatternTree.GetItemText(item)
    1611             item2, cookie2 = self.G2frame.PatternTree.GetFirstChild(item)
     1607            name = self.G2frame.GPXtree.GetItemText(item)
     1608            item2, cookie2 = self.G2frame.GPXtree.GetFirstChild(item)
    16121609            if not item2:
    1613                 self.OverallParms[name] = self.G2frame.PatternTree.GetItemPyData(item)
    1614             item, cookie = self.G2frame.PatternTree.GetNextChild(self.G2frame.root, cookie)
     1610                self.OverallParms[name] = self.G2frame.GPXtree.GetItemPyData(item)
     1611            item, cookie = self.G2frame.GPXtree.GetNextChild(self.G2frame.root, cookie)
    16151612        # index powder and single crystal histograms
    16161613        for hist in self.Histograms:
     
    21232120
    21242121if __name__ == '__main__':
    2125     import GSASII
    2126     application = GSASII.GSASIImain(0)
     2122    import GSASIIdataGUI
     2123    application = GSASIIdataGUI.GSASIImain(0)
    21272124    G2frame = application.main
    21282125    #app = wx.PySimpleApp()
  • trunk/GSASIIconstrGUI.py

    r2753 r3000  
    3131import GSASIImath as G2mth
    3232import GSASIIlattice as G2lat
    33 import GSASIIgrid as G2gd
    34 import GSASIIctrls as G2G
     33import GSASIIdataGUI as G2gd
     34import GSASIIctrlGUI as G2G
    3535import GSASIIplot as G2plt
    3636import GSASIIobj as G2obj
     
    224224            print str(key) + ': '+str(j)+' variable(s) as strings converted to objects'
    225225    ##################################################################################
    226     rigidbodyDict = G2frame.PatternTree.GetItemPyData(
    227         G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))
     226    rigidbodyDict = G2frame.GPXtree.GetItemPyData(
     227        G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Rigid bodies'))
    228228    rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})
    229229    rbVary,rbDict = G2stIO.GetRigidBodyModels(rigidbodyDict,Print=False)
     
    458458            atchoice = [fmt.format(*i1) for i1 in choices]
    459459            dlg = G2G.G2MultiChoiceDialog(
    460                 G2frame.dataFrame,legend,
     460                G2frame,legend,
    461461                'Constrain '+str(FrstVarb)+' with...',atchoice,
    462462                toggle=False,size=(625,400),monoFont=True)
     
    468468            if len(Selections) == 0:
    469469                dlg = wx.MessageDialog(
    470                     G2frame.dataFrame,
     470                    G2frame,
    471471                    'No variables were selected to include with '+str(FrstVarb),
    472472                    'No variables')
     
    477477        else:
    478478            dlg = wx.MessageDialog(
    479                 G2frame.dataFrame,
     479                G2frame,
    480480                'There are no appropriate variables to include with '+str(FrstVarb),
    481481                'No variables')
     
    554554        else:
    555555            dlg = wx.MessageDialog(
    556                 G2frame.dataFrame,
     556                G2frame,
    557557                'There are no selected variables to include with '+str(FrstVarb),
    558558                'No variables')
     
    584584            res = G2frame.ErrorDialog('Constraint Error',
    585585                'Error with newly added constraint:\n'+errmsg+
    586                 '\n\nDiscard newly added constraint?',parent=G2frame.dataFrame,
     586                '\n\nDiscard newly added constraint?',parent=G2frame,
    587587                wtype=wx.YES_NO)
    588588            return res != wx.ID_YES
     
    611611            res = G2frame.ErrorDialog('Constraint Error',
    612612                'Error after editing constraint:\n'+errmsg+
    613                 '\n\nDiscard last constraint edit?',parent=G2frame.dataFrame,
     613                '\n\nDiscard last constraint edit?',parent=G2frame,
    614614                wtype=wx.YES_NO)
    615615            return res != wx.ID_YES
     
    651651        if not varList:
    652652            G2frame.ErrorDialog('No variables','There are no variables of type '+vartype,
    653                 parent=G2frame.dataFrame)
     653                parent=G2frame)
    654654            return
    655655        l2 = l1 = 1
     
    662662        #varListlbl = ["("+i+") "+G2obj.fmtVarDescr(i) for i in varList]
    663663        legend = "Select variables to hold (Will not be varied, even if vary flag is set)"
    664         dlg = G2G.G2MultiChoiceDialog(
    665             G2frame.dataFrame,
     664        dlg = G2G.G2MultiChoiceDialog(G2frame,
    666665            legend,title1,varListlbl,toggle=False,size=(625,400),monoFont=True)
    667666        dlg.CenterOnParent()
     
    684683        if not varList:
    685684            G2frame.ErrorDialog('No variables','There are no variables of type '+vartype,
    686                 parent=G2frame.dataFrame)
     685                parent=G2frame)
    687686            return
    688687#        legend = "Select variables to make equivalent (only one of the variables will be varied when all are set to be varied)"
     
    697696        if not varList:
    698697            G2frame.ErrorDialog('No variables','There are no variables of type '+vartype,
    699                 parent=G2frame.dataFrame)
     698                parent=G2frame)
    700699            return
    701700#        legend = "Select atoms to make equivalent (only one of the atom variables will be varied when all are set to be varied)"
     
    710709        if not varList:
    711710            G2frame.ErrorDialog('No variables','There are no variables of type '+vartype,
    712                 parent=G2frame.dataFrame)
     711                parent=G2frame)
    713712            return
    714713#        legend = "Select atoms to ride (only one of the atom variables will be varied when all are set to be varied)"
     
    723722        if not varList:
    724723            G2frame.ErrorDialog('No variables','There are no variables of type '+vartype,
    725                 parent=G2frame.dataFrame)
     724                parent=G2frame)
    726725            return
    727726#        legend = "Select variables to include in a new variable (the new variable will be varied when all included variables are varied)"
     
    736735        if not varList:
    737736            G2frame.ErrorDialog('No variables','There are no variables of type '+vartype,
    738                 parent=G2frame.dataFrame)
     737                parent=G2frame)
    739738            return
    740739#        legend = "Select variables to include in a constraint equation (the values will be constrainted to equal a specified constant)"
     
    753752        fmt = "{:"+str(l1)+"s} {:"+str(l2)+"s} {:s}"
    754753        varListlbl = [fmt.format(i,*G2obj.VarDescr(i)) for i in varList]       
    755         dlg = G2G.G2SingleChoiceDialog(G2frame.dataFrame,'Select 1st variable:',
     754        dlg = G2G.G2SingleChoiceDialog(G2frame,'Select 1st variable:',
    756755            title1,varListlbl,monoFont=True,size=(625,400))
    757756        dlg.CenterOnParent()
     
    802801        AtNames = Atoms.keys()
    803802        AtNames.sort()
    804         dlg = G2G.G2SingleChoiceDialog(G2frame.dataFrame,'Select 1st atom:',
     803        dlg = G2G.G2SingleChoiceDialog(G2frame,'Select 1st atom:',
    805804            title1,AtNames,monoFont=True,size=(625,400))
    806805        dlg.CenterOnParent()
     
    820819            return
    821820        dlg = G2G.G2MultiChoiceDialog(
    822             G2frame.dataFrame,title2+FrstAtom,
     821            G2frame,title2+FrstAtom,
    823822            'Constrain '+str(FrstAtom)+' with...',AtNames,
    824823            toggle=False,size=(625,400),monoFont=True)
     
    10131012                varname = ""
    10141013            lbl = 'Enter value for each term in constraint; sum = new variable'
    1015             dlg = ConstraintDialog(G2frame.dataFrame,constType,lbl,items,
     1014            dlg = ConstraintDialog(G2frame,constType,lbl,items,
    10161015                                   varname=varname,varyflag=data[name][Id][-2])
    10171016        elif data[name][Id][-1] == 'c':
     
    10201019            constType = 'Constraint'
    10211020            lbl = 'Edit value for each term in constant constraint sum'
    1022             dlg = ConstraintDialog(G2frame.dataFrame,constType,lbl,items)
     1021            dlg = ConstraintDialog(G2frame,constType,lbl,items)
    10231022        elif data[name][Id][-1] == 'e':
    10241023            items = data[name][Id][:-3]
    10251024            constType = 'Equivalence'
    10261025            lbl = 'The following terms are set to be equal:'
    1027             dlg = ConstraintDialog(G2frame.dataFrame,constType,lbl,items,'/')
     1026            dlg = ConstraintDialog(G2frame,constType,lbl,items,'/')
    10281027        else:
    10291028            return
     
    10621061        notebook tab. Called in :func:`OnPageChanged`
    10631062        '''
    1064         if panel.GetSizer(): panel.GetSizer().Clear(True) # N.B. don't use panel.DestroyChildren()
    1065         # because it deletes scrollbars on Mac
     1063        if panel.GetSizer(): panel.GetSizer().Clear(True)
    10661064        Siz = wx.BoxSizer(wx.VERTICAL)
    10671065        Siz.Add((5,5),0)
    1068         Siz.Add(MakeConstraintsSizer(typ,panel))
     1066        Siz.Add(MakeConstraintsSizer(typ,panel),1,wx.EXPAND)
    10691067        panel.SetSizer(Siz,True)
    10701068        Size = Siz.GetMinSize()
     
    10731071        panel.SetSize(Size)
    10741072        panel.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
    1075         Size[1] = min(500,Size[1])
    1076         G2frame.dataFrame.setSizePosLeft(Size)
     1073        panel.Show()
    10771074
    10781075    def OnPageChanged(event):
     
    10831080            page = event.GetSelection()
    10841081        else: # called directly, get current page
    1085             page = G2frame.dataDisplay.GetSelection()
    1086         G2frame.dataDisplay.ChangeSelection(page)
    1087         text = G2frame.dataDisplay.GetPageText(page)
    1088         G2frame.dataFrame.ConstraintEdit.Enable(G2gd.wxID_EQUIVALANCEATOMS,False)
    1089 #        G2frame.dataFrame.ConstraintEdit.Enable(G2gd.wxID_ADDRIDING,False)
     1082            page = G2frame.constr.GetSelection()
     1083        #G2frame.constr.SetSize(G2frame.dataWindow.GetClientSize())    #TODO -almost right
     1084        G2frame.constr.ChangeSelection(page)
     1085        text = G2frame.constr.GetPageText(page)
     1086        G2frame.dataWindow.ConstraintEdit.Enable(G2G.wxID_EQUIVALANCEATOMS,False)
     1087#        G2frame.dataWindow.ConstraintEdit.Enable(G2G.wxID_ADDRIDING,False)
    10901088        if text == 'Histogram/Phase':
    10911089            G2frame.Page = [page,'hap']
     
    10961094        elif text == 'Phase':
    10971095            G2frame.Page = [page,'phs']
    1098             G2frame.dataFrame.ConstraintEdit.Enable(G2gd.wxID_EQUIVALANCEATOMS,True)
    1099 #            G2frame.dataFrame.ConstraintEdit.Enable(G2gd.wxID_ADDRIDING,True)
     1096            G2frame.dataWindow.ConstraintEdit.Enable(G2G.wxID_EQUIVALANCEATOMS,True)
     1097#            G2frame.dataWindow.ConstraintEdit.Enable(G2G.wxID_ADDRIDING,True)
    11001098            if 'DELETED' in str(PhaseConstr):   #seems to be no other way to do this (wx bug)
    11011099                if GSASIIpath.GetConfigValue('debug'):
     
    11101108        'Respond to a "select tab" menu button'
    11111109        try:
    1112             i = (G2gd.wxID_CONSPHASE,
    1113                  G2gd.wxID_CONSHAP,
    1114                  G2gd.wxID_CONSHIST,
    1115                  G2gd.wxID_CONSGLOBAL).index(event.GetId())
    1116             G2frame.dataDisplay.SetSelection(i)
     1110            i = (G2G.wxID_CONSPHASE,
     1111                 G2G.wxID_CONSHAP,
     1112                 G2G.wxID_CONSHIST,
     1113                 G2G.wxID_CONSGLOBAL).index(event.GetId())
     1114            G2frame.constr.SetSelection(i)
    11171115            wx.CallAfter(OnPageChanged,None)
    11181116        except ValueError:
     
    11201118
    11211119    def SetStatusLine(text):
    1122         Status.SetStatusText(text)                                     
    1123        
    1124     if G2frame.dataDisplay:
    1125         G2frame.dataDisplay.Destroy()
    1126     G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ConstraintMenu)
    1127     G2frame.dataFrame.SetLabel('Constraints')
    1128     if not G2frame.dataFrame.GetStatusBar():
    1129         Status = G2frame.dataFrame.CreateStatusBar()
     1120        G2frame.GetStatusBar().SetStatusText(text,1)                                     
     1121       
     1122    G2gd.SetDataMenuBar(G2frame,G2frame.dataWindow.ConstraintMenu)
     1123    #G2frame.SetLabel(G2frame.GetLabel().split('||')[0]+' || '+'Constraints')
     1124    G2frame.SetTitle('Constraints')
    11301125    SetStatusLine('')
    11311126   
    1132     G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ConstraintMenu)
    1133     G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddConstraint, id=G2gd.wxID_CONSTRAINTADD)
    1134     G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddFunction, id=G2gd.wxID_FUNCTADD)
    1135     G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddEquivalence, id=G2gd.wxID_EQUIVADD)
    1136     G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddHold, id=G2gd.wxID_HOLDADD)
    1137     G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddAtomEquiv, id=G2gd.wxID_EQUIVALANCEATOMS)
    1138 #    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddRiding, id=G2gd.wxID_ADDRIDING)
     1127    G2frame.Bind(wx.EVT_MENU, OnAddConstraint, id=G2G.wxID_CONSTRAINTADD)
     1128    G2frame.Bind(wx.EVT_MENU, OnAddFunction, id=G2G.wxID_FUNCTADD)
     1129    G2frame.Bind(wx.EVT_MENU, OnAddEquivalence, id=G2G.wxID_EQUIVADD)
     1130    G2frame.Bind(wx.EVT_MENU, OnAddHold, id=G2G.wxID_HOLDADD)
     1131    G2frame.Bind(wx.EVT_MENU, OnAddAtomEquiv, id=G2G.wxID_EQUIVALANCEATOMS)
     1132#    G2frame.Bind(wx.EVT_MENU, OnAddRiding, id=G2G.wxID_ADDRIDING)
    11391133    # tab commands
    1140     for id in (G2gd.wxID_CONSPHASE,
    1141                G2gd.wxID_CONSHAP,
    1142                G2gd.wxID_CONSHIST,
    1143                G2gd.wxID_CONSGLOBAL):
    1144         G2frame.dataFrame.Bind(wx.EVT_MENU, RaisePage,id=id)
    1145 
    1146     G2frame.dataDisplay = G2G.GSNoteBook(parent=G2frame.dataFrame)
     1134    for id in (G2G.wxID_CONSPHASE,
     1135               G2G.wxID_CONSHAP,
     1136               G2G.wxID_CONSHIST,
     1137               G2G.wxID_CONSGLOBAL):
     1138        G2frame.Bind(wx.EVT_MENU, RaisePage,id=id)
     1139
     1140    #G2frame.constr = G2G.GSNoteBook(parent=G2frame.dataWindow,size=G2frame.dataWindow.GetClientSize())
     1141    G2frame.constr = G2G.GSNoteBook(parent=G2frame.dataWindow)
     1142    G2frame.dataWindow.GetSizer().Add(G2frame.constr,1,wx.ALL|wx.EXPAND)
    11471143    # note that order of pages is hard-coded in RaisePage
    1148     PhaseConstr = wx.ScrolledWindow(G2frame.dataDisplay)
    1149     G2frame.dataDisplay.AddPage(PhaseConstr,'Phase')
    1150     HAPConstr = wx.ScrolledWindow(G2frame.dataDisplay)
    1151     G2frame.dataDisplay.AddPage(HAPConstr,'Histogram/Phase')
    1152     HistConstr = wx.ScrolledWindow(G2frame.dataDisplay)
    1153     G2frame.dataDisplay.AddPage(HistConstr,'Histogram')
    1154     GlobalConstr = wx.ScrolledWindow(G2frame.dataDisplay)
    1155     G2frame.dataDisplay.AddPage(GlobalConstr,'Global')
     1144    PhaseConstr = wx.ScrolledWindow(G2frame.constr)
     1145    G2frame.constr.AddPage(PhaseConstr,'Phase')
     1146    HAPConstr = wx.ScrolledWindow(G2frame.constr)
     1147    G2frame.constr.AddPage(HAPConstr,'Histogram/Phase')
     1148    HistConstr = wx.ScrolledWindow(G2frame.constr)
     1149    G2frame.constr.AddPage(HistConstr,'Histogram')
     1150    GlobalConstr = wx.ScrolledWindow(G2frame.constr)
     1151    G2frame.constr.AddPage(GlobalConstr,'Global')
    11561152    wx.CallAfter(OnPageChanged,None)
    1157     G2frame.dataDisplay.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged)
     1153    G2frame.constr.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged)
    11581154    # validate all the constrants -- should not see any errors here normally
    11591155    allcons = []
     
    11671163    if errmsg:
    11681164        G2frame.ErrorDialog('Constraint Error','Error in constraints:\n'+errmsg,
    1169             parent=G2frame.dataFrame)
     1165            parent=G2frame)
    11701166    elif warnmsg:
    11711167        print 'Unexpected contraint warning:\n',warnmsg
     
    12121208    oAcof = G2lat.cell2A(oldPhase['General']['Cell'][1:7])
    12131209    nAcof = G2lat.cell2A(newPhase['General']['Cell'][1:7])
    1214     item = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Constraints')
    1215     constraints = G2frame.PatternTree.GetItemPyData(item)
     1210    item = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Constraints')
     1211    constraints = G2frame.GPXtree.GetItemPyData(item)