source: trunk/GSASIIimgGUI.py @ 1192

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

modify docs for stress strain stuff
add True vs Conventional strain fitting
make stress/strain window have scroll bars

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