source: trunk/GSASIIimgGUI.py @ 1470

Last change on this file since 1470 was 1470, checked in by vondreele, 9 years ago

fix missing 'outChannels' from imtrl files
fix bug re missing drawingData in MC/SA plotting

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 81.9 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - image data display routines
3########### SVN repository information ###################
4# $Date: 2014-08-19 19:31:12 +0000 (Tue, 19 Aug 2014) $
5# $Author: vondreele $
6# $Revision: 1470 $
7# $URL: trunk/GSASIIimgGUI.py $
8# $Id: GSASIIimgGUI.py 1470 2014-08-19 19:31:12Z vondreele $
9########### SVN repository information ###################
10'''
11*GSASIIimgGUI: Image GUI*
12-------------------------
13
14Control image display and processing
15
16'''
17import wx
18import wx.lib.scrolledpanel as wxscroll
19import matplotlib as mpl
20import math
21import time
22import copy
23import GSASIIpath
24GSASIIpath.SetVersionNumber("$Revision: 1470 $")
25import GSASIIimage as G2img
26import GSASIImath as G2mth
27import GSASIIplot as G2plt
28import GSASIIIO as G2IO
29import GSASIIgrid as G2gd
30import numpy as np
31
32VERY_LIGHT_GREY = wx.Colour(235,235,235)
33WACV = wx.ALIGN_CENTER_VERTICAL
34
35# trig functions in degrees
36sind = lambda x: math.sin(x*math.pi/180.)
37tand = lambda x: math.tan(x*math.pi/180.)
38cosd = lambda x: math.cos(x*math.pi/180.)
39asind = lambda x: 180.*math.asin(x)/math.pi
40   
41################################################################################
42##### Image Data
43################################################################################
44def UpdateImageData(G2frame,data):
45   
46    def OnPixVal(event):
47        Obj = event.GetEventObject()
48        id = Indx[Obj.GetId()]
49        try:
50            data['pixelSize'][id] = min(500,max(10,float(Obj.GetValue())))
51        except ValueError:
52            pass
53        Obj.SetValue('%.3f'%(data['pixelSize'][id]))
54        G2plt.PlotExposedImage(G2frame,newPlot=True,event=event)
55       
56       
57       
58    if G2frame.dataDisplay:
59        G2frame.dataDisplay.Destroy()
60    if not G2frame.dataFrame.GetStatusBar():
61        G2frame.dataFrame.CreateStatusBar()
62    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
63    mainSizer = wx.BoxSizer(wx.VERTICAL)
64    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,
65        label='Do not change anything here unless you are absolutely sure!'),0,WACV)
66    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Image size: %d by %d'%(data['size'][0],data['size'][1])),0,WACV)
67    pixSize = wx.FlexGridSizer(0,4,5,5)
68    pixLabels = [u' Pixel X-dimension (\xb5m)',u' Pixel Y-dimension (\xb5m)']
69    Indx = {}
70    for i,[pixLabel,pix] in enumerate(zip(pixLabels,data['pixelSize'])):
71        pixSize.Add(wx.StaticText(G2frame.dataDisplay,label=pixLabel),0,WACV)
72        pixVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(pix),style=wx.TE_PROCESS_ENTER)
73        Indx[pixVal.GetId()] = i
74        pixVal.Bind(wx.EVT_TEXT_ENTER,OnPixVal)
75        pixVal.Bind(wx.EVT_KILL_FOCUS,OnPixVal)
76        pixSize.Add(pixVal,0,WACV)
77    mainSizer.Add(pixSize,0)
78   
79    mainSizer.Layout()   
80    G2frame.dataDisplay.SetSizer(mainSizer)
81    fitSize = mainSizer.Fit(G2frame.dataFrame)
82    G2frame.dataFrame.setSizePosLeft(fitSize)
83    G2frame.dataDisplay.SetSize(fitSize)
84
85################################################################################
86##### Image Controls
87################################################################################                   
88def UpdateImageControls(G2frame,data,masks):
89    '''Shows and handles the controls on the "Image Controls"
90    data tree entry
91    '''
92    import ImageCalibrants as calFile
93#patch
94    if 'GonioAngles' not in data:
95        data['GonioAngles'] = [0.,0.,0.]
96    if 'DetDepth' not in data:
97        data['DetDepth'] = 0.
98        data['DetDepthRef'] = False
99    if 'SampleAbs' not in data:
100        data['SampleShape'] = 'Cylinder'
101        data['SampleAbs'] = [0.0,False]
102    if 'binType' not in data:
103        if 'PWDR' in data['type']:
104            data['binType'] = '2-theta'
105        elif 'SASD' in data['type']:
106            data['binType'] = 'log(q)'
107#end patch
108   
109# Menu items
110           
111    def OnCalibrate(event):       
112        G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=True)   
113        G2frame.dataFrame.GetStatusBar().SetStatusText('Select > 4 points on 1st used ring; LB to pick, RB on point to delete else RB to finish')
114        G2frame.ifGetRing = True
115       
116    def OnRecalibrate(event):
117        G2img.ImageRecalibrate(G2frame,data,masks)
118        UpdateImageControls(G2frame,data,masks)
119       
120    def OnClearCalib(event):
121        data['ring'] = []
122        data['rings'] = []
123        data['ellipses'] = []
124#        G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=False)   
125        G2plt.PlotExposedImage(G2frame,event=event)
126           
127    def OnIntegrate(event):
128        blkSize = 128   #this seems to be optimal; will break in polymask if >1024
129        Nx,Ny = data['size']
130        nXBlks = (Nx-1)/blkSize+1
131        nYBlks = (Ny-1)/blkSize+1
132        Nup = nXBlks*nYBlks*3+3
133        dlg = wx.ProgressDialog("Elapsed time","2D image integration",Nup,
134            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE)
135        try:
136            sumImg = G2frame.ImageZ
137            darkImg,darkScale = data['dark image']
138            if darkImg:
139                Did = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, darkImg)
140                Npix,imagefile = G2frame.PatternTree.GetItemPyData(Did)
141                darkImage = G2IO.GetImageData(G2frame,imagefile,True)
142                sumImg += darkImage*darkScale
143            backImg,backScale = data['background image']           
144            if backImg:     #ignores any transmission effect in the background image
145                Bid = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, backImg)
146                Npix,imagefile = G2frame.PatternTree.GetItemPyData(Bid)
147                backImage = G2IO.GetImageData(G2frame,imagefile,True)
148                Bdata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Bid,'Image Controls'))
149                BdarkImg,BdarkScale = Bdata['dark image']
150                if BdarkImg:
151                    BDid = G2gd.GetPatternTreeItemId(G2frame, G2frame.root,BdarkImg)
152                    Npix,imagefile = G2frame.PatternTree.GetItemPyData(BDid)
153                    BdarkImage = G2IO.GetImageData(G2frame,imagefile,True)
154                    backImage += BdarkImage*BdarkScale               
155                sumImg += backImage*backScale
156            G2frame.Integrate = G2img.ImageIntegrate(sumImg,data,masks,blkSize,dlg)
157#            G2plt.PlotIntegration(G2frame,newPlot=True)
158            Id = G2IO.SaveIntegration(G2frame,G2frame.PickId,data)
159            G2frame.PatternId = Id
160            G2frame.PatternTree.SelectItem(Id)
161            G2frame.PatternTree.Expand(Id)
162        finally:
163            dlg.Destroy()
164        for item in G2frame.MakePDF: item.Enable(True)
165       
166    def OnIntegrateAll(event):
167        print 'integrate all'
168        TextList = [[False,'All IMG',0]]
169        Names = []
170        if G2frame.PatternTree.GetCount():
171            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
172            while id:
173                name = G2frame.PatternTree.GetItemText(id)
174                Names.append(name)
175                if 'IMG' in name:
176                    TextList.append([False,name,id])
177                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
178            if len(TextList) == 1:
179                G2frame.ErrorDialog('Nothing to integrate','There must some "IMG" patterns')
180                return
181            dlg = G2frame.CopyDialog(G2frame,'Image integration controls','Select images to integrate:',TextList)
182            try:
183                if dlg.ShowModal() == wx.ID_OK:
184                    result = dlg.GetData()
185                    if result[0][0]:                    #the 'All IMG' is True
186                        result = TextList[1:]
187                        for item in result: item[0] = True
188                    G2frame.EnablePlot = False
189                    for item in result:
190                        ifintegrate,name,id = item
191                        if ifintegrate:
192                            Id = G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls')
193                            Data = G2frame.PatternTree.GetItemPyData(Id)
194                            blkSize = 128   #this seems to be optimal; will break in polymask if >1024
195                            Nx,Ny = Data['size']
196                            nXBlks = (Nx-1)/blkSize+1
197                            nYBlks = (Ny-1)/blkSize+1
198                            Nup = nXBlks*nYBlks*3+3
199                            dlgp = wx.ProgressDialog("Elapsed time","2D image integration",Nup,
200                                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE)
201                            try:
202                                id = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, name)
203                                Npix,imagefile = G2frame.PatternTree.GetItemPyData(id)
204                                image = G2IO.GetImageData(G2frame,imagefile,True)
205                                backImage = []
206                                if Data['background image'][0]:
207                                    backImg = Data['background image'][0]
208                                    backScale = Data['background image'][1]
209                                    id = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, backImg)
210                                    Npix,imagefile = G2frame.PatternTree.GetItemPyData(id)
211                                    backImage = G2IO.GetImageData(G2frame,imagefile,True)*backScale
212                                try:
213                                    Masks = G2frame.PatternTree.GetItemPyData(
214                                        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
215                                except TypeError:       #missing Masks
216                                    Imin,Imax = Data['Range']
217                                    Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Frames':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
218                                    G2frame.PatternTree.SetItemPyData(
219                                        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'),Masks)
220                                if len(backImage):                               
221                                    G2frame.Integrate = G2img.ImageIntegrate(image+backImage,Data,Masks,blkSize,dlgp)
222                                else:
223                                    G2frame.Integrate = G2img.ImageIntegrate(image,Data,Masks,blkSize,dlgp)
224                                pId = G2IO.SaveIntegration(G2frame,Id,Data)
225                            finally:
226                                dlgp.Destroy()
227                    else:
228                        G2frame.EnablePlot = True
229                        G2frame.PatternTree.SelectItem(pId)
230                        G2frame.PatternTree.Expand(pId)
231                        G2frame.PatternId = pId
232                       
233            finally:
234                dlg.Destroy()
235       
236    def OnCopyControls(event):
237        TextList = [[False,'All IMG',0]]
238        Names = []
239        if G2frame.PatternTree.GetCount():
240            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
241            while id:
242                name = G2frame.PatternTree.GetItemText(id)
243                Names.append(name)
244                if 'IMG' in name:
245                    if id == G2frame.Image:
246                        Source = name
247                        Data = copy.deepcopy(data)
248#                        Data = copy.deepcopy(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls')))
249                        Data['showLines'] = True
250                        Data['ring'] = []
251                        Data['rings'] = []
252                        Data['ellipses'] = []
253                        Data['setDefault'] = False
254                    else:
255                        TextList.append([False,name,id])
256                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
257            if len(TextList) == 1:
258                G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "IMG" pattern')
259                return
260            dlg = G2frame.CopyDialog(G2frame,'Copy image controls','Copy controls from '+Source+' to:',TextList)
261            try:
262                if dlg.ShowModal() == wx.ID_OK:
263                    result = dlg.GetData()
264                    if result[0][0]:
265                        result = TextList[1:]
266                        for item in result: item[0] = True
267                    for i,item in enumerate(result):
268                        ifcopy,name,id = item
269                        if ifcopy:
270                            oldData = copy.deepcopy(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls')))
271                            Data['range'] = oldData['range']
272                            Data['size'] = oldData['size']
273                            Data['GonioAngles'] = oldData.get('GonioAngles', [0.,0.,0.])
274                            Data['ring'] = []
275                            Data['rings'] = []
276                            Data['ellipses'] = []
277                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls'),copy.deepcopy(Data))
278            finally:
279                dlg.Destroy()
280                G2frame.PatternTree.SelectItem(G2frame.PickId)
281               
282    def OnSaveControls(event):
283        dlg = wx.FileDialog(G2frame, 'Choose image controls file', '.', '', 
284            'image control files (*.imctrl)|*.imctrl',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
285        try:
286            if dlg.ShowModal() == wx.ID_OK:
287                filename = dlg.GetPath()
288                File = open(filename,'w')
289                save = {}
290                keys = ['type','wavelength','calibrant','distance','center',
291                    'tilt','rotation','azmthOff','fullIntegrate','LRazimuth',
292                    'IOtth','outChannels','outAzimuths','invert_x','invert_y','DetDepth',
293                    'calibskip','pixLimit','cutoff','calibdmin','chisq',
294                    'binType','SampleShape','PolaVal','SampleAbs','dark image','background image']
295                for key in keys:
296                    if key not in data:     #uncalibrated!
297                        continue
298                    File.write(key+':'+str(data[key])+'\n')
299                File.close()
300        finally:
301            dlg.Destroy()
302       
303    def OnLoadControls(event):
304        cntlList = ['wavelength','distance','tilt','invert_x','invert_y','type',
305            'fullIntegrate','outChannels','outAzimuths','LRazimuth','IOtth','azmthOff','DetDepth',
306            'calibskip','pixLimit','cutoff','calibdmin','chisq',
307            'PolaVal','SampleAbs','dark image','background image']
308        dlg = wx.FileDialog(G2frame, 'Choose image controls file', '.', '', 
309            'image control files (*.imctrl)|*.imctrl',wx.OPEN|wx.CHANGE_DIR)
310        try:
311            if dlg.ShowModal() == wx.ID_OK:
312                filename = dlg.GetPath()
313                File = open(filename,'r')
314                save = {}
315                S = File.readline()
316                while S:
317                    if S[0] == '#':
318                        S = File.readline()
319                        continue
320                    [key,val] = S[:-1].split(':')
321                    if key in ['type','calibrant','binType','SampleShape',]:    #strings
322                        save[key] = val
323                    elif key in ['rotation']:
324                        save[key] = float(val)
325                    elif key in ['center',]:
326                        if ',' in val:
327                            save[key] = eval(val)
328                        else:
329                            vals = val.strip('[] ').split()
330                            save[key] = [float(vals[0]),float(vals[1])] 
331                    elif key in cntlList:
332                        save[key] = eval(val)
333                    S = File.readline()
334                data.update(save)
335                G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'),copy.deepcopy(data))
336                UpdateImageControls(G2frame,data,masks)
337                G2plt.PlotExposedImage(G2frame,event=event)
338               
339                File.close()
340        finally:
341            dlg.Destroy()
342           
343# Sizers
344                                       
345    def ComboSizer():
346
347        def OnDataType(event):
348            data['type'] = typeSel.GetValue()[:4]
349            if 'SASD' in data['type']:
350                data['SampleAbs'][0] = np.exp(-data['SampleAbs'][0]) #switch from muT to trans!
351                if data['binType'] == '2-theta': data['binType'] = 'log(q)'  #switch default bin type
352            elif 'PWDR' in data['type']:
353                data['SampleAbs'][0] = -np.log(data['SampleAbs'][0])  #switch from trans to muT!
354                if data['binType'] == 'log(q)': data['binType'] = '2-theta'  #switch default bin type                 
355            wx.CallAfter(UpdateImageControls,G2frame,data,masks)
356   
357        def OnNewColorBar(event):
358            data['color'] = colSel.GetValue()
359            G2plt.PlotExposedImage(G2frame,event=event)
360       
361        def OnAzmthOff(event):
362            try:
363                azmthoff = float(azmthOff.GetValue())
364                data['azmthOff'] = azmthoff
365            except ValueError:
366                pass
367            azmthOff.SetValue("%.2f"%(data['azmthOff']))          #reset in case of error 
368            G2plt.PlotExposedImage(G2frame,event=event)
369       
370        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
371        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Type of image data: '),0,WACV)
372        typeSel = wx.ComboBox(parent=G2frame.dataDisplay,value=typeDict[data['type']],choices=typeList,
373            style=wx.CB_READONLY|wx.CB_DROPDOWN)
374        typeSel.SetValue(data['type'])
375        typeSel.Bind(wx.EVT_COMBOBOX, OnDataType)
376        comboSizer.Add(typeSel,0,WACV)
377        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Color bar '),0,WACV)
378        colSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['color'],choices=colorList,
379            style=wx.CB_READONLY|wx.CB_DROPDOWN|wx.CB_SORT)
380        colSel.Bind(wx.EVT_COMBOBOX, OnNewColorBar)
381        comboSizer.Add(colSel,0,WACV)
382        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Azimuth offset '),0,WACV)
383        azmthOff = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f" % (data['azmthOff'])),
384            style=wx.TE_PROCESS_ENTER)
385        azmthOff.Bind(wx.EVT_TEXT_ENTER,OnAzmthOff)
386        azmthOff.Bind(wx.EVT_KILL_FOCUS,OnAzmthOff)
387        comboSizer.Add(azmthOff,0,WACV)
388        return comboSizer
389       
390    def MaxSizer():
391               
392        def OnMaxVal(event):
393            try:
394                value = min(data['range'][0][1],int(maxVal.GetValue()))
395                if value < data['range'][1][0]+1:
396                    raise ValueError
397                data['range'][1][1] = value
398            except ValueError:
399                pass
400            maxVal.SetValue('%.0f'%(data['range'][1][1]))
401            DeltOne = data['range'][1][1]-max(0.0,data['range'][0][0])
402            sqrtDeltOne = math.sqrt(DeltOne)
403            maxSel.SetValue(int(100*sqrtDeltOne/sqrtDeltZero))
404            minSel.SetValue(int(100*(data['range'][1][0]/DeltOne)))
405            G2plt.PlotExposedImage(G2frame,event=event)
406           
407        def OnMinVal(event):
408            try:
409                value = int(minVal.GetValue())
410                if value > data['range'][1][1]-1:
411                    raise ValueError
412                data['range'][1][0] = value
413            except ValueError:
414                pass
415            minVal.SetValue('%.0f'%(data['range'][1][0]))
416            minSel.SetValue(int(100*(data['range'][1][0]-max(0.0,data['range'][0][0]))/DeltOne))
417            G2plt.PlotExposedImage(G2frame,event=event)
418           
419        def OnMaxSlider(event):
420            sqrtDeltZero = math.sqrt(data['range'][0][1])
421            imax = int(maxSel.GetValue())*sqrtDeltZero/100.
422            data['range'][1][1] = imax**2
423            data['range'][1][0] = max(0.0,min(data['range'][1][1]-1,data['range'][1][0]))
424            DeltOne = max(1.0,data['range'][1][1]-data['range'][1][0])
425            minSel.SetValue(int(100*(data['range'][1][0]/DeltOne)))
426            maxVal.SetValue('%.0f'%(data['range'][1][1]))
427            G2plt.PlotExposedImage(G2frame,event=event)
428           
429        def OnMinSlider(event):
430            DeltOne = data['range'][1][1]-data['range'][1][0]
431            imin = int(minSel.GetValue())*DeltOne/100.
432            data['range'][1][0] = max(0.0,min(data['range'][1][1]-1,imin))
433            minVal.SetValue('%.0f'%(data['range'][1][0]))
434            G2plt.PlotExposedImage(G2frame,event=event)
435           
436        maxSizer = wx.FlexGridSizer(0,3,0,5)
437        maxSizer.AddGrowableCol(1,1)
438        maxSizer.SetFlexibleDirection(wx.HORIZONTAL)
439        sqrtDeltZero = math.sqrt(data['range'][0][1]-max(0.0,data['range'][0][0]))
440        DeltOne = data['range'][1][1]-max(0.0,data['range'][0][0])
441        sqrtDeltOne = math.sqrt(DeltOne)
442        maxSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max intensity'),0,WACV)
443        maxSel = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
444            value=int(100*sqrtDeltOne/sqrtDeltZero))
445        maxSizer.Add(maxSel,1,wx.EXPAND)
446        maxSel.Bind(wx.EVT_SLIDER, OnMaxSlider)
447        maxVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.0f'%(data['range'][1][1]))
448        maxVal.Bind(wx.EVT_TEXT_ENTER,OnMaxVal)   
449        maxVal.Bind(wx.EVT_KILL_FOCUS,OnMaxVal)
450        maxSizer.Add(maxVal,0,WACV)   
451        maxSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Min intensity'),0,WACV)
452        minSel = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
453            value=int(100*(data['range'][1][0]-max(0.0,data['range'][0][0]))/DeltOne))
454        maxSizer.Add(minSel,1,wx.EXPAND)
455        minSel.Bind(wx.EVT_SLIDER, OnMinSlider)
456        minVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.0f'%(data['range'][1][0]))
457        minVal.Bind(wx.EVT_TEXT_ENTER,OnMinVal)   
458        minVal.Bind(wx.EVT_KILL_FOCUS,OnMinVal)
459        maxSizer.Add(minVal,0,WACV)
460        return maxSizer
461       
462    def CalibCoeffSizer():
463       
464        def OnWavelength(event):
465            try:
466                wave = float(waveSel.GetValue())
467                if wave < .01:
468                    raise ValueError
469                data['wavelength'] = wave
470            except ValueError:
471                pass
472            waveSel.SetValue("%7.5f" % (data['wavelength']))          #reset in case of error
473           
474        def OnDetDepthRef(event):
475            data['DetDepthRef'] = penSel.GetValue()
476           
477        def OnDetDepth(event):
478            try:
479                data['DetDepth'] = float(penVal.GetValue())
480            except ValueError:
481                pass
482            penVal.SetValue("%6.3f" % (data['DetDepth']))          #reset in case of error                     
483           
484        calibSizer = wx.FlexGridSizer(0,2,5,5)
485        calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calibration coefficients'),0,WACV)   
486        calibSizer.Add((5,0),0)
487        cent = data['center']
488        for axis,cnt in zip(['X','Y'],cent):
489            calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Beam center '+axis),0,WACV)
490            centText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%7.2f" % (cnt)),style=wx.TE_READONLY)
491            centText.SetBackgroundColour(VERY_LIGHT_GREY)
492            calibSizer.Add(centText,0,WACV)       
493        calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Wavelength'),0,WACV)
494        waveSel = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%7.5f" % (data['wavelength'])),
495            style=wx.TE_PROCESS_ENTER)
496        waveSel.Bind(wx.EVT_TEXT_ENTER,OnWavelength)
497        waveSel.Bind(wx.EVT_KILL_FOCUS,OnWavelength)
498        calibSizer.Add(waveSel,0,WACV)             
499        calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Distance'),0,WACV)
500        distSel = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%8.2f"%(data['distance'])),style=wx.TE_READONLY)
501        distSel.SetBackgroundColour(VERY_LIGHT_GREY)
502        calibSizer.Add(distSel,0,WACV)
503        calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Tilt angle'),0,WACV)
504        tiltSel = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%9.3f"%(data['tilt'])),style=wx.TE_READONLY)
505        tiltSel.SetBackgroundColour(VERY_LIGHT_GREY)
506        calibSizer.Add(tiltSel,0,WACV)
507        calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Tilt rotation'),0,WACV)
508        rotSel = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%9.3f"%(data['rotation'])),style=wx.TE_READONLY)
509        rotSel.SetBackgroundColour(VERY_LIGHT_GREY)
510        calibSizer.Add(rotSel,0,WACV)
511        if 'PWDR' in data['type']:
512            penSel = wx.CheckBox(parent=G2frame.dataDisplay,label='Penetration?')
513            calibSizer.Add(penSel,0,WACV)
514            penSel.Bind(wx.EVT_CHECKBOX, OnDetDepthRef)
515            penSel.SetValue(data['DetDepthRef'])
516            penVal = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%6.5f" % (data['DetDepth'])),
517                style=wx.TE_PROCESS_ENTER)
518            penVal.Bind(wx.EVT_TEXT_ENTER,OnDetDepth)
519            penVal.Bind(wx.EVT_KILL_FOCUS,OnDetDepth)
520            calibSizer.Add(penVal,0,WACV)             
521       
522        return calibSizer
523   
524    def IntegrateSizer():
525       
526        def OnNewBinType(event):
527            data['binType'] = binSel.GetValue()
528       
529        def OnIOtth(event):
530            Ltth = max(float(G2frame.InnerTth.GetValue()),0.001)
531            Utth = float(G2frame.OuterTth.GetValue())
532            if Ltth > Utth:
533                Ltth,Utth = Utth,Ltth
534            data['IOtth'] = [Ltth,Utth]
535            G2frame.InnerTth.SetValue("%8.3f" % (Ltth))
536            G2frame.OuterTth.SetValue("%8.2f" % (Utth))
537            G2plt.PlotExposedImage(G2frame,event=event)
538       
539        def OnLRazim(event):
540            Lazm = int(G2frame.Lazim.GetValue())%360
541            Razm = int(G2frame.Razim.GetValue())%360
542            if Lazm > Razm:
543                Razm += 360
544            if data['fullIntegrate']:
545                Razm = Lazm+360
546            G2frame.Lazim.SetValue("%6d" % (Lazm))
547            G2frame.Razim.SetValue("%6d" % (Razm))
548            data['LRazimuth'] = [Lazm,Razm]
549            G2plt.PlotExposedImage(G2frame,event=event)
550       
551        def OnNumOutChans(event):
552            try:
553                numChans = int(outChan.GetValue())
554                if numChans < 10:
555                    raise ValueError
556                data['outChannels'] = numChans
557            except ValueError:
558                pass
559            outChan.SetValue(str(data['outChannels']))          #reset in case of error       
560       
561        def OnNumOutAzms(event):
562            try:
563                numAzms = int(outAzim.GetValue())
564                if numAzms < 1:
565                    raise ValueError
566                data['outAzimuths'] = numAzms           
567            except ValueError:
568                pass
569            outAzim.SetValue(str(data['outAzimuths']))          #reset in case of error       
570            G2plt.PlotExposedImage(G2frame,event=event)
571       
572        def OnOblique(event):
573            if data['Oblique'][1]:
574                data['Oblique'][1] = False
575            else:
576                data['Oblique'][1] = True
577               
578        def OnObliqVal(event):
579            try:
580                value = float(obliqVal.GetValue())
581                if 0.01 <= value <= 0.99:
582                    data['Oblique'][0] = value
583                else:
584                    raise ValueError
585            except ValueError:
586                pass
587            obliqVal.SetValue('%.3f'%(data['Oblique'][0]))
588                           
589        def OnSamAbs(event):
590            if data['SampleAbs'][1]:
591                data['SampleAbs'][1] = False
592            else:
593                data['SampleAbs'][1] = True
594               
595        def OnSamAbsVal(event):
596            try:
597                value = float(samabsVal.GetValue())
598                minmax = [0.,2.]
599                if 'SASD' in data['type']:
600                    minmax = [.05,1.0]
601                if minmax[0] <= value <= minmax[1]:
602                    data['SampleAbs'][0] = value
603                else:
604                    raise ValueError
605            except ValueError:
606                pass
607            samabsVal.SetValue('%.3f'%(data['SampleAbs'][0]))
608                           
609        def OnShowLines(event):
610            if data['showLines']:
611                data['showLines'] = False
612            else:
613                data['showLines'] = True
614            G2plt.PlotExposedImage(G2frame,event=event)
615           
616        def OnFullIntegrate(event):
617            Lazm =int(G2frame.Lazim.GetValue())
618            if data['fullIntegrate']:
619                data['fullIntegrate'] = False
620                data['LRazimuth'] = [Lazm,Lazm+20]
621            else:
622                data['fullIntegrate'] = True
623                data['LRazimuth'] = [Lazm,Lazm+360]
624            UpdateImageControls(G2frame,data,masks)
625            G2plt.PlotExposedImage(G2frame,event=event)
626           
627        def OnSetDefault(event):
628            if data['setDefault']:
629                G2frame.imageDefault = {}
630                data['setDefault'] = False
631            else:
632                G2frame.imageDefault = copy.copy(data)
633                data['setDefault'] = True
634               
635        def OnCenterAzm(event):
636            if data['centerAzm']:
637                data['centerAzm'] = False
638            else:
639                data['centerAzm'] = True
640            G2plt.PlotExposedImage(G2frame,event=event)
641               
642        def OnApplyPola(event):
643            if data['PolaVal'][1]:
644                data['PolaVal'][1] = False
645            else:
646                data['PolaVal'][1] = True
647               
648        def OnPolaVal(event):
649            try:
650                value = float(polaVal.GetValue())
651                if 0.001 <= value <= 0.999:
652                    data['PolaVal'][0] = value
653                else:
654                    raise ValueError
655            except ValueError:
656                pass
657            polaVal.SetValue('%.3f'%(data['PolaVal'][0]))
658                           
659        dataSizer = wx.FlexGridSizer(0,2,5,3)
660        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Integration coefficients'),0,WACV)   
661        dataSizer.Add((5,0),0)
662        if 'PWDR' in data['type']:
663            binChoice = ['2-theta','q']
664        elif 'SASD' in data['type']:
665            binChoice = ['q','log(q)']
666        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Bin style: Constant step bins in'),0,WACV)           
667        binSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['binType'],choices=binChoice,
668            style=wx.CB_READONLY|wx.CB_DROPDOWN|wx.CB_SORT)
669        binSel.Bind(wx.EVT_COMBOBOX, OnNewBinType)
670        dataSizer.Add(binSel,0,WACV)
671        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Inner/Outer 2-theta'),0,WACV)           
672        IOtth = data['IOtth']
673        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
674        G2frame.InnerTth = wx.TextCtrl(parent=G2frame.dataDisplay,
675            value=("%8.3f" % (IOtth[0])),style=wx.TE_PROCESS_ENTER)
676        G2frame.InnerTth.Bind(wx.EVT_TEXT_ENTER,OnIOtth)
677        G2frame.InnerTth.Bind(wx.EVT_KILL_FOCUS,OnIOtth)
678        littleSizer.Add(G2frame.InnerTth,0,WACV)
679        G2frame.OuterTth = wx.TextCtrl(parent=G2frame.dataDisplay,
680            value=("%8.2f" % (IOtth[1])),style=wx.TE_PROCESS_ENTER)
681        G2frame.OuterTth.Bind(wx.EVT_TEXT_ENTER,OnIOtth)
682        G2frame.OuterTth.Bind(wx.EVT_KILL_FOCUS,OnIOtth)
683        littleSizer.Add(G2frame.OuterTth,0,WACV)
684        dataSizer.Add(littleSizer,0,)
685        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start/End azimuth'),0,WACV)
686        LRazim = data['LRazimuth']
687        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
688        G2frame.Lazim = wx.TextCtrl(parent=G2frame.dataDisplay,
689            value=("%6d" % (LRazim[0])),style=wx.TE_PROCESS_ENTER)
690        G2frame.Lazim.Bind(wx.EVT_TEXT_ENTER,OnLRazim)
691        G2frame.Lazim.Bind(wx.EVT_KILL_FOCUS,OnLRazim)
692        littleSizer.Add(G2frame.Lazim,0,WACV)
693        G2frame.Razim = wx.TextCtrl(parent=G2frame.dataDisplay,
694            value=("%6d" % (LRazim[1])),style=wx.TE_PROCESS_ENTER)
695        G2frame.Razim.Bind(wx.EVT_TEXT_ENTER,OnLRazim)
696        G2frame.Razim.Bind(wx.EVT_KILL_FOCUS,OnLRazim)
697        if data['fullIntegrate']:
698            G2frame.Razim.Enable(False)
699            G2frame.Razim.SetBackgroundColour(VERY_LIGHT_GREY)
700            G2frame.Razim.SetValue("%6d" % (LRazim[0]+360))
701        littleSizer.Add(G2frame.Razim,0,WACV)
702        dataSizer.Add(littleSizer,0,)
703        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' No. 2-theta/azimuth bins'),0,WACV)
704        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
705        outChan = wx.TextCtrl(parent=G2frame.dataDisplay,value=str(data['outChannels']),style=wx.TE_PROCESS_ENTER)
706        outChan.Bind(wx.EVT_TEXT_ENTER,OnNumOutChans)
707        outChan.Bind(wx.EVT_KILL_FOCUS,OnNumOutChans)
708        littleSizer.Add(outChan,0,WACV)
709        outAzim = wx.TextCtrl(parent=G2frame.dataDisplay,value=str(data['outAzimuths']),style=wx.TE_PROCESS_ENTER)
710        outAzim.Bind(wx.EVT_TEXT_ENTER,OnNumOutAzms)
711        outAzim.Bind(wx.EVT_KILL_FOCUS,OnNumOutAzms)
712        littleSizer.Add(outAzim,0,WACV)
713        dataSizer.Add(littleSizer,0,)
714        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
715        samabs = wx.CheckBox(parent=G2frame.dataDisplay,label='Apply sample absorption?')
716        dataSizer.Add(samabs,0,WACV)
717        samabs.Bind(wx.EVT_CHECKBOX, OnSamAbs)
718        samabs.SetValue(data['SampleAbs'][1])
719        if 'PWDR' in data['type']:
720            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='mu/R (0.00-2.0) '),0,WACV)
721        elif 'SASD' in data['type']:
722            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='transmission '),0,WACV)
723        samabsVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.3f'%(data['SampleAbs'][0]),style=wx.TE_PROCESS_ENTER)           
724        samabsVal.Bind(wx.EVT_TEXT_ENTER,OnSamAbsVal)
725        samabsVal.Bind(wx.EVT_KILL_FOCUS,OnSamAbsVal)
726        littleSizer.Add(samabsVal,0,WACV)
727        dataSizer.Add(littleSizer,0,)
728        if 'PWDR' in data['type']:
729            littleSizer = wx.BoxSizer(wx.HORIZONTAL)
730            oblique = wx.CheckBox(parent=G2frame.dataDisplay,label='Apply detector absorption?')
731            dataSizer.Add(oblique,0,WACV)
732            oblique.Bind(wx.EVT_CHECKBOX, OnOblique)
733            oblique.SetValue(data['Oblique'][1])
734            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Value (0.01-0.99)  '),0,WACV)
735            obliqVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.3f'%(data['Oblique'][0]),style=wx.TE_PROCESS_ENTER)
736            obliqVal.Bind(wx.EVT_TEXT_ENTER,OnObliqVal)
737            obliqVal.Bind(wx.EVT_KILL_FOCUS,OnObliqVal)
738            littleSizer.Add(obliqVal,0,WACV)
739            dataSizer.Add(littleSizer,0,)
740        if 'SASD' in data['type']:
741            littleSizer = wx.BoxSizer(wx.HORIZONTAL)
742            setPolariz = wx.CheckBox(parent=G2frame.dataDisplay,label='Apply polarization?')
743            dataSizer.Add(setPolariz,0,WACV)
744            setPolariz.Bind(wx.EVT_CHECKBOX, OnApplyPola)
745            setPolariz.SetValue(data['PolaVal'][1])
746            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Value (0.001-0.999)  '),0,WACV)
747            polaVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.3f'%(data['PolaVal'][0]),
748                style=wx.TE_PROCESS_ENTER)
749            polaVal.Bind(wx.EVT_TEXT_ENTER,OnPolaVal)
750            polaVal.Bind(wx.EVT_KILL_FOCUS,OnPolaVal)
751            littleSizer.Add(polaVal,0,WACV)
752            dataSizer.Add(littleSizer,0,)
753       
754        showLines = wx.CheckBox(parent=G2frame.dataDisplay,label='Show integration limits?')
755        dataSizer.Add(showLines,0,WACV)
756        showLines.Bind(wx.EVT_CHECKBOX, OnShowLines)
757        showLines.SetValue(data['showLines'])
758        fullIntegrate = wx.CheckBox(parent=G2frame.dataDisplay,label='Do full integration?')
759        dataSizer.Add(fullIntegrate,0,WACV)
760        fullIntegrate.Bind(wx.EVT_CHECKBOX, OnFullIntegrate)
761        fullIntegrate.SetValue(data['fullIntegrate'])
762        setDefault = wx.CheckBox(parent=G2frame.dataDisplay,label='Use as default for all images?')
763        dataSizer.Add(setDefault,0,WACV)
764        setDefault.Bind(wx.EVT_CHECKBOX, OnSetDefault)
765        setDefault.SetValue(data['setDefault'])
766        centerAzm = wx.CheckBox(parent=G2frame.dataDisplay,label='Azimuth at bin center?')
767        dataSizer.Add(centerAzm,0,WACV)
768        centerAzm.Bind(wx.EVT_CHECKBOX, OnCenterAzm)
769        centerAzm.SetValue(data['centerAzm'])
770        return dataSizer
771       
772    def BackSizer():
773       
774        def OnBackImage(event):
775            data['background image'][0] = backImage.GetValue()
776           
777        def OnDarkImage(event):
778            data['dark image'][0] = darkImage.GetValue()
779            G2plt.PlotExposedImage(G2frame,event=event)
780
781        def OnBackMult(event):
782            try:
783                mult = float(backMult.GetValue())
784                data['background image'][1] = mult
785            except ValueError:
786                pass
787            backMult.SetValue("%.3f" % (data['background image'][1]))          #reset in case of error
788       
789        def OnDarkMult(event):
790            try:
791                mult = float(darkMult.GetValue())
792                data['dark image'][1] = mult
793            except ValueError:
794                pass
795            darkMult.SetValue("%.3f" % (data['dark image'][1]))          #reset in case of error
796            G2plt.PlotExposedImage(G2frame,event=event)
797       
798        backSizer = wx.FlexGridSizer(0,4,5,5)
799
800        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Dark image'),0,WACV)
801        Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
802        darkImage = wx.ComboBox(parent=G2frame.dataDisplay,value=data['dark image'][0],choices=Choices,
803            style=wx.CB_READONLY|wx.CB_DROPDOWN)
804        darkImage.Bind(wx.EVT_COMBOBOX,OnDarkImage)
805        backSizer.Add(darkImage)
806        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' multiplier'),0,WACV)
807        darkMult =  wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (data['dark image'][1])),
808            style=wx.TE_PROCESS_ENTER)
809        darkMult.Bind(wx.EVT_TEXT_ENTER,OnDarkMult)
810        darkMult.Bind(wx.EVT_KILL_FOCUS,OnDarkMult)
811        backSizer.Add(darkMult,0,WACV)
812
813        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background image'),0,WACV)
814        Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
815        backImage = wx.ComboBox(parent=G2frame.dataDisplay,value=data['background image'][0],choices=Choices,
816            style=wx.CB_READONLY|wx.CB_DROPDOWN)
817        backImage.Bind(wx.EVT_COMBOBOX,OnBackImage)
818        backSizer.Add(backImage)
819        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' multiplier'),0,WACV)
820        backMult =  wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (data['background image'][1])),
821            style=wx.TE_PROCESS_ENTER)
822        backMult.Bind(wx.EVT_TEXT_ENTER,OnBackMult)
823        backMult.Bind(wx.EVT_KILL_FOCUS,OnBackMult)
824        backSizer.Add(backMult,0,WACV)
825        return backSizer
826                       
827    def CalibSizer():
828               
829        def OnNewCalibrant(event):
830            data['calibrant'] = calSel.GetValue()
831            data['calibskip'] = calFile.Calibrants[data['calibrant']][3]
832            limits = calFile.Calibrants[data['calibrant']][4]
833            data['calibdmin'],data['pixLimit'],data['cutoff'] = limits
834            pixLimit.SetValue(str(limits[1]))
835            cutOff.SetValue('%.1f'%(limits[2]))
836            calibSkip.SetValue(str(data['calibskip']))
837            calibDmin.SetValue('%.1f'%(limits[0]))
838           
839        def OnCalibSkip(event):
840            data['calibskip'] = int(calibSkip.GetValue())
841           
842        def OnCalibDmin(event):
843            try:
844                dmin = float(calibDmin.GetValue())
845                if dmin < 0.25:
846                    raise ValueError
847                data['calibdmin'] = dmin
848            except ValueError:
849                pass
850            calibDmin.SetValue("%.2f"%(data['calibdmin']))          #reset in case of error 
851                   
852        def OnCutOff(event):
853            try:
854                cutoff = float(cutOff.GetValue())
855                if cutoff < 0.1:
856                    raise ValueError
857                data['cutoff'] = cutoff
858            except ValueError:
859                pass
860            cutOff.SetValue("%.1f"%(data['cutoff']))          #reset in case of error 
861       
862        def OnPixLimit(event):
863            data['pixLimit'] = int(pixLimit.GetValue())
864           
865        def OnSetRings(event):
866            if data['setRings']:
867                data['setRings'] = False
868            else:
869                data['setRings'] = True
870            G2plt.PlotExposedImage(G2frame,event=event)
871   
872        calibSizer = wx.FlexGridSizer(0,3,5,5)
873        comboSizer = wx.BoxSizer(wx.HORIZONTAL)   
874        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calibrant '),0,WACV)
875        calSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['calibrant'],choices=calList,
876            style=wx.CB_READONLY|wx.CB_DROPDOWN|wx.CB_SORT)
877        calSel.Bind(wx.EVT_COMBOBOX, OnNewCalibrant)
878        comboSizer.Add(calSel,0,WACV)
879        calibSizer.Add(comboSizer,0)
880       
881        comboSizer = wx.BoxSizer(wx.HORIZONTAL)   
882        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calib lines to skip   '),0,WACV)
883        calibSkip  = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['calibskip']),choices=[str(i) for i in range(25)],
884            style=wx.CB_READONLY|wx.CB_DROPDOWN)
885        calibSkip.Bind(wx.EVT_COMBOBOX, OnCalibSkip)
886        comboSizer.Add(calibSkip,0,WACV)
887        calibSizer.Add(comboSizer,0)
888       
889        comboSizer = wx.BoxSizer(wx.HORIZONTAL)       
890        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Min calib d-spacing '),0,WACV)
891        calibDmin = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f" % (data['calibdmin'])),
892            style=wx.TE_PROCESS_ENTER)
893        calibDmin.Bind(wx.EVT_TEXT_ENTER,OnCalibDmin)
894        calibDmin.Bind(wx.EVT_KILL_FOCUS,OnCalibDmin)
895        comboSizer.Add(calibDmin,0,WACV)
896        calibSizer.Add(comboSizer,0)
897       
898        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
899        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Min ring I/Ib '),0,WACV)
900        cutOff = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.1f" % (data['cutoff'])),
901            style=wx.TE_PROCESS_ENTER)
902        cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)
903        cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
904        comboSizer.Add(cutOff,0,WACV)
905        calibSizer.Add(comboSizer,0)
906       
907        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
908        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Pixel search range '),0,WACV)
909        pixLimit = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['pixLimit']),choices=['1','2','5','10','15','20'],
910            style=wx.CB_READONLY|wx.CB_DROPDOWN)
911        pixLimit.Bind(wx.EVT_COMBOBOX, OnPixLimit)
912        comboSizer.Add(pixLimit,0,WACV)
913        calibSizer.Add(comboSizer,0)
914       
915        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
916        setRings = wx.CheckBox(parent=G2frame.dataDisplay,label='Show ring picks?')
917        comboSizer.Add(setRings,0)
918        setRings.Bind(wx.EVT_CHECKBOX, OnSetRings)
919        setRings.SetValue(data['setRings'])
920        calibSizer.Add(comboSizer,0)
921        return calibSizer
922       
923    def GonioSizer():
924       
925        ValObj = {}
926       
927        def OnGonioAngle(event):
928            Obj = event.GetEventObject()
929            item = ValObj[Obj.GetId()]
930            try:
931                value = float(Obj.GetValue())
932            except ValueError:
933                value = data['GonioAngles'][item]
934            data['GonioAngles'][item] = value
935            Obj.SetValue('%8.2f'%(value))
936       
937        gonioSizer = wx.BoxSizer(wx.HORIZONTAL)
938        names = ['Omega','Chi','Phi']
939        gonioSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'Sample goniometer angles: '),0,WACV)
940        for i,name in enumerate(names):
941            gonioSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,name),0,WACV)
942            angle = wx.TextCtrl(G2frame.dataDisplay,-1,value='%8.2f'%(data['GonioAngles'][i]),
943                style=wx.TE_PROCESS_ENTER)
944            angle.Bind(wx.EVT_TEXT_ENTER,OnGonioAngle)
945            angle.Bind(wx.EVT_KILL_FOCUS,OnGonioAngle)
946            ValObj[angle.GetId()] = i
947            gonioSizer.Add(angle,0,WACV)
948        return gonioSizer
949       
950# Image Controls main code             
951                           
952    #fix for old files:
953    if 'azmthOff' not in data:
954        data['azmthOff'] = 0.0
955    if 'background image' not in data:
956        data['background image'] = ['',-1.0]
957    if 'dark image' not in data:
958        data['dark image'] = ['',-1.0]
959    if 'centerAzm' not in data:
960        data['centerAzm'] = False
961    if 'Oblique' not in data:
962        data['Oblique'] = [0.5,False]
963    if 'PolaVal' not in data:
964        data['PolaVal'] = [0.99,False]
965    #end fix
966   
967    colorList = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
968    calList = [m for m in calFile.Calibrants.keys()]
969    typeList = ['PWDR - powder diffraction data','SASD - small angle scattering data',
970        'REFL - reflectometry data']
971    if not data.get('type'):                        #patch for old project files
972        data['type'] = 'PWDR'
973    typeDict = {'PWDR':typeList[0],'SASD':typeList[1],'REFL':typeList[2]}
974    if G2frame.dataDisplay:
975        G2frame.dataDisplay.Destroy()
976    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ImageMenu)
977    if not G2frame.dataFrame.GetStatusBar():
978        G2frame.dataFrame.CreateStatusBar()
979    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCalibrate, id=G2gd.wxID_IMCALIBRATE)
980    G2frame.dataFrame.Bind(wx.EVT_MENU, OnRecalibrate, id=G2gd.wxID_IMRECALIBRATE)
981    G2frame.dataFrame.Bind(wx.EVT_MENU, OnClearCalib, id=G2gd.wxID_IMCLEARCALIB)
982    if 'chisq' not in data:
983        G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=False)   
984    G2frame.dataFrame.Bind(wx.EVT_MENU, OnIntegrate, id=G2gd.wxID_IMINTEGRATE)
985    G2frame.dataFrame.Bind(wx.EVT_MENU, OnIntegrateAll, id=G2gd.wxID_INTEGRATEALL)
986    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyControls, id=G2gd.wxID_IMCOPYCONTROLS)
987    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveControls, id=G2gd.wxID_IMSAVECONTROLS)
988    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadControls, id=G2gd.wxID_IMLOADCONTROLS)
989    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
990
991    mainSizer = wx.BoxSizer(wx.VERTICAL)
992    mainSizer.Add((5,10),0)   
993    mainSizer.Add(ComboSizer(),0,wx.ALIGN_LEFT)
994    mainSizer.Add((5,5),0)           
995    mainSizer.Add(MaxSizer(),0,wx.ALIGN_LEFT|wx.EXPAND)
996   
997    mainSizer.Add((5,5),0)
998    DataSizer = wx.FlexGridSizer(0,2,5,5)
999    DataSizer.Add(CalibCoeffSizer(),0)
1000    DataSizer.Add(IntegrateSizer(),0)       
1001    mainSizer.Add(DataSizer,0)
1002    mainSizer.Add((5,5),0)           
1003    mainSizer.Add(BackSizer(),0)
1004    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calibration controls:'),0,WACV)
1005    mainSizer.Add((5,5),0)
1006    mainSizer.Add(CalibSizer(),0,WACV)
1007    mainSizer.Add((5,5),0)
1008    mainSizer.Add(GonioSizer(),0,WACV)   
1009       
1010    mainSizer.Layout()   
1011    G2frame.dataDisplay.SetSizer(mainSizer)
1012    fitSize = mainSizer.Fit(G2frame.dataFrame)
1013    G2frame.dataFrame.setSizePosLeft(fitSize)
1014    G2frame.dataDisplay.SetSize(fitSize)
1015   
1016################################################################################
1017##### Masks
1018################################################################################
1019   
1020def UpdateMasks(G2frame,data):
1021    '''Shows and handles the controls on the "Masks"
1022    data tree entry
1023    '''
1024   
1025    def OnTextMsg(event):
1026        Obj = event.GetEventObject()
1027        Obj.SetToolTipString('Drag this mask on 2D Powder Image with mouse to change ')
1028       
1029    def OnThreshold(event):
1030        try:
1031            lower = max(int(lowerThreshold.GetValue()),thresh[0][0])
1032        except ValueError:
1033            lower = thresh[0][0]
1034        try:
1035            upper = min(int(upperThreshold.GetValue()),thresh[0][1])
1036        except ValueError:
1037            upper = thresh[0][1]
1038        data['Thresholds'][1] = [lower,upper]
1039        lowerThreshold.SetValue("%8d" % (lower))
1040        upperThreshold.SetValue("%8d" % (upper))
1041        G2plt.PlotExposedImage(G2frame,event=event)
1042       
1043    def OnSpotDiameter(event):
1044        Obj = event.GetEventObject()
1045        try:
1046            diameter = min(100.,max(0.1,float(Obj.GetValue())))
1047        except ValueError:
1048            diameter = 1.0
1049        Obj.SetValue("%.2f"%(diameter))
1050        data['Points'][spotIds.index(Obj.GetId())][2] = diameter
1051        G2plt.PlotExposedImage(G2frame,event=event)
1052       
1053    def OnDeleteSpot(event):
1054        Obj = event.GetEventObject()
1055        del(data['Points'][delSpotId.index(Obj)])
1056        UpdateMasks(G2frame,data)
1057        G2plt.PlotExposedImage(G2frame,event=event)
1058       
1059    def OnRingThickness(event):
1060        Obj = event.GetEventObject()
1061        try:
1062            thick = min(1.0,max(0.001,float(Obj.GetValue())))
1063        except ValueError:
1064            thick = 0.1
1065        Obj.SetValue("%.3f"%(thick))
1066        data['Rings'][ringIds.index(Obj.GetId())][1] = thick
1067        G2plt.PlotExposedImage(G2frame,event=event)
1068       
1069    def OnDeleteRing(event):
1070        Obj = event.GetEventObject()
1071        del(data['Rings'][delRingId.index(Obj)])
1072        UpdateMasks(G2frame,data)
1073        G2plt.PlotExposedImage(G2frame,event=event)
1074
1075    def OnArcThickness(event):
1076        Obj = event.GetEventObject()
1077        try:
1078            thick = min(20.0,max(0.001,float(Obj.GetValue())))
1079        except ValueError:
1080            thick = 0.1
1081        Obj.SetValue("%.3f"%(thick))
1082        data['Arcs'][arcIds.index(Obj.GetId())][2] = thick
1083        G2plt.PlotExposedImage(G2frame,event=event)
1084       
1085    def OnDeleteArc(event):
1086        Obj = event.GetEventObject()
1087        del(data['Arcs'][delArcId.index(Obj)])
1088        UpdateMasks(G2frame,data)
1089        G2plt.PlotExposedImage(G2frame,event=event)
1090
1091    def OnDeletePoly(event):
1092        Obj = event.GetEventObject()
1093        del(data['Polygons'][delPolyId.index(Obj)])
1094        UpdateMasks(G2frame,data)
1095        G2plt.PlotExposedImage(G2frame,event=event)
1096
1097    def OnDeleteFrame(event):
1098        data['Frames'] = []
1099        UpdateMasks(G2frame,data)
1100        G2plt.PlotExposedImage(G2frame,event=event)
1101
1102    def OnCopyMask(event):
1103        TextList = [[False,'All IMG',0]]
1104        Names = []
1105        if G2frame.PatternTree.GetCount():
1106            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1107            while id:
1108                name = G2frame.PatternTree.GetItemText(id)
1109                Names.append(name)
1110                if 'IMG' in name:
1111                    if id == G2frame.Image:
1112                        Source = name
1113                        Mask = copy.deepcopy(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Masks')))
1114                        Mask.pop('Thresholds')  #remove Thresholds from source mask
1115                    else:
1116                        TextList.append([False,name,id])
1117                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1118            if len(TextList) == 1:
1119                G2frame.ErrorDialog('Nothing to copy mask to','There must be more than one "IMG" pattern')
1120                return
1121            dlg = G2frame.CopyDialog(G2frame,'Copy mask information','Copy mask from '+Source+' to:',TextList)
1122            try:
1123                if dlg.ShowModal() == wx.ID_OK:
1124                    result = dlg.GetData()
1125                    if result[0][0]:
1126                        result = TextList[1:]
1127                        for item in result: item[0] = True
1128                    for i,item in enumerate(result):
1129                        ifcopy,name,id = item
1130                        if ifcopy:
1131                            mask = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Masks'))
1132#                            Mask['Thresholds'][0] = mask['Thresholds'][0]
1133#                            Mask['Thresholds'][1][1] = min(mask['Thresholds'][1][1],Mask['Thresholds'][1][1])
1134                            mask.update(Mask)                               
1135                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Masks'),copy.deepcopy(mask))
1136            finally:
1137                dlg.Destroy()
1138               
1139    def OnSaveMask(event):
1140        dlg = wx.FileDialog(G2frame, 'Choose image mask file', '.', '', 
1141            'image mask files (*.immask)|*.immask',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1142        try:
1143            if dlg.ShowModal() == wx.ID_OK:
1144                filename = dlg.GetPath()
1145                File = open(filename,'w')
1146                save = {}
1147                keys = ['Points','Rings','Arcs','Polygons','Frames','Thresholds']
1148                for key in keys:
1149                    File.write(key+':'+str(data[key])+'\n')
1150                File.close()
1151        finally:
1152            dlg.Destroy()
1153       
1154    def OnLoadMask(event):
1155        dlg = wx.FileDialog(G2frame, 'Choose image mask file', '.', '', 
1156            'image mask files (*.immask)|*.immask',wx.OPEN|wx.CHANGE_DIR)
1157        try:
1158            if dlg.ShowModal() == wx.ID_OK:
1159                filename = dlg.GetPath()
1160                File = open(filename,'r')
1161                save = {}
1162                oldThreshold = data['Thresholds'][0]
1163                S = File.readline()
1164                while S:
1165                    if S[0] == '#':
1166                        S = File.readline()
1167                        continue
1168                    [key,val] = S[:-1].split(':')
1169                    if key in ['Points','Rings','Arcs','Polygons','Frames','Thresholds']:
1170                        save[key] = eval(val)
1171                        if key == 'Thresholds':
1172                            save[key][0] = oldThreshold
1173                            save[key][1][1] = min(oldThreshold[1],save[key][1][1])
1174                    S = File.readline()
1175                data.update(save)
1176                UpdateMasks(G2frame,data)
1177                G2plt.PlotExposedImage(G2frame,event=event)               
1178                File.close()
1179        finally:
1180            dlg.Destroy()
1181           
1182    def OnNewSpotMask(event):
1183        'Start a new spot mask'
1184        G2frame.MaskKey = 's'
1185        G2plt.OnStartMask(G2frame)
1186       
1187    def OnNewArcMask(event):
1188        'Start a new arc mask'
1189        G2frame.MaskKey = 'a'
1190        G2plt.OnStartMask(G2frame)
1191       
1192    def OnNewRingMask(event):
1193        'Start a new ring mask'
1194        G2frame.MaskKey = 'r'
1195        G2plt.OnStartMask(G2frame)
1196       
1197    def OnNewPolyMask(event):
1198        'Start a new polygon mask'
1199        G2frame.MaskKey = 'p'
1200        G2plt.OnStartMask(G2frame)
1201       
1202    def OnNewFrameMask(event):
1203        'Start a new Frame mask'
1204        G2frame.MaskKey = 'f'
1205        G2plt.OnStartMask(G2frame)
1206               
1207    if G2frame.dataDisplay:
1208        G2frame.dataDisplay.Destroy()
1209    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.MaskMenu)
1210    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyMask, id=G2gd.wxID_MASKCOPY)
1211    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadMask, id=G2gd.wxID_MASKLOAD)
1212    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveMask, id=G2gd.wxID_MASKSAVE)
1213    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewSpotMask, id=G2gd.wxID_NEWMASKSPOT)
1214    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewArcMask, id=G2gd.wxID_NEWMASKARC)
1215    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewRingMask, id=G2gd.wxID_NEWMASKRING)
1216    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewPolyMask, id=G2gd.wxID_NEWMASKPOLY)
1217    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewFrameMask, id=G2gd.wxID_NEWMASKFRAME)
1218    if not G2frame.dataFrame.GetStatusBar():
1219        Status = G2frame.dataFrame.CreateStatusBar()
1220    if G2frame.MaskKey == 'f':
1221        G2frame.dataFrame.GetStatusBar().SetStatusText('Frame mask active - LB pick next point, RB close polygon')
1222    elif G2frame.MaskKey == 'p':
1223        G2frame.dataFrame.GetStatusBar().SetStatusText('Polygon mask active - LB pick next point, RB close polygon')
1224    elif G2frame.MaskKey == 's':
1225        G2frame.dataFrame.GetStatusBar().SetStatusText('Spot mask active - LB pick spot location')
1226    elif G2frame.MaskKey == 'a':
1227        G2frame.dataFrame.GetStatusBar().SetStatusText('Arc mask active - LB pick arc location')
1228    elif G2frame.MaskKey == 'r':
1229        G2frame.dataFrame.GetStatusBar().SetStatusText('Ring mask active - LB pick ring location')
1230    else:
1231        G2frame.dataFrame.GetStatusBar().SetStatusText("To add mask: On 2D Powder Image, key a:arc, r:ring, s:spot, p:polygon, f:frame")
1232    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1233    mainSizer = wx.BoxSizer(wx.VERTICAL)
1234    mainSizer.Add((5,10),0)
1235
1236    thresh = data['Thresholds']         #min/max intensity range
1237    spots = data['Points']               #x,y,radius in mm
1238    rings = data['Rings']               #radius, thickness
1239    polygons = data['Polygons']         #3+ x,y pairs
1240    if 'Frames' not in data:
1241        data['Frames'] = []
1242    frame = data['Frames']             #3+ x,y pairs
1243    arcs = data['Arcs']                 #radius, start/end azimuth, thickness
1244   
1245    littleSizer = wx.FlexGridSizer(0,3,0,5)
1246    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Lower/Upper limits '),0,WACV)
1247    Text = wx.TextCtrl(G2frame.dataDisplay,value=("%8d" % (thresh[0][0])),style=wx.TE_READONLY)
1248    littleSizer.Add(Text,0,WACV)
1249    Text.SetBackgroundColour(VERY_LIGHT_GREY)
1250    Text = wx.TextCtrl(G2frame.dataDisplay,value=("%8d" % (thresh[0][1])),style=wx.TE_READONLY)
1251    littleSizer.Add(Text,0,WACV)
1252    Text.SetBackgroundColour(VERY_LIGHT_GREY)
1253    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Lower/Upper thresholds '),0,WACV)
1254    lowerThreshold = wx.TextCtrl(parent=G2frame.dataDisplay,
1255        value=("%8d" % (thresh[1][0])),style=wx.TE_PROCESS_ENTER)
1256    lowerThreshold.Bind(wx.EVT_TEXT_ENTER,OnThreshold)
1257    lowerThreshold.Bind(wx.EVT_KILL_FOCUS,OnThreshold)
1258    littleSizer.Add(lowerThreshold,0,WACV)
1259    upperThreshold = wx.TextCtrl(parent=G2frame.dataDisplay,
1260        value=("%8d" % (thresh[1][1])),style=wx.TE_PROCESS_ENTER)
1261    upperThreshold.Bind(wx.EVT_TEXT_ENTER,OnThreshold)
1262    upperThreshold.Bind(wx.EVT_KILL_FOCUS,OnThreshold)
1263    littleSizer.Add(upperThreshold,0,WACV)
1264    mainSizer.Add(littleSizer,0,)
1265    spotIds = []
1266    delSpotId = []
1267    if spots:
1268        littleSizer = wx.FlexGridSizer(0,3,0,5)
1269        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Spot masks:'),0,WACV)
1270        littleSizer.Add((5,0),0)
1271        littleSizer.Add((5,0),0)
1272        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' position, mm'),0,WACV)
1273        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' diameter, mm'),0,WACV)
1274        littleSizer.Add((5,0),0)
1275        for spot in spots:
1276            if spot:
1277                x,y,d = spot
1278                spotText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f,%.2f" % (x,y)),
1279                    style=wx.TE_READONLY)
1280                spotText.SetBackgroundColour(VERY_LIGHT_GREY)
1281                littleSizer.Add(spotText,0,WACV)
1282                spotText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1283                spotDiameter = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f" % (d)),
1284                    style=wx.TE_PROCESS_ENTER)
1285                littleSizer.Add(spotDiameter,0,WACV)
1286                spotDiameter.Bind(wx.EVT_TEXT_ENTER,OnSpotDiameter)
1287                spotDiameter.Bind(wx.EVT_KILL_FOCUS,OnSpotDiameter)
1288                spotIds.append(spotDiameter.GetId())
1289                spotDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1290                spotDelete.Bind(wx.EVT_CHECKBOX,OnDeleteSpot)
1291                delSpotId.append(spotDelete)
1292                littleSizer.Add(spotDelete,0,WACV)
1293        mainSizer.Add(littleSizer,0,)
1294    ringIds = []
1295    delRingId = []
1296    if rings:
1297        littleSizer = wx.FlexGridSizer(0,3,0,5)
1298        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Ring masks:'),0,WACV)
1299        littleSizer.Add((5,0),0)
1300        littleSizer.Add((5,0),0)
1301        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' 2-theta,deg'),0,WACV)
1302        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' thickness, deg'),0,WACV)
1303        littleSizer.Add((5,0),0)
1304        for ring in rings:
1305            if ring:
1306                tth,thick = ring
1307                ringText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (tth)),
1308                    style=wx.TE_READONLY)
1309                ringText.SetBackgroundColour(VERY_LIGHT_GREY)
1310                ringText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1311                littleSizer.Add(ringText,0,WACV)
1312                ringThick = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (thick)),
1313                    style=wx.TE_PROCESS_ENTER)
1314                littleSizer.Add(ringThick,0,WACV)
1315                ringThick.Bind(wx.EVT_TEXT_ENTER,OnRingThickness)
1316                ringThick.Bind(wx.EVT_KILL_FOCUS,OnRingThickness)
1317                ringIds.append(ringThick.GetId())
1318                ringDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1319                ringDelete.Bind(wx.EVT_CHECKBOX,OnDeleteRing)
1320                delRingId.append(ringDelete)
1321                littleSizer.Add(ringDelete,0,WACV)
1322        mainSizer.Add(littleSizer,0,)
1323    arcIds = []
1324    delArcId = []
1325    if arcs:
1326        littleSizer = wx.FlexGridSizer(0,4,0,5)
1327        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Arc masks:'),0,WACV)
1328        littleSizer.Add((5,0),0)
1329        littleSizer.Add((5,0),0)
1330        littleSizer.Add((5,0),0)
1331        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' 2-theta,deg'),0,WACV)
1332        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' azimuth, deg'),0,WACV)
1333        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' thickness, deg'),0,WACV)
1334        littleSizer.Add((5,0),0)
1335        for arc in arcs:
1336            if arc:
1337                tth,azimuth,thick = arc
1338                arcText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (tth)),
1339                    style=wx.TE_READONLY)
1340                arcText.SetBackgroundColour(VERY_LIGHT_GREY)
1341                arcText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1342                littleSizer.Add(arcText,0,WACV)
1343                azmText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%d,%d" % (azimuth[0],azimuth[1])),
1344                    style=wx.TE_READONLY)
1345                azmText.SetBackgroundColour(VERY_LIGHT_GREY)
1346                azmText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1347                littleSizer.Add(azmText,0,WACV)
1348                arcThick = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (thick)),
1349                    style=wx.TE_PROCESS_ENTER)
1350                littleSizer.Add(arcThick,0,WACV)
1351                arcThick.Bind(wx.EVT_TEXT_ENTER,OnArcThickness)
1352                arcThick.Bind(wx.EVT_KILL_FOCUS,OnArcThickness)
1353                arcIds.append(arcThick.GetId())
1354                arcDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1355                arcDelete.Bind(wx.EVT_CHECKBOX,OnDeleteArc)
1356                delArcId.append(arcDelete)
1357                littleSizer.Add(arcDelete,0,WACV)
1358        mainSizer.Add(littleSizer,0,)
1359    polyIds = []
1360    delPolyId = []
1361    delFrameId = []
1362    if polygons:
1363        littleSizer = wx.FlexGridSizer(0,2,0,5)
1364        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Polygon masks:'),0,WACV)
1365        littleSizer.Add((5,0),0)
1366        for polygon in polygons:
1367            if polygon:
1368                polyList = []
1369                for x,y in polygon:
1370                    polyList.append("%.2f, %.2f"%(x,y))
1371                polyText = wx.ComboBox(G2frame.dataDisplay,value=polyList[0],choices=polyList,style=wx.CB_READONLY)
1372                littleSizer.Add(polyText,0,WACV)
1373                polyDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1374                polyDelete.Bind(wx.EVT_CHECKBOX,OnDeletePoly)
1375                delPolyId.append(polyDelete)
1376                littleSizer.Add(polyDelete,0,WACV)
1377        mainSizer.Add(littleSizer,0,)
1378    if frame:
1379        littleSizer = wx.FlexGridSizer(0,2,0,5)
1380        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Frame mask:'),0,
1381            WACV)
1382        littleSizer.Add((5,0),0)
1383        frameList = []
1384        for x,y in frame:
1385            frameList.append("%.2f, %.2f"%(x,y))
1386        frameText = wx.ComboBox(G2frame.dataDisplay,value=frameList[0],choices=frameList,style=wx.CB_READONLY)
1387        littleSizer.Add(frameText,0,WACV)
1388        frameDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1389        frameDelete.Bind(wx.EVT_CHECKBOX,OnDeleteFrame)
1390        delFrameId.append(frameDelete)
1391        littleSizer.Add(frameDelete,0,WACV)
1392        mainSizer.Add(littleSizer,0,)
1393    if (frame or polygons):
1394        mainSizer.Add(wx.StaticText(G2frame.dataDisplay,
1395            label=' For frame and polygons: on plot RB vertex drag to move, LB vertex drag to insert'),0,WACV)
1396    mainSizer.Layout()   
1397    G2frame.dataDisplay.SetSizer(mainSizer)
1398    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
1399    Size = mainSizer.Fit(G2frame.dataFrame)
1400    Size[0] = 450
1401    G2frame.dataFrame.setSizePosLeft(Size)   
1402
1403################################################################################
1404##### Stress/Strain
1405################################################################################
1406
1407def UpdateStressStrain(G2frame,data):
1408    '''Shows and handles the controls on the "Stress/Strain"
1409    data tree entry
1410    '''
1411   
1412    def OnAppendDzero(event):
1413        data['d-zero'].append({'Dset':1.0,'Dcalc':0.0,'pixLimit':10,'cutoff':1.0,
1414            'ImxyObs':[[],[]],'ImtaObs':[[],[]],'ImtaCalc':[[],[]],'Emat':[1.0,1.0,1.0]})
1415        UpdateStressStrain(G2frame,data)
1416       
1417    def OnUpdateDzero(event):
1418        for item in data['d-zero']:
1419            if item['Dcalc']:   #skip unrefined ones
1420                item['Dset'] = item['Dcalc']
1421        UpdateStressStrain(G2frame,data)
1422           
1423    def OnCopyStrSta(event):
1424        TextList = [[False,'All IMG',0,0]]
1425        Names = []
1426        if G2frame.PatternTree.GetCount():
1427            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1428            while id:
1429                name = G2frame.PatternTree.GetItemText(id)
1430                Names.append(name)
1431                if 'IMG' in name:
1432                    Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Stress/Strain'))
1433                    if id == G2frame.Image:
1434                        Source = name
1435                    else:
1436                        TextList.append([False,name,id,Data.get('Sample load',0.0)])
1437                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1438            if len(TextList) == 1:
1439                G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "IMG" pattern')
1440                return
1441            dlg = G2frame.CopyDialog(G2frame,'Copy stress/strain controls','Copy controls from '+Source+' to:',TextList)
1442            try:
1443                if dlg.ShowModal() == wx.ID_OK:
1444                    result = dlg.GetData()
1445                    if result[0][0]:
1446                        result = TextList[1:]
1447                        for item in result: item[0] = True
1448                    for i,item in enumerate(result):
1449                        ifcopy,name,id,load = item
1450                        if ifcopy:
1451                            Data = copy.deepcopy(data)
1452                            Data['Sample load'] = load
1453                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Stress/Strain'),Data)
1454            finally:
1455                dlg.Destroy()
1456
1457    def OnLoadStrSta(event):
1458        dlg = wx.FileDialog(G2frame, 'Choose stress/strain file', '.', '', 
1459            'image control files (*.strsta)|*.strsta',wx.OPEN|wx.CHANGE_DIR)
1460        try:
1461            if dlg.ShowModal() == wx.ID_OK:
1462                filename = dlg.GetPath()
1463                File = open(filename,'r')
1464                S = File.read()
1465                data = eval(S)
1466                Controls = G2frame.PatternTree.GetItemPyData(
1467                    G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
1468                G2img.FitStrSta(G2frame.ImageZ,data,Controls)
1469                UpdateStressStrain(G2frame,data)
1470                G2plt.PlotExposedImage(G2frame,event=event)
1471                G2plt.PlotStrain(G2frame,data,newPlot=True)
1472                File.close()
1473        finally:
1474            dlg.Destroy()
1475
1476    def OnSaveStrSta(event):
1477        dlg = wx.FileDialog(G2frame, 'Choose stress/strain file', '.', '', 
1478            'image control files (*.strsta)|*.strsta',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1479        try:
1480            if dlg.ShowModal() == wx.ID_OK:
1481                filename = dlg.GetPath()
1482                File = open(filename,'w')
1483                save = {}
1484                keys = ['Type','Sample phi','Sample z','Sample load']
1485                keys2 = ['Dset','Dcalc','pixLimit','cutoff','Emat']
1486                File.write('{\n\t')
1487                for key in keys:
1488                    if key in 'Type':
1489                        File.write("'"+key+"':'"+data[key]+"',")
1490                    else:
1491                        File.write("'"+key+"':"+str(data[key])+',')
1492                File.write('\n\t'+"'d-zero':[\n")
1493                for data2 in data['d-zero']:
1494                    File.write('\t\t{')
1495                    for key in keys2:
1496                        File.write("'"+key+"':"+str(data2[key])+',')
1497                    File.write("'ImxyObs':[[],[]],'ImtaObs':[[],[]],'ImtaCalc':[[],[]]},\n")
1498                File.write('\t]\n}')
1499                File.close()
1500        finally:
1501            dlg.Destroy()
1502
1503    def OnFitStrSta(event):
1504        Controls = G2frame.PatternTree.GetItemPyData(
1505            G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
1506        G2img.FitStrSta(G2frame.ImageZ,data,Controls)
1507        print 'Strain fitting finished'
1508        UpdateStressStrain(G2frame,data)
1509        G2plt.PlotExposedImage(G2frame,event=event)
1510        G2plt.PlotStrain(G2frame,data,newPlot=True)
1511       
1512    def OnFitAllStrSta(event):
1513        TextList = [[False,'All IMG',0]]
1514        Names = []
1515        if G2frame.PatternTree.GetCount():
1516            choices = G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
1517            if len(choices) == 1:
1518                G2frame.ErrorDialog('Nothing to fit','There must some "IMG" patterns')
1519                return
1520            sel = []
1521            dlg = G2gd.G2MultiChoiceDialog(G2frame,'Stress/Strain fitting','Select images to fit:',choices)
1522            dlg.SetSelections(sel)
1523            names = []
1524            if dlg.ShowModal() == wx.ID_OK:
1525                for sel in dlg.GetSelections():
1526                    names.append(choices[sel])
1527            dlg.Destroy()
1528            SeqResult = {}
1529            dlg = wx.ProgressDialog('Sequential IMG Strain fit','Data set name = '+names[0],len(names), 
1530                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)         
1531            wx.BeginBusyCursor()
1532            goodnames = []
1533            try:
1534                for i,name in enumerate(names):
1535                    print ' Sequential strain fit for ',name
1536                    GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
1537                    if not GoOn:
1538                        break
1539                    Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
1540                    Controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Image Controls'))
1541                    StaCtrls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Stress/Strain'))
1542                    if not len(StaCtrls['d-zero']):
1543                        continue
1544                    goodnames.append(name)
1545                    id = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, name)
1546                    Npix,imagefile = G2frame.PatternTree.GetItemPyData(Id)
1547                    image = G2IO.GetImageData(G2frame,imagefile,True)
1548                    dark = Controls['dark image']
1549                    if dark[0]:
1550                        darkfile = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame, 
1551                            G2frame.root,dark[0]))[1]
1552                        darkImg = G2IO.GetImageData(G2frame,darkfile,imageOnly=True)
1553                        image += dark[1]*darkImg
1554                    G2img.FitStrSta(image,StaCtrls,Controls)
1555                    G2plt.PlotStrain(G2frame,StaCtrls,newPlot=True)
1556                    parmDict = {'Sample load':StaCtrls['Sample load'],}
1557                    varyNames = ['e11','e12','e22']
1558                    sig = []
1559                    varyList = []
1560                    variables = []
1561                    for i,item in enumerate(StaCtrls['d-zero']):
1562                        variables += item['Emat']
1563                        sig += item['Esig']
1564                        varylist = ['%d%s%s'%(i,':',Name) for Name in varyNames]
1565                        varyList += varylist
1566                        parmDict.update(dict(zip(varylist,item['Emat'])))
1567                        parmDict['%d:Dcalc'%(i)] = item['Dcalc']
1568                    SeqResult[name] = {'variables':variables,'varyList':varyList,'sig':sig,'Rvals':[],
1569                        'covMatrix':np.eye(len(variables)),'title':name,'parmDict':parmDict}
1570                else:
1571                    SeqResult['histNames'] = goodnames
1572                    dlg.Destroy()
1573                    print ' ***** Sequential strain refinement successful *****'
1574            finally:
1575                wx.EndBusyCursor()   
1576            Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
1577            if Id:
1578                G2frame.PatternTree.SetItemPyData(Id,SeqResult)
1579            else:
1580                Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
1581                G2frame.PatternTree.SetItemPyData(Id,SeqResult)
1582            G2frame.PatternTree.SelectItem(Id)
1583            print 'All images fitted'
1584       
1585    def SamSizer():
1586       
1587        def OnStrainType(event):
1588            data['Type'] = strType.GetValue()
1589       
1590        def OnSamPhi(event):
1591            try:
1592                value = float(samPhi.GetValue())
1593            except ValueError:
1594                value = data['Sample phi']
1595            data['Sample phi'] = value
1596            samPhi.SetValue("%.3f" % (data['Sample phi']))
1597               
1598        def OnSamZ(event):
1599            try:
1600                value = float(samZ.GetValue())
1601            except ValueError:
1602                value = data['Sample z']
1603            data['Sample z'] = value
1604            samZ.SetValue("%.3f" % (data['Sample z']))
1605               
1606        def OnSamLoad(event):
1607            try:
1608                value = float(samLoad.GetValue())
1609            except ValueError:
1610                value = data['Sample load']
1611            data['Sample load'] = value
1612            samLoad.SetValue("%.3f" % (data['Sample load']))
1613               
1614        samSizer = wx.BoxSizer(wx.HORIZONTAL)
1615        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Strain type: '),0,WACV)
1616        strType = wx.ComboBox(G2frame.dataDisplay,value=data['Type'],choices=['True','Conventional'],
1617            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1618        strType.SetValue(data['Type'])
1619        strType.Bind(wx.EVT_COMBOBOX, OnStrainType)
1620        samSizer.Add(strType,0,WACV)
1621       
1622        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Sample phi: '),0,WACV)
1623        samPhi = wx.TextCtrl(G2frame.dataDisplay,-1,value=("%.3f" % (data['Sample phi'])),
1624            style=wx.TE_PROCESS_ENTER)
1625        samSizer.Add(samPhi,0,WACV)
1626        samPhi.Bind(wx.EVT_TEXT_ENTER,OnSamPhi)
1627        samPhi.Bind(wx.EVT_KILL_FOCUS,OnSamPhi)
1628        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Sample delta-z(mm): '),0,WACV)
1629        samZ = wx.TextCtrl(G2frame.dataDisplay,-1,value=("%.3f" % (data['Sample z'])),
1630            style=wx.TE_PROCESS_ENTER)
1631        samSizer.Add(samZ,0,WACV)
1632        samZ.Bind(wx.EVT_TEXT_ENTER,OnSamZ)
1633        samZ.Bind(wx.EVT_KILL_FOCUS,OnSamZ)
1634        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Sample load(MPa): '),0,WACV)
1635        samLoad = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data,'Sample load',
1636                nDig=[8,3],typeHint=float,)
1637        samSizer.Add(samLoad,0,WACV)
1638
1639        return samSizer
1640       
1641    def DzeroSizer():
1642   
1643        def OnDzero(event):
1644            Obj = event.GetEventObject()
1645            try:
1646                value = min(20.0,max(0.25,float(Obj.GetValue())))
1647            except ValueError:
1648                value = 1.0
1649            Obj.SetValue("%.5f"%(value))
1650            data['d-zero'][Indx[Obj.GetId()]]['Dset'] = value
1651            data['d-zero'] = G2mth.sortArray(data['d-zero'],'Dset',reverse=True)
1652            Ring,R = G2img.MakeStrStaRing(data['d-zero'][Indx[Obj.GetId()]],G2frame.ImageZ,Controls)
1653            if len(Ring):
1654                data['d-zero'][Indx[Obj.GetId()]].update(R)
1655            else:
1656                G2frame.ErrorDialog('Strain peak selection','WARNING - No points found for this ring selection')
1657               
1658            UpdateStressStrain(G2frame,data)
1659            G2plt.PlotExposedImage(G2frame,event=event,newPlot=False)
1660            G2plt.PlotStrain(G2frame,data,newPlot=True)
1661           
1662        def OnDeleteDzero(event):
1663            Obj = event.GetEventObject()
1664            del(data['d-zero'][delIndx.index(Obj)])
1665            UpdateStressStrain(G2frame,data)
1666            G2plt.PlotExposedImage(G2frame,event=event,newPlot=True)
1667            G2plt.PlotStrain(G2frame,data,newPlot=True)
1668       
1669        def OnCutOff(event):
1670            Obj = event.GetEventObject()
1671            try:
1672                value = min(10.0,max(0.5,float(Obj.GetValue())))
1673            except ValueError:
1674                value = 1.0
1675            Obj.SetValue("%.1f"%(value))
1676            data['d-zero'][Indx[Obj.GetId()]]['cutoff'] = value
1677            Ring,R = G2img.MakeStrStaRing(data['d-zero'][Indx[Obj.GetId()]],G2frame.ImageZ,Controls)
1678            G2plt.PlotExposedImage(G2frame,event=event)
1679            G2plt.PlotStrain(G2frame,data,newPlot=True)
1680       
1681        def OnPixLimit(event):
1682            Obj = event.GetEventObject()
1683            data['d-zero'][Indx[Obj.GetId()]]['pixLimit'] = int(Obj.GetValue())
1684            Ring,R = G2img.MakeStrStaRing(data['d-zero'][Indx[Obj.GetId()]],G2frame.ImageZ,Controls)
1685            G2plt.PlotExposedImage(G2frame,event=event)
1686            G2plt.PlotStrain(G2frame,data,newPlot=True)
1687           
1688        Indx = {}
1689        delIndx = []   
1690        dzeroSizer = wx.FlexGridSizer(0,8,5,5)
1691        for id,dzero in enumerate(data['d-zero']):
1692            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=(' d-zero #%d: '%(id))),0,WACV)
1693            dZero = wx.TextCtrl(G2frame.dataDisplay,-1,value=('%.5f'%(dzero['Dset'])),
1694                style=wx.TE_PROCESS_ENTER)
1695            dzeroSizer.Add(dZero,0,WACV)
1696            dZero.Bind(wx.EVT_TEXT_ENTER,OnDzero)
1697            dZero.Bind(wx.EVT_KILL_FOCUS,OnDzero)
1698            Indx[dZero.GetId()] = id
1699            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=(' d-zero ave: %.5f'%(dzero['Dcalc']))),0,WACV)
1700               
1701            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min ring I/Ib '),0,WACV)
1702            cutOff = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.1f" % (dzero['cutoff'])),
1703                style=wx.TE_PROCESS_ENTER)
1704            cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)
1705            cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
1706            Indx[cutOff.GetId()] = id
1707            dzeroSizer.Add(cutOff,0,WACV)
1708       
1709            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Pixel search range '),0,WACV)
1710            pixLimit = wx.ComboBox(parent=G2frame.dataDisplay,value=str(dzero['pixLimit']),choices=['1','2','5','10','15','20'],
1711                style=wx.CB_READONLY|wx.CB_DROPDOWN)
1712            pixLimit.Bind(wx.EVT_COMBOBOX, OnPixLimit)
1713            Indx[pixLimit.GetId()] = id
1714            dzeroSizer.Add(pixLimit,0,WACV)               
1715               
1716            dzeroDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1717            dzeroDelete.Bind(wx.EVT_CHECKBOX,OnDeleteDzero)
1718            delIndx.append(dzeroDelete)
1719            dzeroSizer.Add(dzeroDelete,0,WACV)
1720           
1721            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=(' Strain tensor:')),WACV)
1722            names = ['e11','e12','e22']
1723            for i in range(3):
1724                dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=names[i]),0,WACV)
1725                tensorElem = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2f'%(dzero['Emat'][i]),style=wx.TE_READONLY)
1726                tensorElem.SetBackgroundColour(VERY_LIGHT_GREY)
1727                dzeroSizer.Add(tensorElem,0,WACV)
1728            dzeroSizer.Add((5,5),0)             
1729        return dzeroSizer
1730       
1731# patches
1732    if 'Sample load' not in data:
1733        data['Sample load'] = 0.0
1734# end patches
1735   
1736    if G2frame.dataDisplay:
1737        G2frame.dataDisplay.Destroy()
1738    Controls = G2frame.PatternTree.GetItemPyData(
1739        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))       
1740    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.StrStaMenu)
1741    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAppendDzero, id=G2gd.wxID_APPENDDZERO)
1742    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUpdateDzero, id=G2gd.wxID_UPDATEDZERO)
1743    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitStrSta, id=G2gd.wxID_STRSTAFIT)
1744    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitAllStrSta, id=G2gd.wxID_STRSTAALLFIT)
1745    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyStrSta, id=G2gd.wxID_STRSTACOPY)
1746    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadStrSta, id=G2gd.wxID_STRSTALOAD)
1747    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveStrSta, id=G2gd.wxID_STRSTASAVE)   
1748    if not G2frame.dataFrame.GetStatusBar():
1749        Status = G2frame.dataFrame.CreateStatusBar()
1750    if G2frame.StrainKey == 'a':    #probably doesn't happen
1751        G2frame.dataFrame.GetStatusBar().SetStatusText('Add strain ring active - LB pick d-zero value')
1752    else:
1753        G2frame.dataFrame.GetStatusBar().SetStatusText("To add strain data: On 2D Powder Image, key a:add ring")
1754       
1755    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
1756    mainSizer = wx.BoxSizer(wx.VERTICAL)
1757    mainSizer.Add((5,10),0)
1758    mainSizer.Add(SamSizer())
1759    mainSizer.Add((5,10),0)
1760    mainSizer.Add(DzeroSizer())
1761   
1762    mainSizer.Layout()   
1763    G2frame.dataDisplay.SetSizer(mainSizer)
1764    G2frame.dataDisplay.SetAutoLayout(1)
1765    G2frame.dataDisplay.SetupScrolling()
1766    Size = mainSizer.Fit(G2frame.dataFrame)
1767    Size[0] += 25
1768    G2frame.dataDisplay.SetSize(Size)
1769    G2frame.dataFrame.setSizePosLeft(Size)   
Note: See TracBrowser for help on using the repository browser.