source: trunk/GSASIIimgGUI.py @ 1666

Last change on this file since 1666 was 1666, checked in by vondreele, 7 years ago

change strain tensor elements in seq. fit to have ';' instead of ':'

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