source: trunk/GSASIIimgGUI.py @ 2184

Last change on this file since 2184 was 2184, checked in by vondreele, 6 years ago

fix problems in adding atoms, etc for 'faulted' phases in the regular phase stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 128.3 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - image data display routines
3########### SVN repository information ###################
4# $Date: 2016-03-25 15:36:47 +0000 (Fri, 25 Mar 2016) $
5# $Author: vondreele $
6# $Revision: 2184 $
7# $URL: trunk/GSASIIimgGUI.py $
8# $Id: GSASIIimgGUI.py 2184 2016-03-25 15:36:47Z vondreele $
9########### SVN repository information ###################
10'''
11*GSASIIimgGUI: Image GUI*
12-------------------------
13
14Control image display and processing
15
16'''
17import os
18import copy
19import glob
20import re
21import bisect
22import math
23import time
24import copy
25import sys
26import wx
27import wx.lib.scrolledpanel as wxscroll
28import wx.lib.mixins.listctrl  as  listmix
29import matplotlib as mpl
30import numpy as np
31import GSASIIpath
32GSASIIpath.SetVersionNumber("$Revision: 2184 $")
33import GSASIIimage as G2img
34import GSASIImath as G2mth
35import GSASIIplot as G2plt
36import GSASIIIO as G2IO
37import GSASIIgrid as G2gd
38import GSASIIctrls as G2G
39import GSASIIpy3 as G2py3
40
41VERY_LIGHT_GREY = wx.Colour(235,235,235)
42WACV = wx.ALIGN_CENTER_VERTICAL
43
44# trig functions in degrees
45sind = lambda x: math.sin(x*math.pi/180.)
46tand = lambda x: math.tan(x*math.pi/180.)
47cosd = lambda x: math.cos(x*math.pi/180.)
48asind = lambda x: 180.*math.asin(x)/math.pi
49   
50################################################################################
51##### Image Data
52################################################################################
53
54def GetImageZ(G2frame,data):
55    '''Gets image & applies dark, background & flat background corrections
56    '''
57   
58    Npix,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(G2frame.Image)
59    imagefile = G2IO.CheckImageFile(G2frame,imagefile)
60    sumImg = G2IO.GetImageData(G2frame,imagefile,True,ImageTag=imagetag)
61    if not 'dark image' in data:
62        return sumImg
63    darkImg,darkScale = data['dark image']
64    if darkImg:
65        Did = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, darkImg)
66        Npix,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(Did)
67        imagefile = G2IO.CheckImageFile(G2frame,imagefile)
68        darkImage = G2IO.GetImageData(G2frame,imagefile,True,ImageTag=imagetag)
69        sumImg += darkImage*darkScale
70    if not 'background image' in data:
71        return sumImg
72    backImg,backScale = data['background image']           
73    if backImg:     #ignores any transmission effect in the background image
74        Bid = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, backImg)
75        Npix,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(Bid)
76        imagefile = G2IO.CheckImageFile(G2frame,imagefile)
77        backImage = G2IO.GetImageData(G2frame,imagefile,True,ImageTag=imagetag)
78        Bdata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Bid,'Image Controls'))
79        if darkImg:
80            Did = G2gd.GetPatternTreeItemId(G2frame, G2frame.root,darkImg)
81            Npix,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(Did)
82            imagefile = G2IO.CheckImageFile(G2frame,imagefile)
83            darkImage = G2IO.GetImageData(G2frame,imagefile,True,ImageTag=imagetag)
84            backImage += darkImage*darkScale               
85        sumImg += backImage*backScale
86    sumImg -= data['Flat Bkg']
87    return sumImg
88   
89
90def UpdateImageData(G2frame,data):
91   
92    def OnPixVal(event):
93        Obj = event.GetEventObject()
94        id = Indx[Obj.GetId()]
95        try:
96            data['pixelSize'][id] = min(500,max(10,float(Obj.GetValue())))
97        except ValueError:
98            pass
99        Obj.SetValue('%.3f'%(data['pixelSize'][id]))
100        G2plt.PlotExposedImage(G2frame,newPlot=True,event=event)
101       
102    if G2frame.dataDisplay:
103        G2frame.dataDisplay.Destroy()
104    if not G2frame.dataFrame.GetStatusBar():
105        G2frame.dataFrame.CreateStatusBar()
106    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
107    G2frame.ImageZ = GetImageZ(G2frame,data)
108    mainSizer = wx.BoxSizer(wx.VERTICAL)
109    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,
110        label='Do not change anything here unless you are absolutely sure!'),0,WACV)
111    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Image size: %d by %d'%(data['size'][0],data['size'][1])),0,WACV)
112    pixSize = wx.FlexGridSizer(0,4,5,5)
113    pixLabels = [u' Pixel X-dimension (\xb5m)',u' Pixel Y-dimension (\xb5m)']
114    Indx = {}
115    for i,[pixLabel,pix] in enumerate(zip(pixLabels,data['pixelSize'])):
116        pixSize.Add(wx.StaticText(G2frame.dataDisplay,label=pixLabel),0,WACV)
117        pixVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(pix),style=wx.TE_PROCESS_ENTER)
118        Indx[pixVal.GetId()] = i
119        pixVal.Bind(wx.EVT_TEXT_ENTER,OnPixVal)
120        pixVal.Bind(wx.EVT_KILL_FOCUS,OnPixVal)
121        pixSize.Add(pixVal,0,WACV)
122    mainSizer.Add(pixSize,0)
123   
124    mainSizer.Layout()   
125    G2frame.dataDisplay.SetSizer(mainSizer)
126    fitSize = mainSizer.Fit(G2frame.dataFrame)
127    G2frame.dataFrame.setSizePosLeft(fitSize)
128    G2frame.dataDisplay.SetSize(fitSize)
129
130################################################################################
131##### Image Controls
132################################################################################                   
133def UpdateImageControls(G2frame,data,masks,IntegrateOnly=False):
134    '''Shows and handles the controls on the "Image Controls"
135    data tree entry
136    '''
137    import ImageCalibrants as calFile
138#patch
139    if 'Flat Bkg' not in data:
140        data['Flat Bkg'] = 0.0
141    if 'GonioAngles' not in data:
142        data['GonioAngles'] = [0.,0.,0.]
143    if 'DetDepth' not in data:
144        data['DetDepth'] = 0.
145    if 'SampleAbs' not in data:
146        data['SampleShape'] = 'Cylinder'
147        data['SampleAbs'] = [0.0,False]
148    if 'binType' not in data:
149        if 'PWDR' in data['type']:
150            data['binType'] = '2-theta'
151        elif 'SASD' in data['type']:
152            data['binType'] = 'log(q)'
153    if 'varyList' not in data:
154        data['varyList'] = {'dist':True,'det-X':True,'det-Y':True,'tilt':True,'phi':True,'dep':False,'wave':False}
155#end patch
156
157# Menu items
158           
159    def OnCalibrate(event):
160        if not data.get('calibrant'):
161            G2G.G2MessageBox(G2frame,'A calibrant must first be selected')
162        G2frame.dataFrame.GetStatusBar().SetStatusText('Select > 4 points on 1st used ring; LB to pick, RB on point to delete else RB to finish')
163        G2frame.ifGetRing = True
164               
165    def OnRecalibrate(event):
166        G2img.ImageRecalibrate(G2frame,data,masks)
167        wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
168       
169    def OnClearCalib(event):
170        data['ring'] = []
171        data['rings'] = []
172        data['ellipses'] = []
173        G2plt.PlotExposedImage(G2frame,event=event)
174           
175    def OnIntegrate(event):
176        '''Integrate image in response to a menu event or from the AutoIntegrate
177        dialog. In the latter case, event=None.
178        '''
179        CleanupMasks(masks)
180        blkSize = 128   #this seems to be optimal; will break in polymask if >1024
181        Nx,Ny = data['size']
182        nXBlks = (Nx-1)/blkSize+1
183        nYBlks = (Ny-1)/blkSize+1
184        Nup = nXBlks*nYBlks*3+3
185        dlg = wx.ProgressDialog("Elapsed time","2D image integration",Nup,
186            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE)
187        try:
188            sumImg = GetImageZ(G2frame,data)
189            G2frame.Integrate = G2img.ImageIntegrate(sumImg,data,masks,blkSize,dlg)
190            Id = G2IO.SaveIntegration(G2frame,G2frame.PickId,data,(event is None))
191            G2frame.PatternId = Id
192            G2frame.PatternTree.SelectItem(Id)
193            G2frame.PatternTree.Expand(Id)
194        finally:
195            dlg.Destroy()
196        for item in G2frame.MakePDF: item.Enable(True)
197       
198    def OnIntegrateAll(event):
199        TextList = [[False,'All IMG',0]]
200#        Names = []
201        if G2frame.PatternTree.GetCount():
202            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
203            while id:
204                name = G2frame.PatternTree.GetItemText(id)
205                if 'IMG' in name:
206                    TextList.append([False,name,id])
207                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
208            if len(TextList) == 1:
209                G2frame.ErrorDialog('Nothing to integrate','There must some "IMG" patterns')
210                return
211            dlg = G2frame.CopyDialog(G2frame,'Image integration controls','Select images to integrate:',TextList)
212            try:
213                if dlg.ShowModal() == wx.ID_OK:
214                    result = dlg.GetData()
215                    if result[0][0]:                    #the 'All IMG' is True
216                        result = TextList[1:]
217                        for item in result: item[0] = True
218                    G2frame.EnablePlot = False
219                    for item in result:
220                        ifintegrate,name,id = item
221                        G2frame.Image = id
222                        if ifintegrate:
223                            Id = G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls')
224                            Data = G2frame.PatternTree.GetItemPyData(Id)
225                            blkSize = 128   #this seems to be optimal; will break in polymask if >1024
226                            Nx,Ny = Data['size']
227                            nXBlks = (Nx-1)/blkSize+1
228                            nYBlks = (Ny-1)/blkSize+1
229                            Nup = nXBlks*nYBlks*3+3
230                            dlgp = wx.ProgressDialog("Elapsed time","2D image integration",Nup,
231                                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE)
232                            try:
233#                                GSASIIpath.IPyBreak()
234                                image = GetImageZ(G2frame,Data)
235                                Masks = G2frame.PatternTree.GetItemPyData(
236                                    G2gd.GetPatternTreeItemId(G2frame,id, 'Masks'))
237                                G2frame.Integrate = G2img.ImageIntegrate(image,Data,Masks,blkSize,dlgp)
238                                pId = G2IO.SaveIntegration(G2frame,Id,Data)
239                            finally:
240                                dlgp.Destroy()
241                    else:
242                        G2frame.EnablePlot = True
243                        G2frame.PatternTree.SelectItem(pId)
244                        G2frame.PatternTree.Expand(pId)
245                        G2frame.PatternId = pId
246                       
247            finally:
248                dlg.Destroy()
249       
250    def OnCopyControls(event):
251        TextList = [[False,'All IMG',0]]
252#        Names = []
253        if G2frame.PatternTree.GetCount():
254            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
255            while id:
256                name = G2frame.PatternTree.GetItemText(id)
257#                Names.append(name)
258                if 'IMG' in name:
259                    if id == G2frame.Image:
260                        Source = name
261                        Data = copy.deepcopy(data)
262#                        Data = copy.deepcopy(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls')))
263                        Data['showLines'] = True
264                        Data['ring'] = []
265                        Data['rings'] = []
266                        Data['ellipses'] = []
267                        Data['setDefault'] = False
268                    else:
269                        TextList.append([False,name,id])
270                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
271            if len(TextList) == 1:
272                G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "IMG" pattern')
273                return
274            dlg = G2frame.CopyDialog(G2frame,'Copy image controls','Copy controls from '+Source+' to:',TextList)
275            try:
276                if dlg.ShowModal() == wx.ID_OK:
277                    result = dlg.GetData()
278                    if result[0][0]:
279                        result = TextList[1:]
280                        for item in result: item[0] = True
281                    for i,item in enumerate(result):
282                        ifcopy,name,id = item
283                        if ifcopy:
284                            oldData = copy.deepcopy(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls')))
285                            Data['range'] = oldData['range']
286                            Data['size'] = oldData['size']
287                            Data['GonioAngles'] = oldData.get('GonioAngles', [0.,0.,0.])
288                            Data['ring'] = []
289                            Data['rings'] = []
290                            Data['ellipses'] = []
291                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls'),copy.deepcopy(Data))
292            finally:
293                dlg.Destroy()
294                G2frame.PatternTree.SelectItem(G2frame.PickId)
295               
296    def OnSaveControls(event):
297        pth = G2G.GetExportPath(G2frame)
298        dlg = wx.FileDialog(G2frame, 'Choose image controls file', pth, '', 
299            'image control files (*.imctrl)|*.imctrl',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
300        try:
301            if dlg.ShowModal() == wx.ID_OK:
302                filename = dlg.GetPath()
303                # make sure extension is .imctrl
304                filename = os.path.splitext(filename)[0]+'.imctrl'
305                File = open(filename,'w')
306                keys = ['type','wavelength','calibrant','distance','center',
307                    'tilt','rotation','azmthOff','fullIntegrate','LRazimuth',
308                    'IOtth','outChannels','outAzimuths','invert_x','invert_y','DetDepth',
309                    'calibskip','pixLimit','cutoff','calibdmin','chisq','Flat Bkg',
310                    'binType','SampleShape','PolaVal','SampleAbs','dark image','background image']
311                for key in keys:
312                    if key not in data:     #uncalibrated!
313                        continue
314                    File.write(key+':'+str(data[key])+'\n')
315                File.close()
316        finally:
317            dlg.Destroy()
318       
319    def OnLoadControls(event):
320        cntlList = ['wavelength','distance','tilt','invert_x','invert_y','type',
321            'fullIntegrate','outChannels','outAzimuths','LRazimuth','IOtth','azmthOff','DetDepth',
322            'calibskip','pixLimit','cutoff','calibdmin','chisq','Flat Bkg',
323            'PolaVal','SampleAbs','dark image','background image']
324        pth = G2G.GetImportPath(G2frame)
325        if not pth: pth = '.'
326        dlg = wx.FileDialog(G2frame, 'Choose image controls file', pth, '', 
327            'image control files (*.imctrl)|*.imctrl',wx.OPEN)
328        try:
329            if dlg.ShowModal() == wx.ID_OK:
330                filename = dlg.GetPath()
331                File = open(filename,'r')
332                save = {}
333                S = File.readline()
334                while S:
335                    if S[0] == '#':
336                        S = File.readline()
337                        continue
338                    [key,val] = S[:-1].split(':')
339                    if key in ['type','calibrant','binType','SampleShape',]:    #strings
340                        save[key] = val
341                    elif key in ['rotation']:
342                        save[key] = float(val)
343                    elif key in ['center',]:
344                        if ',' in val:
345                            save[key] = eval(val)
346                        else:
347                            vals = val.strip('[] ').split()
348                            save[key] = [float(vals[0]),float(vals[1])] 
349                    elif key in cntlList:
350                        save[key] = eval(val)
351                    S = File.readline()
352                data.update(save)
353                # next line removed. Previous updates tree contents. The next
354                # makes a copy of data, puts it into tree and "disconnects" data
355                # from tree contents (later changes to data are lost!)
356                #G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'),copy.deepcopy(data))
357                File.close()
358        finally:
359            dlg.Destroy()
360        G2plt.PlotExposedImage(G2frame,event=event)
361        wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
362           
363# Sizers
364    Indx = {}                                   
365    def ComboSizer():
366
367        def OnDataType(event):
368            data['type'] = typeSel.GetValue()[:4]
369            if 'SASD' in data['type']:
370                data['SampleAbs'][0] = np.exp(-data['SampleAbs'][0]) #switch from muT to trans!
371                if data['binType'] == '2-theta': data['binType'] = 'log(q)'  #switch default bin type
372            elif 'PWDR' in data['type']:
373                data['SampleAbs'][0] = -np.log(data['SampleAbs'][0])  #switch from trans to muT!
374                if data['binType'] == 'log(q)': data['binType'] = '2-theta'  #switch default bin type                 
375            wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
376   
377        def OnNewColorBar(event):
378            data['color'] = colSel.GetValue()
379            G2plt.PlotExposedImage(G2frame,event=event)
380       
381        def OnAzmthOff(event):
382            try:
383                azmthoff = float(azmthOff.GetValue())
384                data['azmthOff'] = azmthoff
385            except ValueError:
386                pass
387            azmthOff.SetValue("%.2f"%(data['azmthOff']))          #reset in case of error 
388            G2plt.PlotExposedImage(G2frame,event=event)
389       
390        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
391        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Type of image data: '),0,WACV)
392        typeSel = wx.ComboBox(parent=G2frame.dataDisplay,value=typeDict[data['type']],choices=typeList,
393            style=wx.CB_READONLY|wx.CB_DROPDOWN)
394        typeSel.SetValue(data['type'])
395        typeSel.Bind(wx.EVT_COMBOBOX, OnDataType)
396        comboSizer.Add(typeSel,0,WACV)
397        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Color bar '),0,WACV)
398        colSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['color'],choices=colorList,
399            style=wx.CB_READONLY|wx.CB_DROPDOWN)
400        colSel.Bind(wx.EVT_COMBOBOX, OnNewColorBar)
401        comboSizer.Add(colSel,0,WACV)
402        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Azimuth offset '),0,WACV)
403        azmthOff = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f" % (data['azmthOff'])),
404            style=wx.TE_PROCESS_ENTER)
405        azmthOff.Bind(wx.EVT_TEXT_ENTER,OnAzmthOff)
406        azmthOff.Bind(wx.EVT_KILL_FOCUS,OnAzmthOff)
407        comboSizer.Add(azmthOff,0,WACV)
408        return comboSizer
409       
410    def MaxSizer():
411               
412        def OnMaxVal(event):
413            try:
414                value = min(data['range'][0][1],int(maxVal.GetValue()))
415                if value < data['range'][1][0]+1:
416                    raise ValueError
417                data['range'][1][1] = value
418            except ValueError:
419                pass
420            maxVal.SetValue('%.0f'%(data['range'][1][1]))
421            DeltOne = data['range'][1][1]-max(0.0,data['range'][0][0])
422            sqrtDeltOne = math.sqrt(DeltOne)
423            maxSel.SetValue(int(100*sqrtDeltOne/sqrtDeltZero))
424            minSel.SetValue(int(100*(data['range'][1][0]/DeltOne)))
425            G2plt.PlotExposedImage(G2frame,event=event)
426           
427        def OnMinVal(event):
428            try:
429                value = int(minVal.GetValue())
430                if value > data['range'][1][1]-1:
431                    raise ValueError
432                data['range'][1][0] = value
433            except ValueError:
434                pass
435            minVal.SetValue('%.0f'%(data['range'][1][0]))
436            minSel.SetValue(int(100*(data['range'][1][0]-max(0.0,data['range'][0][0]))/DeltOne))
437            G2plt.PlotExposedImage(G2frame,event=event)
438           
439        def OnMaxSlider(event):
440            sqrtDeltZero = math.sqrt(data['range'][0][1])
441            imax = int(maxSel.GetValue())*sqrtDeltZero/100.
442            data['range'][1][1] = imax**2
443            data['range'][1][0] = max(0.0,min(data['range'][1][1]-1,data['range'][1][0]))
444            DeltOne = max(1.0,data['range'][1][1]-data['range'][1][0])
445            minSel.SetValue(int(100*(data['range'][1][0]/DeltOne)))
446            maxVal.SetValue('%.0f'%(data['range'][1][1]))
447            G2plt.PlotExposedImage(G2frame,event=event)
448           
449        def OnMinSlider(event):
450            DeltOne = data['range'][1][1]-data['range'][1][0]
451            imin = int(minSel.GetValue())*DeltOne/100.
452            data['range'][1][0] = max(0.0,min(data['range'][1][1]-1,imin))
453            minVal.SetValue('%.0f'%(data['range'][1][0]))
454            G2plt.PlotExposedImage(G2frame,event=event)
455           
456        maxSizer = wx.FlexGridSizer(0,3,0,5)
457        maxSizer.AddGrowableCol(1,1)
458        maxSizer.SetFlexibleDirection(wx.HORIZONTAL)
459        sqrtDeltZero = math.sqrt(data['range'][0][1]-max(0.0,data['range'][0][0]))
460        DeltOne = data['range'][1][1]-max(0.0,data['range'][0][0])
461        sqrtDeltOne = math.sqrt(DeltOne)
462        maxSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max intensity'),0,WACV)
463        maxSel = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
464            value=int(100*sqrtDeltOne/sqrtDeltZero))
465        maxSizer.Add(maxSel,1,wx.EXPAND)
466        maxSel.Bind(wx.EVT_SLIDER, OnMaxSlider)
467        maxVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.0f'%(data['range'][1][1]))
468        maxVal.Bind(wx.EVT_TEXT_ENTER,OnMaxVal)   
469        maxVal.Bind(wx.EVT_KILL_FOCUS,OnMaxVal)
470        maxSizer.Add(maxVal,0,WACV)   
471        maxSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Min intensity'),0,WACV)
472        minSel = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
473            value=int(100*(data['range'][1][0]-max(0.0,data['range'][0][0]))/DeltOne))
474        maxSizer.Add(minSel,1,wx.EXPAND)
475        minSel.Bind(wx.EVT_SLIDER, OnMinSlider)
476        minVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.0f'%(data['range'][1][0]))
477        minVal.Bind(wx.EVT_TEXT_ENTER,OnMinVal)   
478        minVal.Bind(wx.EVT_KILL_FOCUS,OnMinVal)
479        maxSizer.Add(minVal,0,WACV)
480        return maxSizer
481       
482    def CalibCoeffSizer():
483       
484        def OnCalRef(event):
485            Obj = event.GetEventObject()
486            name = Indx[Obj]
487            data['varyList'][name] = Obj.GetValue()
488           
489        def OnCalVal(event):
490            Obj = event.GetEventObject()
491            name = Indx[Obj]
492            try:
493                value = float(Obj.GetValue())
494                if name == 'wave' and value < 0.01:
495                    raise ValueError
496            except ValueError:
497                value = Parms[name][2]
498            if name == 'dist':
499                data['distance'] = value
500            elif name == 'det-X':
501                data['center'][0] = value
502            elif name == 'det-Y':
503                data['center'][1] = value
504            elif name == 'tilt':
505                data['tilt'] = value
506            elif name == 'phi':
507                data['rotation'] = value
508            elif name == 'wave':
509                data['wavelength'] = value
510            elif name == 'dep':
511                data['DetDepth'] = value                               
512            Parms[name][2] = value
513            Obj.SetValue(Parms[name][1]%(value))
514           
515        calibSizer = wx.FlexGridSizer(0,2,5,5)
516        calibSizer.SetFlexibleDirection(wx.HORIZONTAL)
517        calibSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calibration coefficients'),0,WACV)   
518        calibSizer.Add((5,0),0)
519        cent = data['center']
520        Names = ['det-X','det-Y','wave','dist','tilt','phi']
521        if 'PWDR' in data['type']:
522            Names.append('dep') 
523        Parms = {'dist':['Distance','%.3f',data['distance']],'det-X':['Beam center X','%.3f',data['center'][0]],
524            'det-Y':['Beam center Y','%.3f',data['center'][1]],'tilt':['Tilt angle','%.3f',data['tilt']],
525            'phi':['Tilt rotation','%.2f',data['rotation']],'dep':['Penetration','%.2f',data['DetDepth']],
526            'wave':['Wavelength','%.6f',data['wavelength']]}
527#        Indx = {}
528        for name in Names:
529            calSel = wx.CheckBox(parent=G2frame.dataDisplay,label=Parms[name][0])
530            calibSizer.Add(calSel,0,WACV)
531            calSel.Bind(wx.EVT_CHECKBOX, OnCalRef)
532            calSel.SetValue(data['varyList'][name])
533            Indx[calSel] = name
534            calVal = wx.TextCtrl(G2frame.dataDisplay,value=(Parms[name][1]%(Parms[name][2])),style=wx.TE_PROCESS_ENTER)
535            calVal.Bind(wx.EVT_TEXT_ENTER,OnCalVal)
536            calVal.Bind(wx.EVT_KILL_FOCUS,OnCalVal)
537            Indx[calVal] = name
538            calibSizer.Add(calVal,0,WACV)
539        return calibSizer
540   
541    def IntegrateSizer():
542       
543        def OnNewBinType(event):
544            data['binType'] = binSel.GetValue()
545            wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
546       
547        def OnIOtth(event):
548            Ltth = max(float(G2frame.InnerTth.GetValue()),0.001)
549            Utth = float(G2frame.OuterTth.GetValue())
550            if Ltth > Utth:
551                Ltth,Utth = Utth,Ltth
552            if 'Q' in data['binType']:
553                data['IOtth'] = [2.*asind(Ltth*wave/(4.*math.pi)),2.*asind(Utth*wave/(4.*math.pi))]
554            else:
555                data['IOtth'] = [Ltth,Utth]
556            G2frame.InnerTth.SetValue("%8.3f" % (Ltth))
557            G2frame.OuterTth.SetValue("%8.3f" % (Utth))
558            G2plt.PlotExposedImage(G2frame,event=event)
559       
560        def OnLRazim(event):
561            Lazm = int(G2frame.Lazim.GetValue())%360
562            Razm = int(G2frame.Razim.GetValue())%360
563            if Lazm > Razm:
564                Razm += 360
565            if data['fullIntegrate']:
566                Razm = Lazm+360
567            G2frame.Lazim.SetValue("%6d" % (Lazm))
568            G2frame.Razim.SetValue("%6d" % (Razm))
569            data['LRazimuth'] = [Lazm,Razm]
570            G2plt.PlotExposedImage(G2frame,event=event)
571       
572        def OnNumOutChans(event):
573            try:
574                numChans = int(outChan.GetValue())
575                if numChans < 10:
576                    raise ValueError
577                data['outChannels'] = numChans
578            except ValueError:
579                pass
580            outChan.SetValue(str(data['outChannels']))          #reset in case of error       
581       
582        def OnNumOutAzms(event):
583            try:
584                numAzms = int(outAzim.GetValue())
585                if numAzms < 1:
586                    raise ValueError
587                data['outAzimuths'] = numAzms           
588            except ValueError:
589                pass
590            outAzim.SetValue(str(data['outAzimuths']))          #reset in case of error       
591            G2plt.PlotExposedImage(G2frame,event=event)
592       
593        def OnOblique(event):
594            if data['Oblique'][1]:
595                data['Oblique'][1] = False
596            else:
597                data['Oblique'][1] = True
598               
599        def OnObliqVal(event):
600            try:
601                value = float(obliqVal.GetValue())
602                if 0.01 <= value <= 0.99:
603                    data['Oblique'][0] = value
604                else:
605                    raise ValueError
606            except ValueError:
607                pass
608            obliqVal.SetValue('%.3f'%(data['Oblique'][0]))
609           
610        def OnSampleShape(event):
611            data['SampleShape'] = samShape.GetValue()
612            if 'Cylind' in data['SampleShape']:
613                data['SampleAbs'][0] = 0.0
614            elif 'Fixed' in data['SampleShape']:
615                data['SampleAbs'][0] = 1.0
616            wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
617                           
618        def OnSamAbs(event):
619            if data['SampleAbs'][1]:
620                data['SampleAbs'][1] = False
621            else:
622                data['SampleAbs'][1] = True
623               
624        def OnSamAbsVal(event):
625            try:
626                value = float(samabsVal.GetValue())
627                minmax = [0.,2.]
628                if 'Fixed' in data['SampleShape']:
629                    minmax = [.05,1.0]
630                if minmax[0] <= value <= minmax[1]:
631                    data['SampleAbs'][0] = value
632                else:
633                    raise ValueError
634            except ValueError:
635                pass
636            samabsVal.SetValue('%.3f'%(data['SampleAbs'][0]))
637                           
638        def OnShowLines(event):
639            if data['showLines']:
640                data['showLines'] = False
641            else:
642                data['showLines'] = True
643            G2plt.PlotExposedImage(G2frame,event=event)
644           
645        def OnFullIntegrate(event):
646            Lazm =int(G2frame.Lazim.GetValue())
647            if data['fullIntegrate']:
648                data['fullIntegrate'] = False
649                data['LRazimuth'] = [Lazm,Lazm+20]
650            else:
651                data['fullIntegrate'] = True
652                data['LRazimuth'] = [Lazm,Lazm+360]
653            wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
654            G2plt.PlotExposedImage(G2frame,event=event)
655           
656        def OnSetDefault(event):
657            if data['setDefault']:
658                G2frame.imageDefault = {}
659                data['setDefault'] = False
660            else:
661                G2frame.imageDefault = copy.copy(data)
662                data['setDefault'] = True
663               
664        def OnCenterAzm(event):
665            if data['centerAzm']:
666                data['centerAzm'] = False
667            else:
668                data['centerAzm'] = True
669            G2plt.PlotExposedImage(G2frame,event=event)
670               
671        def OnApplyPola(event):
672            if data['PolaVal'][1]:
673                data['PolaVal'][1] = False
674            else:
675                data['PolaVal'][1] = True
676               
677        def OnPolaVal(event):
678            try:
679                value = float(polaVal.GetValue())
680                if 0.001 <= value <= 0.999:
681                    data['PolaVal'][0] = value
682                else:
683                    raise ValueError
684            except ValueError:
685                pass
686            polaVal.SetValue('%.3f'%(data['PolaVal'][0]))
687                           
688        dataSizer = wx.FlexGridSizer(0,2,5,3)
689        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Integration coefficients'),0,WACV)   
690        dataSizer.Add((5,0),0)
691        if 'PWDR' in data['type']:
692            binChoice = ['2-theta','Q']
693        elif 'SASD' in data['type']:
694            binChoice = ['2-theta','Q','log(q)']
695        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Bin style: Constant step bins in'),0,WACV)           
696        binSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['binType'],choices=binChoice,
697            style=wx.CB_READONLY|wx.CB_DROPDOWN)
698        binSel.Bind(wx.EVT_COMBOBOX, OnNewBinType)
699        dataSizer.Add(binSel,0,WACV)
700        binType = '2-theta'
701        if 'q' in data['binType'].lower():
702            binType = 'Q'
703        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Inner/Outer '+binType),0,WACV)           
704        IOtth = data['IOtth'][:]
705        if 'Q' in data['binType']:
706            wave = data['wavelength']
707            IOtth = [4.*math.pi*sind(IOtth[0]/2.)/wave,4.*math.pi*sind(IOtth[1]/2.)/wave]
708        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
709        G2frame.InnerTth = wx.TextCtrl(parent=G2frame.dataDisplay,
710            value=("%8.3f" % (IOtth[0])),style=wx.TE_PROCESS_ENTER)
711        G2frame.InnerTth.Bind(wx.EVT_TEXT_ENTER,OnIOtth)
712        G2frame.InnerTth.Bind(wx.EVT_KILL_FOCUS,OnIOtth)
713        littleSizer.Add(G2frame.InnerTth,0,WACV)
714        G2frame.OuterTth = wx.TextCtrl(parent=G2frame.dataDisplay,
715            value=("%8.2f" % (IOtth[1])),style=wx.TE_PROCESS_ENTER)
716        G2frame.OuterTth.Bind(wx.EVT_TEXT_ENTER,OnIOtth)
717        G2frame.OuterTth.Bind(wx.EVT_KILL_FOCUS,OnIOtth)
718        littleSizer.Add(G2frame.OuterTth,0,WACV)
719        dataSizer.Add(littleSizer,0,)
720        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start/End azimuth'),0,WACV)
721        LRazim = data['LRazimuth']
722        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
723        G2frame.Lazim = wx.TextCtrl(parent=G2frame.dataDisplay,
724            value=("%6d" % (LRazim[0])),style=wx.TE_PROCESS_ENTER)
725        G2frame.Lazim.Bind(wx.EVT_TEXT_ENTER,OnLRazim)
726        G2frame.Lazim.Bind(wx.EVT_KILL_FOCUS,OnLRazim)
727        littleSizer.Add(G2frame.Lazim,0,WACV)
728        G2frame.Razim = wx.TextCtrl(parent=G2frame.dataDisplay,
729            value=("%6d" % (LRazim[1])),style=wx.TE_PROCESS_ENTER)
730        G2frame.Razim.Bind(wx.EVT_TEXT_ENTER,OnLRazim)
731        G2frame.Razim.Bind(wx.EVT_KILL_FOCUS,OnLRazim)
732        if data['fullIntegrate']:
733            G2frame.Razim.Enable(False)
734            G2frame.Razim.SetBackgroundColour(VERY_LIGHT_GREY)
735            G2frame.Razim.SetValue("%6d" % (LRazim[0]+360))
736        littleSizer.Add(G2frame.Razim,0,WACV)
737        dataSizer.Add(littleSizer,0,)
738        dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' No. 2-theta/azimuth bins'),0,WACV)
739        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
740        outChan = wx.TextCtrl(parent=G2frame.dataDisplay,value=str(data['outChannels']),style=wx.TE_PROCESS_ENTER)
741        outChan.Bind(wx.EVT_TEXT_ENTER,OnNumOutChans)
742        outChan.Bind(wx.EVT_KILL_FOCUS,OnNumOutChans)
743        littleSizer.Add(outChan,0,WACV)
744        outAzim = wx.TextCtrl(parent=G2frame.dataDisplay,value=str(data['outAzimuths']),style=wx.TE_PROCESS_ENTER)
745        outAzim.Bind(wx.EVT_TEXT_ENTER,OnNumOutAzms)
746        outAzim.Bind(wx.EVT_KILL_FOCUS,OnNumOutAzms)
747        littleSizer.Add(outAzim,0,WACV)
748        dataSizer.Add(littleSizer,0,)
749        samplechoice = ['Cylinder','Fixed flat plate',]
750        dataSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Select sample shape'),0,WACV)
751        samShape = wx.ComboBox(G2frame.dataDisplay,value=data['SampleShape'],choices=samplechoice,
752            style=wx.CB_READONLY|wx.CB_DROPDOWN)
753        samShape.Bind(wx.EVT_COMBOBOX,OnSampleShape)
754        dataSizer.Add(samShape,0,WACV)
755        #SampleShape - cylinder or flat plate choice?
756        littleSizer = wx.BoxSizer(wx.HORIZONTAL)
757        samabs = wx.CheckBox(parent=G2frame.dataDisplay,label='Apply sample absorption?')
758        dataSizer.Add(samabs,0,WACV)
759        samabs.Bind(wx.EVT_CHECKBOX, OnSamAbs)
760        samabs.SetValue(data['SampleAbs'][1])
761        if 'Cylind' in data['SampleShape']: #cylinder mu*R; flat plate transmission
762            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='mu*R (0.00-2.0) '),0,WACV)
763        elif 'Fixed' in data['SampleShape']:
764            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='transmission '),0,WACV) #for flat plate
765        samabsVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.3f'%(data['SampleAbs'][0]),style=wx.TE_PROCESS_ENTER)           
766        samabsVal.Bind(wx.EVT_TEXT_ENTER,OnSamAbsVal)
767        samabsVal.Bind(wx.EVT_KILL_FOCUS,OnSamAbsVal)
768        littleSizer.Add(samabsVal,0,WACV)
769        dataSizer.Add(littleSizer,0,)       
770        if 'PWDR' in data['type']:
771            littleSizer = wx.BoxSizer(wx.HORIZONTAL)
772            oblique = wx.CheckBox(parent=G2frame.dataDisplay,label='Apply detector absorption?')
773            dataSizer.Add(oblique,0,WACV)
774            oblique.Bind(wx.EVT_CHECKBOX, OnOblique)
775            oblique.SetValue(data['Oblique'][1])
776            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Value (0.01-0.99)  '),0,WACV)
777            obliqVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.3f'%(data['Oblique'][0]),style=wx.TE_PROCESS_ENTER)
778            obliqVal.Bind(wx.EVT_TEXT_ENTER,OnObliqVal)
779            obliqVal.Bind(wx.EVT_KILL_FOCUS,OnObliqVal)
780            littleSizer.Add(obliqVal,0,WACV)
781            dataSizer.Add(littleSizer,0,)
782        if 'SASD' in data['type']:
783            littleSizer = wx.BoxSizer(wx.HORIZONTAL)
784            setPolariz = wx.CheckBox(parent=G2frame.dataDisplay,label='Apply polarization?')
785            dataSizer.Add(setPolariz,0,WACV)
786            setPolariz.Bind(wx.EVT_CHECKBOX, OnApplyPola)
787            setPolariz.SetValue(data['PolaVal'][1])
788            littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Value (0.001-0.999)  '),0,WACV)
789            polaVal = wx.TextCtrl(parent=G2frame.dataDisplay,value='%.3f'%(data['PolaVal'][0]),
790                style=wx.TE_PROCESS_ENTER)
791            polaVal.Bind(wx.EVT_TEXT_ENTER,OnPolaVal)
792            polaVal.Bind(wx.EVT_KILL_FOCUS,OnPolaVal)
793            littleSizer.Add(polaVal,0,WACV)
794            dataSizer.Add(littleSizer,0,)
795       
796        showLines = wx.CheckBox(parent=G2frame.dataDisplay,label='Show integration limits?')
797        dataSizer.Add(showLines,0,WACV)
798        showLines.Bind(wx.EVT_CHECKBOX, OnShowLines)
799        showLines.SetValue(data['showLines'])
800        fullIntegrate = wx.CheckBox(parent=G2frame.dataDisplay,label='Do full integration?')
801        dataSizer.Add(fullIntegrate,0,WACV)
802        fullIntegrate.Bind(wx.EVT_CHECKBOX, OnFullIntegrate)
803        fullIntegrate.SetValue(data['fullIntegrate'])
804        setDefault = wx.CheckBox(parent=G2frame.dataDisplay,label='Use as default for all images?')
805        dataSizer.Add(setDefault,0,WACV)
806        setDefault.Bind(wx.EVT_CHECKBOX, OnSetDefault)
807        setDefault.SetValue(data['setDefault'])
808        centerAzm = wx.CheckBox(parent=G2frame.dataDisplay,label='Azimuth at bin center?')
809        dataSizer.Add(centerAzm,0,WACV)
810        centerAzm.Bind(wx.EVT_CHECKBOX, OnCenterAzm)
811        centerAzm.SetValue(data['centerAzm'])
812        return dataSizer
813       
814    def BackSizer():
815       
816        def ResetThresholds():
817            Imin = max(0.,np.min(G2frame.ImageZ))
818            Imax = np.max(G2frame.ImageZ)
819            data['range'] = [(Imin,Imax),[Imin,Imax]]
820            masks['Thresholds'] = [(Imin,Imax),[Imin,Imax]]
821            MaxSizer.GetChildren()[2].Window.SetValue(str(int(Imax)))   #tricky
822            MaxSizer.GetChildren()[5].Window.SetValue(str(int(Imin)))   #tricky
823       
824        def OnBackImage(event):
825            data['background image'][0] = backImage.GetValue()
826            G2frame.ImageZ = GetImageZ(G2frame,data)
827            ResetThresholds()
828            G2plt.PlotExposedImage(G2frame,event=event)
829           
830        def OnDarkImage(event):
831            data['dark image'][0] = darkImage.GetValue()
832            G2frame.ImageZ = GetImageZ(G2frame,data)
833            ResetThresholds()
834            G2plt.PlotExposedImage(G2frame,event=event)
835           
836        def OnFlatBkg(event):
837            oldFlat = data.get('Flat Bkg',0.)
838            try:
839                value = float(flatbkg.GetValue())
840                data['Flat Bkg'] = value
841            except ValueError:
842                pass
843            flatbkg.SetValue("%.0f"%(data['Flat Bkg']))   
844            G2frame.ImageZ += (oldFlat-data['Flat Bkg'])
845            ResetThresholds()
846            G2plt.PlotExposedImage(G2frame,event=event)
847
848        def OnBackMult(event):
849            try:
850                mult = float(backMult.GetValue())
851                data['background image'][1] = mult
852            except ValueError:
853                pass
854            backMult.SetValue("%.3f" % (data['background image'][1]))          #reset in case of error
855            G2frame.ImageZ = GetImageZ(G2frame,data)
856            ResetThresholds()
857            G2plt.PlotExposedImage(G2frame,event=event)
858       
859        def OnDarkMult(event):
860            try:
861                mult = float(darkMult.GetValue())
862                data['dark image'][1] = mult
863            except ValueError:
864                pass
865            darkMult.SetValue("%.3f" % (data['dark image'][1]))          #reset in case of error
866            G2frame.ImageZ = GetImageZ(G2frame,data)
867            ResetThresholds()
868            G2plt.PlotExposedImage(G2frame,event=event)
869       
870        backSizer = wx.FlexGridSizer(0,6,5,5)
871
872        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Dark image'),0,WACV)
873        Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
874        darkImage = wx.ComboBox(parent=G2frame.dataDisplay,value=data['dark image'][0],choices=Choices,
875            style=wx.CB_READONLY|wx.CB_DROPDOWN)
876        darkImage.Bind(wx.EVT_COMBOBOX,OnDarkImage)
877        backSizer.Add(darkImage)
878        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' multiplier'),0,WACV)
879        darkMult =  wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (data['dark image'][1])),
880            style=wx.TE_PROCESS_ENTER)
881        darkMult.Bind(wx.EVT_TEXT_ENTER,OnDarkMult)
882        darkMult.Bind(wx.EVT_KILL_FOCUS,OnDarkMult)
883        backSizer.Add(darkMult,0,WACV)
884        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Flat Bkg: '),0,WACV)
885        flatbkg = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.0f" % (data['Flat Bkg'])),
886            style=wx.TE_PROCESS_ENTER)
887        flatbkg.Bind(wx.EVT_TEXT_ENTER,OnFlatBkg)
888        flatbkg.Bind(wx.EVT_KILL_FOCUS,OnFlatBkg)
889        backSizer.Add(flatbkg,0,WACV)
890
891        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background image'),0,WACV)
892        Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
893        backImage = wx.ComboBox(parent=G2frame.dataDisplay,value=data['background image'][0],choices=Choices,
894            style=wx.CB_READONLY|wx.CB_DROPDOWN)
895        backImage.Bind(wx.EVT_COMBOBOX,OnBackImage)
896        backSizer.Add(backImage)
897        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' multiplier'),0,WACV)
898        backMult =  wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (data['background image'][1])),
899            style=wx.TE_PROCESS_ENTER)
900        backMult.Bind(wx.EVT_TEXT_ENTER,OnBackMult)
901        backMult.Bind(wx.EVT_KILL_FOCUS,OnBackMult)
902        backSizer.Add(backMult,0,WACV)
903        return backSizer
904                       
905    def CalibSizer():
906               
907        def OnNewCalibrant(event):
908            data['calibrant'] = calSel.GetValue()
909            data['calibskip'] = calFile.Calibrants[data['calibrant']][3]
910            limits = calFile.Calibrants[data['calibrant']][4]
911            data['calibdmin'],data['pixLimit'],data['cutoff'] = limits
912            pixLimit.SetValue(str(limits[1]))
913            cutOff.SetValue('%.1f'%(limits[2]))
914            calibSkip.SetValue(str(data['calibskip']))
915            calibDmin.SetValue('%.1f'%(limits[0]))
916           
917        def OnCalibSkip(event):
918            data['calibskip'] = int(calibSkip.GetValue())
919           
920        def OnCalibDmin(event):
921            try:
922                dmin = float(calibDmin.GetValue())
923                if dmin < 0.25:
924                    raise ValueError
925                data['calibdmin'] = dmin
926            except ValueError:
927                pass
928            calibDmin.SetValue("%.2f"%(data['calibdmin']))          #reset in case of error 
929                   
930        def OnCutOff(event):
931            try:
932                cutoff = float(cutOff.GetValue())
933                if cutoff < 0.1:
934                    raise ValueError
935                data['cutoff'] = cutoff
936            except ValueError:
937                pass
938            cutOff.SetValue("%.1f"%(data['cutoff']))          #reset in case of error 
939       
940        def OnPixLimit(event):
941            data['pixLimit'] = int(pixLimit.GetValue())
942           
943        def OnSetRings(event):
944            if data['setRings']:
945                data['setRings'] = False
946            else:
947                data['setRings'] = True
948            G2plt.PlotExposedImage(G2frame,event=event)
949   
950        calibSizer = wx.FlexGridSizer(0,3,5,5)
951        comboSizer = wx.BoxSizer(wx.HORIZONTAL)   
952        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calibrant '),0,WACV)
953        calSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['calibrant'],choices=calList,
954            style=wx.CB_READONLY|wx.CB_DROPDOWN)
955        calSel.Bind(wx.EVT_COMBOBOX, OnNewCalibrant)
956        comboSizer.Add(calSel,0,WACV)
957        calibSizer.Add(comboSizer,0)
958       
959        comboSizer = wx.BoxSizer(wx.HORIZONTAL)   
960        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calib lines to skip   '),0,WACV)
961        calibSkip  = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['calibskip']),choices=[str(i) for i in range(25)],
962            style=wx.CB_READONLY|wx.CB_DROPDOWN)
963        calibSkip.Bind(wx.EVT_COMBOBOX, OnCalibSkip)
964        comboSizer.Add(calibSkip,0,WACV)
965        calibSizer.Add(comboSizer,0)
966       
967        comboSizer = wx.BoxSizer(wx.HORIZONTAL)       
968        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Min calib d-spacing '),0,WACV)
969        calibDmin = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f" % (data['calibdmin'])),
970            style=wx.TE_PROCESS_ENTER)
971        calibDmin.Bind(wx.EVT_TEXT_ENTER,OnCalibDmin)
972        calibDmin.Bind(wx.EVT_KILL_FOCUS,OnCalibDmin)
973        comboSizer.Add(calibDmin,0,WACV)
974        calibSizer.Add(comboSizer,0)
975       
976        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
977        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Min ring I/Ib '),0,WACV)
978        cutOff = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.1f" % (data['cutoff'])),
979            style=wx.TE_PROCESS_ENTER)
980        cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)
981        cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
982        comboSizer.Add(cutOff,0,WACV)
983        calibSizer.Add(comboSizer,0)
984       
985        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
986        comboSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Pixel search range '),0,WACV)
987        pixLimit = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['pixLimit']),choices=['1','2','5','10','15','20'],
988            style=wx.CB_READONLY|wx.CB_DROPDOWN)
989        pixLimit.Bind(wx.EVT_COMBOBOX, OnPixLimit)
990        comboSizer.Add(pixLimit,0,WACV)
991        calibSizer.Add(comboSizer,0)
992       
993        comboSizer = wx.BoxSizer(wx.HORIZONTAL)
994        setRings = wx.CheckBox(parent=G2frame.dataDisplay,label='Show ring picks?')
995        comboSizer.Add(setRings,0)
996        setRings.Bind(wx.EVT_CHECKBOX, OnSetRings)
997        setRings.SetValue(data['setRings'])
998        calibSizer.Add(comboSizer,0)
999        return calibSizer
1000       
1001    def GonioSizer():
1002       
1003        ValObj = {}
1004       
1005        def OnGonioAngle(event):
1006            Obj = event.GetEventObject()
1007            item = ValObj[Obj.GetId()]
1008            try:
1009                value = float(Obj.GetValue())
1010            except ValueError:
1011                value = data['GonioAngles'][item]
1012            data['GonioAngles'][item] = value
1013            Obj.SetValue('%8.2f'%(value))
1014           
1015        def OnGlobalEdit(event):
1016            Names = []
1017            Items = []
1018            if G2frame.PatternTree.GetCount():
1019                id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1020                while id:
1021                    name = G2frame.PatternTree.GetItemText(id)
1022                    if 'IMG' in name:
1023                        ctrls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id,'Image Controls'))
1024                        Names.append(name)
1025                        Items.append(ctrls['GonioAngles'])
1026                    id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1027                if len(Names) == 1:
1028                    G2frame.ErrorDialog('Nothing for global editing','There must be more than one "IMG" pattern')
1029                    return
1030                dlg = G2G.G2HistoDataDialog(G2frame,' Edit sample goniometer data:',
1031                    'Edit data',['Omega','Chi','Phi'],['%.2f','%.2f','%.2f'],Names,Items)
1032            try:
1033                if dlg.ShowModal() == wx.ID_OK:
1034                    result = dlg.GetData()
1035                    id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1036                    while id:
1037                        name = G2frame.PatternTree.GetItemText(id)
1038                        if 'IMG' in name:
1039                            ctrls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id,'Image Controls'))
1040                            vals = Items[Names.index(name)]
1041                            ctrls['GonioAngles'] = vals
1042#                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Image Controls'),ctrls)
1043                        id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1044            finally:
1045                dlg.Destroy()
1046                G2frame.PatternTree.SelectItem(G2frame.PickId)
1047       
1048        gonioSizer = wx.BoxSizer(wx.HORIZONTAL)
1049        names = ['Omega','Chi','Phi']
1050        gonioSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'Sample goniometer angles: '),0,WACV)
1051        for i,name in enumerate(names):
1052            gonioSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,name),0,WACV)
1053            angle = wx.TextCtrl(G2frame.dataDisplay,-1,value='%8.2f'%(data['GonioAngles'][i]),
1054                style=wx.TE_PROCESS_ENTER)
1055            angle.Bind(wx.EVT_TEXT_ENTER,OnGonioAngle)
1056            angle.Bind(wx.EVT_KILL_FOCUS,OnGonioAngle)
1057            ValObj[angle.GetId()] = i
1058            gonioSizer.Add(angle,0,WACV)
1059        globEdit = wx.Button(G2frame.dataDisplay,-1,'Global edit')
1060        globEdit.Bind(wx.EVT_BUTTON,OnGlobalEdit)
1061        gonioSizer.Add(globEdit,0,WACV)
1062        return gonioSizer
1063       
1064# Image Controls main code             
1065                           
1066    #fix for old files:
1067    if 'azmthOff' not in data:
1068        data['azmthOff'] = 0.0
1069    if 'background image' not in data:
1070        data['background image'] = ['',-1.0]
1071    if 'dark image' not in data:
1072        data['dark image'] = ['',-1.0]
1073    if 'centerAzm' not in data:
1074        data['centerAzm'] = False
1075    if 'Oblique' not in data:
1076        data['Oblique'] = [0.5,False]
1077    if 'PolaVal' not in data:
1078        data['PolaVal'] = [0.99,False]
1079    #end fix
1080   
1081    if IntegrateOnly:
1082        OnIntegrate(None)
1083        return
1084   
1085    colorList = sorted([m for m in mpl.cm.datad.keys() if not m.endswith("_r")],key=lambda s: s.lower())
1086    calList = sorted([m for m in calFile.Calibrants.keys()],key=lambda s: s.lower())
1087    typeList = ['PWDR - powder diffraction data','SASD - small angle scattering data',
1088        'REFL - reflectometry data']
1089    if not data.get('type'):                        #patch for old project files
1090        data['type'] = 'PWDR'
1091    typeDict = {'PWDR':typeList[0],'SASD':typeList[1],'REFL':typeList[2]}
1092    if G2frame.dataDisplay:
1093        G2frame.dataDisplay.Destroy()
1094    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ImageMenu)
1095    if not G2frame.dataFrame.GetStatusBar():
1096        G2frame.dataFrame.CreateStatusBar()
1097    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCalibrate, id=G2gd.wxID_IMCALIBRATE)
1098    G2frame.dataFrame.Bind(wx.EVT_MENU, OnRecalibrate, id=G2gd.wxID_IMRECALIBRATE)
1099    G2frame.dataFrame.Bind(wx.EVT_MENU, OnClearCalib, id=G2gd.wxID_IMCLEARCALIB)
1100    if data.get('calibrant'):
1101        G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=True)
1102    else:
1103        G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=False)
1104    G2frame.dataFrame.Bind(wx.EVT_MENU, OnIntegrate, id=G2gd.wxID_IMINTEGRATE)
1105    G2frame.dataFrame.Bind(wx.EVT_MENU, OnIntegrateAll, id=G2gd.wxID_INTEGRATEALL)
1106    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyControls, id=G2gd.wxID_IMCOPYCONTROLS)
1107    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveControls, id=G2gd.wxID_IMSAVECONTROLS)
1108    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadControls, id=G2gd.wxID_IMLOADCONTROLS)
1109    def OnDestroy(event):
1110        G2frame.autoIntFrame = None
1111    def OnAutoInt(event):
1112        if G2frame.autoIntFrame: # ensure only one open at a time
1113            G2frame.autoIntFrame.Raise()
1114            return
1115        G2frame.autoIntFrame = AutoIntFrame(G2frame,PollTime=10.0)
1116        G2frame.autoIntFrame.Bind(wx.EVT_WINDOW_DESTROY,OnDestroy) # clean up name on window close
1117    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAutoInt, id=G2gd.wxID_IMAUTOINTEG)
1118    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1119
1120    mainSizer = wx.BoxSizer(wx.VERTICAL)
1121    mainSizer.Add((5,10),0)   
1122    mainSizer.Add(ComboSizer(),0,wx.ALIGN_LEFT)
1123    mainSizer.Add((5,5),0)
1124    MaxSizer = MaxSizer()               #keep this so it can be changed in BackSizer   
1125    mainSizer.Add(MaxSizer,0,wx.ALIGN_LEFT|wx.EXPAND)
1126   
1127    mainSizer.Add((5,5),0)
1128    DataSizer = wx.FlexGridSizer(0,2,5,0)
1129    DataSizer.Add(CalibCoeffSizer(),0)
1130    DataSizer.Add(IntegrateSizer(),0)       
1131    mainSizer.Add(DataSizer,0)
1132    mainSizer.Add((5,5),0)           
1133    mainSizer.Add(BackSizer(),0)
1134    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Calibration controls:'),0,WACV)
1135    mainSizer.Add((5,5),0)
1136    mainSizer.Add(CalibSizer(),0,WACV)
1137    mainSizer.Add((5,5),0)
1138    mainSizer.Add(GonioSizer(),0,WACV)   
1139       
1140    mainSizer.Layout()   
1141    G2frame.dataDisplay.SetSizer(mainSizer)
1142    fitSize = mainSizer.Fit(G2frame.dataFrame)
1143    G2frame.dataFrame.setSizePosLeft(fitSize)
1144    G2frame.dataDisplay.SetSize(fitSize)
1145   
1146################################################################################
1147##### Masks
1148################################################################################
1149def CleanupMasks(data):
1150    '''If a mask creation is not completed, an empty mask entry is created in the
1151    masks array. This cleans them out. It is called when the masks page is first loaded
1152    and before saving them or after reading them in. This should also probably be done
1153    before they are used for integration.
1154    '''
1155    for key in ['Points','Rings','Arcs','Polygons']:
1156        data[key] = data.get(key,[])
1157        l1 = len(data[key])
1158        data[key] = [i for i in data[key] if i]
1159        l2 = len(data[key])
1160        if GSASIIpath.GetConfigValue('debug') and l1 != l2:
1161            print 'Mask Cleanup:',key,'was',l1,'entries','now',l2
1162   
1163def UpdateMasks(G2frame,data):
1164    '''Shows and handles the controls on the "Masks" data tree entry
1165    '''
1166   
1167    def OnTextMsg(event):
1168        Obj = event.GetEventObject()
1169        Obj.SetToolTipString('Drag this mask on 2D Powder Image with mouse to change ')
1170
1171    def Replot(*args,**kwargs):
1172        wx.CallAfter(G2plt.PlotExposedImage,G2frame)
1173
1174    def onDeleteMask(event):
1175        Obj = event.GetEventObject()
1176        typ = Obj.locationcode.split('+')[1]
1177        num = int(Obj.locationcode.split('+')[2])
1178        del(data[typ][num])
1179        wx.CallAfter(UpdateMasks,G2frame,data)
1180        G2plt.PlotExposedImage(G2frame,event=event)
1181
1182    def onDeleteFrame(event):
1183        data['Frames'] = []
1184        wx.CallAfter(UpdateMasks,G2frame,data)
1185        G2plt.PlotExposedImage(G2frame,event=event)
1186
1187    def OnCopyMask(event):
1188        TextList = [[False,'All IMG',0]]
1189#        Names = []
1190        if G2frame.PatternTree.GetCount():
1191            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1192            while id:
1193                name = G2frame.PatternTree.GetItemText(id)
1194#                Names.append(name)
1195                if 'IMG' in name:
1196                    if id == G2frame.Image:
1197                        Source = name
1198                        Mask = copy.deepcopy(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Masks')))
1199                        Thresh = Mask.pop('Thresholds')  #remove Thresholds from source mask & save it for later
1200                    else:
1201                        TextList.append([False,name,id])
1202                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1203            if len(TextList) == 1:
1204                G2frame.ErrorDialog('Nothing to copy mask to','There must be more than one "IMG" pattern')
1205                return
1206            dlg = G2frame.CopyDialog(G2frame,'Copy mask information','Copy mask from '+Source+' to:',TextList)
1207            try:
1208                if dlg.ShowModal() == wx.ID_OK:
1209                    result = dlg.GetData()
1210                    if result[0][0]:
1211                        result = TextList[1:]
1212                        for item in result: item[0] = True
1213                    for i,item in enumerate(result):
1214                        ifcopy,name,id = item
1215                        if ifcopy:
1216                            mask = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Masks'))
1217#                            Mask['Thresholds'][0] = mask['Thresholds'][0]
1218#                            Mask['Thresholds'][1][1] = min(mask['Thresholds'][1][1],Mask['Thresholds'][1][1])
1219                            mask.update(Mask)
1220                            mask['Thresholds'][1][0] = Thresh[1][0]  #copy only lower threshold                             
1221                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Masks'),copy.deepcopy(mask))
1222            finally:
1223                dlg.Destroy()
1224               
1225    def OnSaveMask(event):
1226        CleanupMasks(data)
1227        pth = G2G.GetExportPath(G2frame)
1228        dlg = wx.FileDialog(G2frame, 'Choose image mask file', pth, '', 
1229            'image mask files (*.immask)|*.immask',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1230        try:
1231            if dlg.ShowModal() == wx.ID_OK:
1232                filename = dlg.GetPath()
1233                filename = os.path.splitext(filename)[0]+'.immask'
1234                File = open(filename,'w')
1235                keys = ['Points','Rings','Arcs','Polygons','Frames','Thresholds']
1236                for key in keys:
1237                    File.write(key+':'+str(data[key])+'\n')
1238                File.close()
1239        finally:
1240            dlg.Destroy()
1241       
1242    def OnLoadMask(event):
1243        if event.Id == G2gd.wxID_MASKLOADNOT:
1244            ignoreThreshold = True
1245        else:
1246            ignoreThreshold = False
1247        pth = G2G.GetImportPath(G2frame)
1248        if not pth: pth = '.'
1249        dlg = wx.FileDialog(G2frame, 'Choose image mask file', pth, '', 
1250            'image mask files (*.immask)|*.immask',wx.OPEN)
1251        try:
1252            if dlg.ShowModal() == wx.ID_OK:
1253                filename = dlg.GetPath()
1254                File = open(filename,'r')
1255                save = {}
1256                oldThreshold = data['Thresholds'][0]
1257                S = File.readline()
1258                while S:
1259                    if S[0] == '#':
1260                        S = File.readline()
1261                        continue
1262                    [key,val] = S[:-1].split(':')
1263                    if key in ['Points','Rings','Arcs','Polygons','Frames','Thresholds']:
1264                        if ignoreThreshold and key == 'Thresholds':
1265                            S = File.readline() 
1266                            continue
1267                        save[key] = eval(val)
1268                        if key == 'Thresholds':
1269                            save[key][0] = oldThreshold
1270                            save[key][1][1] = min(oldThreshold[1],save[key][1][1])
1271                    S = File.readline()
1272                File.close()
1273                data.update(save)
1274                CleanupMasks(data)
1275                wx.CallAfter(UpdateMasks,G2frame,data)
1276                G2plt.PlotExposedImage(G2frame,event=event)               
1277        finally:
1278            dlg.Destroy()
1279           
1280    def OnNewSpotMask(event):
1281        'Start a new spot mask'
1282        G2frame.MaskKey = 's'
1283        G2plt.OnStartMask(G2frame)
1284       
1285    def OnNewArcMask(event):
1286        'Start a new arc mask'
1287        G2frame.MaskKey = 'a'
1288        G2plt.OnStartMask(G2frame)
1289       
1290    def OnNewRingMask(event):
1291        'Start a new ring mask'
1292        G2frame.MaskKey = 'r'
1293        G2plt.OnStartMask(G2frame)
1294       
1295    def OnNewPolyMask(event):
1296        'Start a new polygon mask'
1297        G2frame.MaskKey = 'p'
1298        G2plt.OnStartMask(G2frame)
1299       
1300    def OnNewFrameMask(event):
1301        'Start a new Frame mask'
1302        G2frame.MaskKey = 'f'
1303        G2plt.OnStartMask(G2frame)
1304
1305    startScroll = None
1306    if G2frame.dataDisplay:
1307        startScroll = G2frame.dataDisplay.GetScrollPos(wx.VERTICAL) # save scroll position
1308        G2frame.dataDisplay.Destroy()
1309    else:
1310        CleanupMasks(data) # posting page for 1st time; clean out anything unfinished
1311    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.MaskMenu)
1312    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyMask, id=G2gd.wxID_MASKCOPY)
1313    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadMask, id=G2gd.wxID_MASKLOAD)
1314    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadMask, id=G2gd.wxID_MASKLOADNOT)
1315    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveMask, id=G2gd.wxID_MASKSAVE)
1316    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewSpotMask, id=G2gd.wxID_NEWMASKSPOT)
1317    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewArcMask, id=G2gd.wxID_NEWMASKARC)
1318    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewRingMask, id=G2gd.wxID_NEWMASKRING)
1319    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewPolyMask, id=G2gd.wxID_NEWMASKPOLY)
1320    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewFrameMask, id=G2gd.wxID_NEWMASKFRAME)
1321    if not G2frame.dataFrame.GetStatusBar():
1322        Status = G2frame.dataFrame.CreateStatusBar()
1323    if G2frame.MaskKey == 'f':
1324        G2frame.dataFrame.GetStatusBar().SetStatusText('Frame mask active - LB pick next point, RB close polygon')
1325    elif G2frame.MaskKey == 'p':
1326        G2frame.dataFrame.GetStatusBar().SetStatusText('Polygon mask active - LB pick next point, RB close polygon')
1327    elif G2frame.MaskKey == 's':
1328        G2frame.dataFrame.GetStatusBar().SetStatusText('Spot mask active - LB pick spot location')
1329    elif G2frame.MaskKey == 'a':
1330        G2frame.dataFrame.GetStatusBar().SetStatusText('Arc mask active - LB pick arc location')
1331    elif G2frame.MaskKey == 'r':
1332        G2frame.dataFrame.GetStatusBar().SetStatusText('Ring mask active - LB pick ring location')
1333    else:
1334        G2frame.dataFrame.GetStatusBar().SetStatusText("To add mask: press a,r,s,p or f on 2D image for arc/ring/spot/polygon/frame")
1335    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
1336    mainSizer = wx.BoxSizer(wx.VERTICAL)
1337    mainSizer.Add((5,10),0)
1338
1339    thresh = data['Thresholds']         #min/max intensity range
1340    Spots = data['Points']               #x,y,radius in mm
1341    Rings = data['Rings']               #radius, thickness
1342    Polygons = data['Polygons']         #3+ x,y pairs
1343    if 'Frames' not in data:
1344        data['Frames'] = []
1345    frame = data['Frames']             #3+ x,y pairs
1346    Arcs = data['Arcs']                 #radius, start/end azimuth, thickness
1347   
1348    littleSizer = wx.FlexGridSizer(0,3,0,5)
1349    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Lower/Upper limits '),0,WACV)
1350    Text = wx.TextCtrl(G2frame.dataDisplay,value=str(thresh[0][0]),style=wx.TE_READONLY)
1351    littleSizer.Add(Text,0,WACV)
1352    Text.SetBackgroundColour(VERY_LIGHT_GREY)
1353    Text = wx.TextCtrl(G2frame.dataDisplay,value=str(thresh[0][1]),style=wx.TE_READONLY)
1354    littleSizer.Add(Text,0,WACV)
1355    Text.SetBackgroundColour(VERY_LIGHT_GREY)
1356    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Lower/Upper thresholds '),0,WACV)
1357    lowerThreshold = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,loc=thresh[1],key=0,
1358                                           min=thresh[0][0],OnLeave=Replot,typeHint=int)
1359    littleSizer.Add(lowerThreshold,0,WACV)
1360    upperThreshold = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,loc=thresh[1],key=1,
1361                                           max=thresh[0][1],OnLeave=Replot,typeHint=int)
1362    littleSizer.Add(upperThreshold,0,WACV)
1363    mainSizer.Add(littleSizer,0,)
1364    if Spots:
1365        lbl = wx.StaticText(parent=G2frame.dataDisplay,label=' Spot masks')
1366        lbl.SetBackgroundColour(wx.Colour(200,200,210))
1367        mainSizer.Add(lbl,0,wx.EXPAND|wx.ALIGN_CENTER,0)
1368        littleSizer = wx.FlexGridSizer(0,3,0,5)
1369        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' position, mm'),0,WACV)
1370        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' diameter, mm'),0,WACV)
1371        littleSizer.Add((5,0),0)
1372        for i in range(len(Spots)):
1373            if Spots[i]:
1374                x,y,d = Spots[i]
1375                spotText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.2f,%.2f" % (x,y)),
1376                    style=wx.TE_READONLY)
1377                spotText.SetBackgroundColour(VERY_LIGHT_GREY)
1378                littleSizer.Add(spotText,0,WACV)
1379                spotText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1380                spotDiameter = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,loc=Spots[i],key=2,
1381                                           max=100.,OnLeave=Replot,nDig=[8,2])
1382                littleSizer.Add(spotDiameter,0,WACV)
1383                spotDelete = G2G.G2LoggedButton(G2frame.dataDisplay,label='delete?',
1384                                            locationcode='Delete+Points+'+str(i),
1385                                            handler=onDeleteMask)
1386                littleSizer.Add(spotDelete,0,WACV)
1387        mainSizer.Add(littleSizer,0,)
1388    if Rings:
1389        lbl = wx.StaticText(parent=G2frame.dataDisplay,label=' Ring masks')
1390        lbl.SetBackgroundColour(wx.Colour(200,200,210))
1391        mainSizer.Add(lbl,0,wx.EXPAND|wx.ALIGN_CENTER,0)
1392        littleSizer = wx.FlexGridSizer(0,3,0,5)
1393        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' 2-theta,deg'),0,WACV)
1394        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' thickness, deg'),0,WACV)
1395        littleSizer.Add((5,0),0)
1396        for i in range(len(Rings)):
1397            if Rings[i]:
1398                ringText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (Rings[i][0])),
1399                    style=wx.TE_READONLY)
1400                ringText.SetBackgroundColour(VERY_LIGHT_GREY)
1401                ringText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1402                littleSizer.Add(ringText,0,WACV)
1403                ringThick = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,loc=Rings[i],key=1,
1404                                           min=0.001,max=1.,OnLeave=Replot,nDig=[8,3])
1405                littleSizer.Add(ringThick,0,WACV)
1406                ringDelete = G2G.G2LoggedButton(G2frame.dataDisplay,label='delete?',
1407                                            locationcode='Delete+Rings+'+str(i),
1408                                            handler=onDeleteMask)
1409                littleSizer.Add(ringDelete,0,WACV)
1410        mainSizer.Add(littleSizer,0,)
1411    if Arcs:
1412        lbl = wx.StaticText(parent=G2frame.dataDisplay,label=' Arc masks')
1413        lbl.SetBackgroundColour(wx.Colour(200,200,210))
1414        mainSizer.Add(lbl,0,wx.EXPAND|wx.ALIGN_CENTER,0)
1415        littleSizer = wx.FlexGridSizer(0,4,0,5)
1416        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' 2-theta,deg'),0,WACV)
1417        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' azimuth, deg'),0,WACV)
1418        littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' thickness, deg'),0,WACV)
1419        littleSizer.Add((5,0),0)
1420        for i in range(len(Arcs)):
1421            if Arcs[i]:
1422                tth,azimuth,thick = Arcs[i]
1423                arcText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.3f" % (tth)),
1424                    style=wx.TE_READONLY)
1425                arcText.SetBackgroundColour(VERY_LIGHT_GREY)
1426                arcText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1427                littleSizer.Add(arcText,0,WACV)
1428                azmText = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%d,%d" % (azimuth[0],azimuth[1])),
1429                    style=wx.TE_READONLY)
1430                azmText.SetBackgroundColour(VERY_LIGHT_GREY)
1431                azmText.Bind(wx.EVT_ENTER_WINDOW,OnTextMsg)
1432                littleSizer.Add(azmText,0,WACV)
1433                arcThick = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,loc=Arcs[i],key=2,
1434                                           min=0.001,max=20.,OnLeave=Replot,nDig=[8,3])
1435                littleSizer.Add(arcThick,0,WACV)
1436                arcDelete = G2G.G2LoggedButton(G2frame.dataDisplay,label='delete?',
1437                                            locationcode='Delete+Arcs+'+str(i),
1438                                            handler=onDeleteMask)
1439                littleSizer.Add(arcDelete,0,WACV)
1440        mainSizer.Add(littleSizer,0,)
1441    if Polygons:
1442        lbl = wx.StaticText(parent=G2frame.dataDisplay,
1443            label=' Polygon masks (on plot RB vertex drag to move,\nLB vertex drag to insert)')
1444        lbl.SetBackgroundColour(wx.Colour(200,200,210))
1445        mainSizer.Add(lbl,0,wx.EXPAND|wx.ALIGN_CENTER,0)
1446        littleSizer = wx.FlexGridSizer(0,2,0,5)
1447        for i in range(len(Polygons)):
1448            if Polygons[i]:
1449                polyList = []
1450                for x,y in Polygons[i]:
1451                    polyList.append("%.2f, %.2f"%(x,y))
1452                polyText = wx.ComboBox(G2frame.dataDisplay,value=polyList[0],choices=polyList,style=wx.CB_READONLY)
1453                littleSizer.Add(polyText,0,WACV)
1454                polyDelete = G2G.G2LoggedButton(G2frame.dataDisplay,label='delete?',
1455                                            locationcode='Delete+Polygons+'+str(i),
1456                                            handler=onDeleteMask)
1457                littleSizer.Add(polyDelete,0,WACV)
1458        mainSizer.Add(littleSizer,0,)
1459    if frame:
1460        lbl = wx.StaticText(parent=G2frame.dataDisplay,
1461            label=' Frame mask (on plot RB vertex drag to move,LB vertex drag to insert)')
1462        lbl.SetBackgroundColour(wx.Colour(200,200,210))
1463        mainSizer.Add(lbl,0,wx.EXPAND|wx.ALIGN_CENTER,0)
1464        littleSizer = wx.FlexGridSizer(0,2,0,5)
1465        frameList = []
1466        for x,y in frame:
1467            frameList.append("%.2f, %.2f"%(x,y))
1468        frameText = wx.ComboBox(G2frame.dataDisplay,value=frameList[0],choices=frameList,style=wx.CB_READONLY)
1469        littleSizer.Add(frameText,0,WACV)
1470        frameDelete = G2G.G2LoggedButton(G2frame.dataDisplay,label='delete?',
1471                                            locationcode='Delete+Frame',
1472                                            handler=onDeleteFrame)
1473        littleSizer.Add(frameDelete,0,WACV)
1474        mainSizer.Add(littleSizer,0,)
1475    mainSizer.Layout()   
1476    G2frame.dataDisplay.SetSizer(mainSizer)
1477    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
1478    G2frame.dataDisplay.SetupScrolling()
1479    Size = mainSizer.Fit(G2frame.dataFrame)
1480    Size[0] += 50 # room for scrollbar & status msg
1481    Size[1] = min(Size[1],500)
1482    G2frame.dataDisplay.SetSize(Size)
1483    G2frame.dataFrame.setSizePosLeft(Size)   
1484    wx.Yield()
1485    if startScroll: # reset scroll to saved position
1486        G2frame.dataDisplay.Scroll(0,startScroll) # set to saved scroll position
1487        wx.Yield()
1488
1489################################################################################
1490##### Stress/Strain
1491################################################################################
1492
1493def UpdateStressStrain(G2frame,data):
1494    '''Shows and handles the controls on the "Stress/Strain"
1495    data tree entry
1496    '''
1497   
1498    def OnAppendDzero(event):
1499        data['d-zero'].append({'Dset':1.0,'Dcalc':0.0,'pixLimit':10,'cutoff':1.0,
1500            'ImxyObs':[[],[]],'ImtaObs':[[],[]],'ImtaCalc':[[],[]],'Emat':[1.0,1.0,1.0]})
1501        UpdateStressStrain(G2frame,data)
1502       
1503    def OnUpdateDzero(event):
1504        for item in data['d-zero']:
1505            if item['Dcalc']:   #skip unrefined ones
1506                item['Dset'] = item['Dcalc']
1507        UpdateStressStrain(G2frame,data)
1508           
1509    def OnCopyStrSta(event):
1510        TextList = [[False,'All IMG',0,0]]
1511#        Names = []
1512        if G2frame.PatternTree.GetCount():
1513            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1514            while id:
1515                name = G2frame.PatternTree.GetItemText(id)
1516#                Names.append(name)
1517                if 'IMG' in name:
1518                    Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Stress/Strain'))
1519                    if id == G2frame.Image:
1520                        Source = name
1521                    else:
1522                        TextList.append([False,name,id,Data.get('Sample load',0.0)])
1523                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1524            if len(TextList) == 1:
1525                G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "IMG" pattern')
1526                return
1527            dlg = G2frame.CopyDialog(G2frame,'Copy stress/strain controls','Copy controls from '+Source+' to:',TextList)
1528            try:
1529                if dlg.ShowModal() == wx.ID_OK:
1530                    result = dlg.GetData()
1531                    if result[0][0]:
1532                        result = TextList[1:]
1533                        for item in result: item[0] = True
1534                    for i,item in enumerate(result):
1535                        ifcopy,name,id,load = item
1536                        if ifcopy:
1537                            Data = copy.deepcopy(data)
1538                            Data['Sample load'] = load
1539                            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'Stress/Strain'),Data)
1540            finally:
1541                dlg.Destroy()
1542
1543    def OnLoadStrSta(event):
1544        pth = G2G.GetImportPath(G2frame)
1545        if not pth: pth = '.'
1546        dlg = wx.FileDialog(G2frame, 'Choose stress/strain file', pth, '', 
1547            'image control files (*.strsta)|*.strsta',wx.OPEN)
1548        try:
1549            if dlg.ShowModal() == wx.ID_OK:
1550                filename = dlg.GetPath()
1551                File = open(filename,'r')
1552                S = File.read()
1553                data = eval(S)
1554                Controls = G2frame.PatternTree.GetItemPyData(
1555                    G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
1556                G2img.FitStrSta(G2frame.ImageZ,data,Controls)
1557                UpdateStressStrain(G2frame,data)
1558                G2plt.PlotExposedImage(G2frame,event=event)
1559                G2plt.PlotStrain(G2frame,data,newPlot=True)
1560                File.close()
1561        finally:
1562            dlg.Destroy()
1563
1564    def OnSaveStrSta(event):
1565        pth = G2G.GetExportPath(G2frame)
1566        dlg = wx.FileDialog(G2frame, 'Choose stress/strain file', pth, '', 
1567            'image control files (*.strsta)|*.strsta',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1568        try:
1569            if dlg.ShowModal() == wx.ID_OK:
1570                filename = dlg.GetPath()
1571                File = open(filename,'w')
1572                save = {}
1573                keys = ['Type','Sample phi','Sample z','Sample load']
1574                keys2 = ['Dset','Dcalc','pixLimit','cutoff','Emat']
1575                File.write('{\n\t')
1576                for key in keys:
1577                    if key in 'Type':
1578                        File.write("'"+key+"':'"+data[key]+"',")
1579                    else:
1580                        File.write("'"+key+"':"+str(data[key])+',')
1581                File.write('\n\t'+"'d-zero':[\n")
1582                for data2 in data['d-zero']:
1583                    File.write('\t\t{')
1584                    for key in keys2:
1585                        File.write("'"+key+"':"+str(data2[key])+',')
1586                    File.write("'ImxyObs':[[],[]],'ImtaObs':[[],[]],'ImtaCalc':[[],[]]},\n")
1587                File.write('\t]\n}')
1588                File.close()
1589        finally:
1590            dlg.Destroy()
1591           
1592    def OnStrStaSample(event):
1593        filename = ''
1594        pth = G2G.GetImportPath(G2frame)
1595        if not pth: pth = '.'
1596        dlg = wx.FileDialog(G2frame, 'Choose multihistogram metadata text file', pth, '', 
1597            'metadata file (*.*)|*.*',wx.OPEN)
1598        try:
1599            if dlg.ShowModal() == wx.ID_OK:
1600                filename = dlg.GetPath()
1601                File = open(filename,'r')
1602                S = File.readline()
1603                newItems = []
1604                itemNames = []
1605                Comments = []
1606                while S:
1607                    if S[0] == '#':
1608                        Comments.append(S)
1609                        S = File.readline()
1610                        continue
1611                    S = S.replace(',',' ').replace('\t',' ')
1612                    Stuff = S[:-1].split()
1613                    itemNames.append(Stuff[0])
1614                    newItems.append(Stuff[1:])
1615                    S = File.readline()               
1616                File.close()
1617        finally:
1618            dlg.Destroy()
1619        if not filename:
1620            G2frame.ErrorDialog('Nothing to do','No file selected')
1621            return
1622        dataDict = dict(zip(itemNames,newItems))
1623        ifany = False
1624        Names = [' ','Sample phi','Sample z','Sample load']
1625        dlg = G2G.G2ColumnIDDialog( G2frame,' Choose multihistogram metadata columns:',
1626            'Select columns',Comments,Names,np.array(newItems).T)
1627        try:
1628            if dlg.ShowModal() == wx.ID_OK:
1629                colNames,newData = dlg.GetSelection()
1630                dataDict = dict(zip(itemNames,newData.T))
1631                for item in colNames:
1632                    if item != ' ':
1633                        ifany = True
1634        finally:
1635            dlg.Destroy()
1636        if not ifany:
1637            G2frame.ErrorDialog('Nothing to do','No columns identified')
1638            return
1639        histList = []
1640        item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)       
1641        while item:
1642            name = G2frame.PatternTree.GetItemText(item)
1643            if name.startswith('IMG'):
1644                histList.append(name)
1645            item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1646        colIds = {}
1647        for i,name in enumerate(colNames):
1648            if name != ' ':
1649                colIds[name] = i
1650        for hist in histList:
1651            name = hist.split()[1]  #this is file name
1652            if name in dataDict:
1653                newItems = {}
1654                for item in colIds:
1655                    newItems[item] = float(dataDict[name][colIds[item]])
1656                Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,hist)
1657                stsrData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Stress/Strain'))
1658                stsrData.update(newItems)       
1659        UpdateStressStrain(G2frame,data)       
1660   
1661    def OnFitStrSta(event):
1662        Controls = G2frame.PatternTree.GetItemPyData(
1663            G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
1664        G2img.FitStrSta(G2frame.ImageZ,data,Controls)
1665        print 'Strain fitting finished'
1666        UpdateStressStrain(G2frame,data)
1667        G2plt.PlotExposedImage(G2frame,event=event)
1668        G2plt.PlotStrain(G2frame,data,newPlot=True)
1669       
1670    def OnFitAllStrSta(event):
1671        TextList = [[False,'All IMG',0]]
1672#        Names = []
1673        if G2frame.PatternTree.GetCount():
1674            choices = G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
1675            if len(choices) == 1:
1676                G2frame.ErrorDialog('Nothing to fit','There must some "IMG" patterns')
1677                return
1678            sel = []
1679            dlg = G2G.G2MultiChoiceDialog(G2frame,'Stress/Strain fitting','Select images to fit:',choices)
1680            dlg.SetSelections(sel)
1681            names = []
1682            if dlg.ShowModal() == wx.ID_OK:
1683                for sel in dlg.GetSelections():
1684                    names.append(choices[sel])
1685            dlg.Destroy()
1686            SeqResult = {}
1687            dlg = wx.ProgressDialog('Sequential IMG Strain fit','Data set name = '+names[0],len(names), 
1688                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)         
1689            wx.BeginBusyCursor()
1690            goodnames = []
1691            try:
1692                for i,name in enumerate(names):
1693                    print ' Sequential strain fit for ',name
1694                    GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
1695                    if not GoOn:
1696                        break
1697                    Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
1698                    Controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Image Controls'))
1699                    StaCtrls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Stress/Strain'))
1700                    if not len(StaCtrls['d-zero']):
1701                        continue
1702                    goodnames.append(name)
1703                    id = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, name)
1704                    Npix,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(Id)
1705                    image = G2IO.GetImageData(G2frame,imagefile,True,ImageTag=imagetag)
1706                    dark = Controls['dark image']
1707                    if dark[0]:
1708                        id = G2gd.GetPatternTreeItemId(G2frame, G2frame.root,dark[0])
1709                        Npix,darkfile,imagetag = G2frame.PatternTree.GetImageLoc(id)
1710                        darkImg = G2IO.GetImageData(G2frame,darkfile,True,ImageTag=imagetag)
1711                        image += dark[1]*darkImg
1712                    G2img.FitStrSta(image,StaCtrls,Controls)
1713                    G2plt.PlotStrain(G2frame,StaCtrls,newPlot=True)
1714                    parmDict = {'Sample load':StaCtrls['Sample load'],}
1715                    varyNames = ['e11','e12','e22']
1716                    sig = []
1717                    varyList = []
1718                    variables = []
1719                    for i,item in enumerate(StaCtrls['d-zero']):
1720                        variables += item['Emat']
1721                        sig += item['Esig']
1722                        varylist = ['%d%s%s'%(i,';',Name) for Name in varyNames]
1723                        varyList += varylist
1724                        parmDict.update(dict(zip(varylist,item['Emat'])))
1725                        parmDict['%d:Dcalc'%(i)] = item['Dcalc']
1726                    SeqResult[name] = {'variables':variables,'varyList':varyList,'sig':sig,'Rvals':[],
1727                        'covMatrix':np.eye(len(variables)),'title':name,'parmDict':parmDict}
1728                else:
1729                    SeqResult['histNames'] = goodnames
1730                    dlg.Destroy()
1731                    print ' ***** Sequential strain refinement successful *****'
1732            finally:
1733                wx.EndBusyCursor()   
1734            Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
1735            if Id:
1736                G2frame.PatternTree.SetItemPyData(Id,SeqResult)
1737            else:
1738                Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
1739                G2frame.PatternTree.SetItemPyData(Id,SeqResult)
1740            G2frame.PatternTree.SelectItem(Id)
1741            print 'All images fitted'
1742       
1743    def SamSizer():
1744       
1745        def OnStrainType(event):
1746            data['Type'] = strType.GetValue()
1747       
1748        def OnSamPhi(event):
1749            try:
1750                value = float(samPhi.GetValue())
1751            except ValueError:
1752                value = data['Sample phi']
1753            data['Sample phi'] = value
1754            samPhi.SetValue("%.3f" % (data['Sample phi']))
1755               
1756        def OnSamZ(event):
1757            try:
1758                value = float(samZ.GetValue())
1759            except ValueError:
1760                value = data['Sample z']
1761            data['Sample z'] = value
1762            samZ.SetValue("%.3f" % (data['Sample z']))
1763               
1764        def OnSamLoad(event):
1765            try:
1766                value = float(samLoad.GetValue())
1767            except ValueError:
1768                value = data['Sample load']
1769            data['Sample load'] = value
1770            samLoad.SetValue("%.3f" % (data['Sample load']))
1771               
1772        samSizer = wx.BoxSizer(wx.HORIZONTAL)
1773        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Strain type: '),0,WACV)
1774        strType = wx.ComboBox(G2frame.dataDisplay,value=data['Type'],choices=['True','Conventional'],
1775            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1776        strType.SetValue(data['Type'])
1777        strType.Bind(wx.EVT_COMBOBOX, OnStrainType)
1778        samSizer.Add(strType,0,WACV)
1779       
1780        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Sample phi: '),0,WACV)
1781        samPhi = wx.TextCtrl(G2frame.dataDisplay,-1,value=("%.3f" % (data['Sample phi'])),
1782            style=wx.TE_PROCESS_ENTER)
1783        samSizer.Add(samPhi,0,WACV)
1784        samPhi.Bind(wx.EVT_TEXT_ENTER,OnSamPhi)
1785        samPhi.Bind(wx.EVT_KILL_FOCUS,OnSamPhi)
1786        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Sample delta-z(mm): '),0,WACV)
1787        samZ = wx.TextCtrl(G2frame.dataDisplay,-1,value=("%.3f" % (data['Sample z'])),
1788            style=wx.TE_PROCESS_ENTER)
1789        samSizer.Add(samZ,0,WACV)
1790        samZ.Bind(wx.EVT_TEXT_ENTER,OnSamZ)
1791        samZ.Bind(wx.EVT_KILL_FOCUS,OnSamZ)
1792        samSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=' Sample load(MPa): '),0,WACV)
1793        samLoad = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,data,'Sample load',
1794                nDig=[8,3],typeHint=float,)
1795        samSizer.Add(samLoad,0,WACV)
1796
1797        return samSizer
1798       
1799    def DzeroSizer():
1800   
1801        def OnDzero(event):
1802            Obj = event.GetEventObject()
1803            try:
1804                value = min(20.0,max(0.25,float(Obj.GetValue())))
1805            except ValueError:
1806                value = 1.0
1807            Obj.SetValue("%.5f"%(value))
1808            data['d-zero'][Indx[Obj.GetId()]]['Dset'] = value
1809            data['d-zero'] = G2mth.sortArray(data['d-zero'],'Dset',reverse=True)
1810            Ring,R = G2img.MakeStrStaRing(data['d-zero'][Indx[Obj.GetId()]],G2frame.ImageZ,Controls)
1811            if len(Ring):
1812                data['d-zero'][Indx[Obj.GetId()]].update(R)
1813            else:
1814                G2frame.ErrorDialog('Strain peak selection','WARNING - No points found for this ring selection')
1815               
1816            UpdateStressStrain(G2frame,data)
1817            G2plt.PlotExposedImage(G2frame,event=event,newPlot=False)
1818            G2plt.PlotStrain(G2frame,data,newPlot=True)
1819           
1820        def OnDeleteDzero(event):
1821            Obj = event.GetEventObject()
1822            del(data['d-zero'][delIndx.index(Obj)])
1823            UpdateStressStrain(G2frame,data)
1824            G2plt.PlotExposedImage(G2frame,event=event,newPlot=True)
1825            G2plt.PlotStrain(G2frame,data,newPlot=True)
1826       
1827        def OnCutOff(event):
1828            Obj = event.GetEventObject()
1829            try:
1830                value = min(10.0,max(0.5,float(Obj.GetValue())))
1831            except ValueError:
1832                value = 1.0
1833            Obj.SetValue("%.1f"%(value))
1834            data['d-zero'][Indx[Obj.GetId()]]['cutoff'] = value
1835            Ring,R = G2img.MakeStrStaRing(data['d-zero'][Indx[Obj.GetId()]],G2frame.ImageZ,Controls)
1836            G2plt.PlotExposedImage(G2frame,event=event)
1837            G2plt.PlotStrain(G2frame,data,newPlot=True)
1838       
1839        def OnPixLimit(event):
1840            Obj = event.GetEventObject()
1841            data['d-zero'][Indx[Obj.GetId()]]['pixLimit'] = int(Obj.GetValue())
1842            Ring,R = G2img.MakeStrStaRing(data['d-zero'][Indx[Obj.GetId()]],G2frame.ImageZ,Controls)
1843            G2plt.PlotExposedImage(G2frame,event=event)
1844            G2plt.PlotStrain(G2frame,data,newPlot=True)
1845           
1846        Indx = {}
1847        delIndx = []   
1848        dzeroSizer = wx.FlexGridSizer(0,8,5,5)
1849        for id,dzero in enumerate(data['d-zero']):
1850            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=(' d-zero #%d: '%(id))),0,WACV)
1851            dZero = wx.TextCtrl(G2frame.dataDisplay,-1,value=('%.5f'%(dzero['Dset'])),
1852                style=wx.TE_PROCESS_ENTER)
1853            dzeroSizer.Add(dZero,0,WACV)
1854            dZero.Bind(wx.EVT_TEXT_ENTER,OnDzero)
1855            dZero.Bind(wx.EVT_KILL_FOCUS,OnDzero)
1856            Indx[dZero.GetId()] = id
1857            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=(' d-zero ave: %.5f'%(dzero['Dcalc']))),0,WACV)
1858               
1859            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min ring I/Ib '),0,WACV)
1860            cutOff = wx.TextCtrl(parent=G2frame.dataDisplay,value=("%.1f" % (dzero['cutoff'])),
1861                style=wx.TE_PROCESS_ENTER)
1862            cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)
1863            cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
1864            Indx[cutOff.GetId()] = id
1865            dzeroSizer.Add(cutOff,0,WACV)
1866       
1867            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Pixel search range '),0,WACV)
1868            pixLimit = wx.ComboBox(parent=G2frame.dataDisplay,value=str(dzero['pixLimit']),choices=['1','2','5','10','15','20'],
1869                style=wx.CB_READONLY|wx.CB_DROPDOWN)
1870            pixLimit.Bind(wx.EVT_COMBOBOX, OnPixLimit)
1871            Indx[pixLimit.GetId()] = id
1872            dzeroSizer.Add(pixLimit,0,WACV)               
1873               
1874            dzeroDelete = wx.CheckBox(parent=G2frame.dataDisplay,label='delete?')
1875            dzeroDelete.Bind(wx.EVT_CHECKBOX,OnDeleteDzero)
1876            delIndx.append(dzeroDelete)
1877            dzeroSizer.Add(dzeroDelete,0,WACV)
1878           
1879            dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=(' Strain tensor:')),WACV)
1880            names = ['e11','e12','e22']
1881            for i in range(3):
1882                dzeroSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=names[i]),0,WACV)
1883                tensorElem = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2f'%(dzero['Emat'][i]),style=wx.TE_READONLY)
1884                tensorElem.SetBackgroundColour(VERY_LIGHT_GREY)
1885                dzeroSizer.Add(tensorElem,0,WACV)
1886            dzeroSizer.Add((5,5),0)             
1887        return dzeroSizer
1888       
1889# patches
1890    if 'Sample load' not in data:
1891        data['Sample load'] = 0.0
1892# end patches
1893   
1894    if G2frame.dataDisplay:
1895        G2frame.dataDisplay.Destroy()
1896    Controls = G2frame.PatternTree.GetItemPyData(
1897        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))       
1898    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.StrStaMenu)
1899    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAppendDzero, id=G2gd.wxID_APPENDDZERO)
1900    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUpdateDzero, id=G2gd.wxID_UPDATEDZERO)
1901    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitStrSta, id=G2gd.wxID_STRSTAFIT)
1902    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitAllStrSta, id=G2gd.wxID_STRSTAALLFIT)
1903    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyStrSta, id=G2gd.wxID_STRSTACOPY)
1904    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadStrSta, id=G2gd.wxID_STRSTALOAD)
1905    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveStrSta, id=G2gd.wxID_STRSTASAVE)
1906    G2frame.dataFrame.Bind(wx.EVT_MENU, OnStrStaSample, id=G2gd.wxID_STRSTSAMPLE)       
1907    if not G2frame.dataFrame.GetStatusBar():
1908        Status = G2frame.dataFrame.CreateStatusBar()
1909    if G2frame.StrainKey == 'a':    #probably doesn't happen
1910        G2frame.dataFrame.GetStatusBar().SetStatusText('Add strain ring active - LB pick d-zero value')
1911    else:
1912        G2frame.dataFrame.GetStatusBar().SetStatusText("To add strain data: On 2D Powder Image, key a:add ring")
1913       
1914    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
1915    mainSizer = wx.BoxSizer(wx.VERTICAL)
1916    mainSizer.Add((5,10),0)
1917    mainSizer.Add(SamSizer())
1918    mainSizer.Add((5,10),0)
1919    mainSizer.Add(DzeroSizer())
1920   
1921    mainSizer.Layout()   
1922    G2frame.dataDisplay.SetSizer(mainSizer)
1923    G2frame.dataDisplay.SetAutoLayout(1)
1924    G2frame.dataDisplay.SetupScrolling()
1925    Size = mainSizer.Fit(G2frame.dataFrame)
1926    Size[0] += 25
1927    G2frame.dataDisplay.SetSize(Size)
1928    G2frame.dataFrame.setSizePosLeft(Size)   
1929
1930###########################################################################
1931# Autointegration follows
1932def ReadMask(filename):
1933    'Read a mask (.immask) file'
1934    File = open(filename,'r')
1935    save = {}
1936    S = File.readline()
1937    while S:
1938        if S[0] == '#':
1939            S = File.readline()
1940            continue
1941        [key,val] = S[:-1].split(':')
1942        if key in ['Points','Rings','Arcs','Polygons','Frames','Thresholds']:
1943            save[key] = eval(val)
1944        S = File.readline()
1945    File.close()
1946    CleanupMasks(save)
1947    return save
1948
1949def ReadControls(filename):
1950    'read an image controls (.imctrl) file'
1951    cntlList = ['wavelength','distance','tilt','invert_x','invert_y','type',
1952            'fullIntegrate','outChannels','outAzimuths','LRazimuth','IOtth','azmthOff','DetDepth',
1953            'calibskip','pixLimit','cutoff','calibdmin','chisq','Flat Bkg',
1954            'PolaVal','SampleAbs','dark image','background image']
1955    File = open(filename,'r')
1956    save = {}
1957    S = File.readline()
1958    while S:
1959        if S[0] == '#':
1960            S = File.readline()
1961            continue
1962        [key,val] = S[:-1].split(':')
1963        if key in ['type','calibrant','binType','SampleShape',]:    #strings
1964            save[key] = val
1965        elif key in ['rotation']:
1966            save[key] = float(val)
1967        elif key in ['center',]:
1968            if ',' in val:
1969                save[key] = eval(val)
1970            else:
1971                vals = val.strip('[] ').split()
1972                save[key] = [float(vals[0]),float(vals[1])] 
1973        elif key in cntlList:
1974            save[key] = eval(val)
1975        S = File.readline()
1976    File.close()
1977    return save
1978
1979def Read_imctrl(imctrl_file):
1980    '''Read an image control file and record control parms into a dict, with some simple
1981    type conversions
1982    '''
1983    file_opt = options = {}
1984    save = {'filename':imctrl_file}
1985    immask_file = os.path.splitext(imctrl_file)[0]+'.immask'
1986    if os.path.exists(immask_file):
1987        save['maskfile'] = immask_file
1988    else:
1989        save['maskfile'] = '(none)'
1990    cntlList = ['wavelength','distance','tilt','invert_x','invert_y','type',
1991                        'fullIntegrate','outChannels','outAzimuths','LRazimuth','IOtth','azmthOff','DetDepth',
1992                        'calibskip','pixLimit','cutoff','calibdmin','chisq','Flat Bkg',
1993                        'PolaVal','SampleAbs','dark image','background image']
1994    File = open(imctrl_file,'r')
1995    fullIntegrate = False
1996    try:
1997        S = File.readline()
1998        while S:
1999            if S[0] == '#':
2000                S = File.readline()
2001                continue
2002            [key,val] = S[:-1].split(':')
2003            if key in ['type','calibrant','binType','SampleShape',]:    #strings
2004                save[key] = val
2005            elif key == 'rotation':
2006                save[key] = float(val)
2007            elif key == 'fullIntegrate':
2008                fullIntegrate = eval(val)
2009            elif key == 'LRazimuth':
2010                save['LRazimuth_min'],save['LRazimuth_max'] = eval(val)[0:2]
2011            elif key == 'IOtth':
2012                save['IOtth_min'],save['IOtth_max'] = eval(val)[0:2]
2013            elif key == 'center':
2014                if ',' in val:
2015                    vals = eval(val)
2016                else:
2017                    vals = val.strip('[] ').split()
2018                    vals = [float(vals[0]),float(vals[1])] 
2019                save['center_x'],save['center_y'] = vals[0:2]
2020            elif key in cntlList:
2021                save[key] = eval(val)
2022            S = File.readline()
2023    finally:
2024        File.close()
2025        if fullIntegrate: save['LRazimuth_min'],save['LRazimuth_max'] = 0,0
2026    return save
2027   
2028class AutoIntFrame(wx.Frame):
2029    '''Creates a wx.Frame window for the Image AutoIntegration.
2030    The intent is that this will be used as a non-modal dialog window.
2031   
2032    Implements a Start button that morphs into a pause and resume button.
2033    This button starts a processing loop that is repeated every
2034    :meth:`PollTime` seconds.
2035
2036    :param wx.Frame G2frame: main GSAS-II frame
2037    :param float PollTime: frequency in seconds to repeat calling the
2038      processing loop. (Default is 3.0 seconds.)
2039    '''
2040
2041    def __init__(self,G2frame,PollTime=60.0):
2042        def OnStart(event):
2043            '''Called when the start button is pressed. Changes button label
2044            to Pause. When Pause is pressed the label changes to Resume.
2045            When either Start or Resume is pressed, the processing loop
2046            is started. When Pause is pressed, the loop is stopped.
2047            '''
2048            # check inputs for errors before starting
2049            #err = ''
2050            #if not any([self.params[fmt] for fmt in self.fmtlist]):
2051            #    err += '\nPlease select at least one output format\n'
2052            #if err:
2053            #    G2G.G2MessageBox(self,err)
2054            #    return
2055            self.Pause = False
2056            # change button label
2057            if btnstart.GetLabel() != 'Pause':
2058                btnstart.SetLabel('Pause')
2059                if self.timer.IsRunning(): self.timer.Stop()
2060                self.PreventReEntryTimer = False
2061                self.StartLoop()
2062                self.OnTimerLoop(None) # run once immediately and again after delay
2063                self.timer.Start(int(1000*PollTime),oneShot=False)
2064                self.Status.SetStatusText('Press Pause to delay integration or Reset to prepare to reintegrate all images')
2065            else:
2066                btnstart.SetLabel('Resume')
2067                if self.timer.IsRunning(): self.timer.Stop()
2068                print('\nPausing autointegration\n')
2069                self.Status.SetStatusText('Press Resume to continue integration or Reset to prepare to reintegrate all images')
2070                self.Pause = True
2071
2072        def OnReset(event):
2073            '''Called when Reset button is pressed. This stops the
2074            processing loop and resets the list of integrated files so
2075            all images can be reintegrated.
2076            '''
2077            btnstart.SetLabel('Restart')
2078            self.Status.SetStatusText('Press Restart to reload and re-integrate images matching filter')
2079            if self.timer.IsRunning(): self.timer.Stop()
2080            self.Reset = True
2081            self.Pause = True
2082           
2083        def OnQuit(event):
2084            '''Stop the processing loop and close the Frame
2085            '''
2086            if self.timer.IsRunning(): self.timer.Stop() # make sure we stop first
2087            wx.CallAfter(self.Destroy)
2088           
2089        def OnBrowse(event):
2090            '''Responds when the Browse button is pressed to load a file.
2091            The routine determines which button was pressed and gets the
2092            appropriate file type and loads it into the appropriate place
2093            in the dict.
2094            '''
2095            if btn3 == event.GetEventObject():
2096                dlg = wx.DirDialog(
2097                    self, 'Select directory for output files',
2098                    self.params['outdir'],wx.DD_DEFAULT_STYLE)
2099                dlg.CenterOnParent()
2100                try:
2101                    if dlg.ShowModal() == wx.ID_OK:
2102                        self.params['outdir'] = dlg.GetPath()
2103                        fInp3.SetValue(self.params['outdir'])
2104                finally:
2105                    dlg.Destroy()
2106                return
2107               
2108        def OnRadioSelect(event):
2109            '''Respond to a radiobutton selection and when in table
2110            mode, get distance-dependent parameters from user.
2111            '''
2112            self.Evaluator = None
2113            if r2.GetValue():
2114                try:
2115                    dlg = IntegParmTable(self.G2frame) # create the dialog
2116                    dlg.CenterOnParent()
2117                    if dlg.ShowModal() == wx.ID_OK:
2118                        self.ImgTblParms = dlg.parms
2119                        self.IMfileList = dlg.IMfileList
2120                        self.Evaluator = DefineEvaluator(dlg)
2121                        self.params['Mode'] = 'table'
2122                        r2E.Enable(True)
2123                    else:
2124                        self.useActive.SetValue(True)
2125                finally:
2126                    dlg.Destroy()
2127            if self.useActive.GetValue():
2128                self.params['Mode'] = 'active'
2129                self.imageBase = G2frame.Image
2130                self.useActive.SetLabel("Active Image: "+
2131                        G2frame.PatternTree.GetItemText(self.imageBase))
2132                r2E.Enable(False)
2133
2134        def OnEditTable(event):
2135            '''Called to edit the distance-dependent parameter look-up table.
2136            Should be called only when table is defined and active.
2137            '''
2138            try:
2139                dlg = IntegParmTable(self.G2frame,self.ImgTblParms,self.IMfileList)
2140                dlg.CenterOnParent()
2141                if dlg.ShowModal() == wx.ID_OK:
2142                    self.ImgTblParms = dlg.parms
2143                    self.IMfileList = dlg.IMfileList
2144                    self.Evaluator = DefineEvaluator(dlg)
2145                    self.params['Mode'] = 'table'
2146                    r2E.Enable(True)
2147                else:
2148                    self.useActive.SetValue(True)
2149                    self.params['Mode'] = 'active'
2150                    self.imageBase = G2frame.Image
2151                    self.useActive.SetLabel("Active Image: "+
2152                            G2frame.PatternTree.GetItemText(self.imageBase))
2153                    r2E.Enable(False)
2154            finally:
2155                dlg.Destroy()
2156
2157        ##################################################
2158        # beginning of __init__ processing
2159        ##################################################
2160        self.G2frame = G2frame
2161        self.ImgTblParms = None
2162        self.IMfileList = None
2163        self.Evaluator = None
2164        self.params = {}
2165        self.Reset = False
2166        self.Pause = False
2167        self.PreventReEntryShowMatch = False
2168        self.PreventReEntryTimer = False
2169        self.params['IMGfile'] = ''
2170        self.params['MaskFile'] = ''
2171        self.params['IgnoreMask'] = True
2172        self.fmtlist = G2IO.ExportPowderList(G2frame)
2173        self.timer = wx.Timer()
2174        self.timer.Bind(wx.EVT_TIMER,self.OnTimerLoop)
2175        self.imageBase = G2frame.Image
2176
2177        controlsId = G2frame.PatternTree.GetSelection()
2178        size,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(self.imageBase)       
2179        self.imagedir,fileroot = os.path.split(imagefile)
2180        self.params['filter'] = '*'+os.path.splitext(fileroot)[1]
2181        self.params['outdir'] = os.path.abspath(self.imagedir)
2182        wx.Frame.__init__(self, G2frame, title='Automatic Integration',
2183                          style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
2184        self.Status = self.CreateStatusBar()
2185        self.Status.SetStatusText('Press Start to load and integrate images matching filter')
2186        mnpnl = wx.Panel(self)
2187        mnsizer = wx.BoxSizer(wx.VERTICAL)
2188        # box for integration controls & masks input
2189        lbl = wx.StaticBox(mnpnl, wx.ID_ANY, "Integration Control")
2190        lblsizr = wx.StaticBoxSizer(lbl, wx.VERTICAL)
2191        lblsizr.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Use integration parameters from:'))
2192        self.useActive = wx.RadioButton(mnpnl, wx.ID_ANY, 
2193                            style = wx.RB_GROUP)
2194        self.useActive.Bind(wx.EVT_RADIOBUTTON, OnRadioSelect)
2195        self.useActive.SetLabel("Active Image: "+
2196                                G2frame.PatternTree.GetItemText(self.imageBase))
2197        lblsizr.Add(self.useActive,1,wx.EXPAND,1)
2198        self.useActive.SetValue(True)
2199        minisizer = wx.BoxSizer(wx.HORIZONTAL)
2200        r2 = wx.RadioButton(mnpnl, wx.ID_ANY, "From distance look-up table")
2201        minisizer.Add(r2,0,wx.ALIGN_LEFT|wx.ALL,1)
2202        r2.Bind(wx.EVT_RADIOBUTTON, OnRadioSelect)
2203        r2E = wx.Button(mnpnl,  wx.ID_ANY, "Edit table")
2204        minisizer.Add(r2E,0,wx.ALIGN_LEFT,10)
2205        r2E.Enable(False)
2206        r2E.Bind(wx.EVT_BUTTON, OnEditTable)
2207        # bind button and deactivate be default
2208        lblsizr.Add(minisizer)
2209        mnsizer.Add(lblsizr,1,wx.EXPAND,1)
2210
2211        # file filter stuff
2212        sizer = wx.BoxSizer(wx.HORIZONTAL)
2213        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Image filter'))
2214        flterInp = G2G.ValidatedTxtCtrl(mnpnl,self.params,'filter',
2215                                        OnLeave=self.ShowMatchingFiles)
2216        sizer.Add(flterInp)
2217        mnsizer.Add(sizer,0,wx.ALIGN_RIGHT,1)
2218        self.ListBox = wx.ListBox(mnpnl,size=(-1,100))
2219        mnsizer.Add(self.ListBox,0,wx.EXPAND,1)
2220        self.ShowMatchingFiles(self.params['filter'])
2221        # box for output selections
2222        lbl = wx.StaticBox(mnpnl, wx.ID_ANY, "Output settings")
2223        lblsizr = wx.StaticBoxSizer(lbl, wx.VERTICAL)
2224        sizer = wx.BoxSizer(wx.HORIZONTAL)
2225        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Write to: '))
2226        fInp3 = G2G.ValidatedTxtCtrl(mnpnl,self.params,'outdir',
2227                                       notBlank=False,size=(300,-1))
2228        sizer.Add(fInp3)
2229        btn3 = wx.Button(mnpnl,  wx.ID_ANY, "Browse")
2230        btn3.Bind(wx.EVT_BUTTON, OnBrowse)
2231        sizer.Add(btn3)
2232        lblsizr.Add(sizer)
2233        #lblsizr.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Select format(s): '))
2234        sizer = wx.BoxSizer(wx.HORIZONTAL)
2235        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Select format(s): '))
2236        for dfmt in self.fmtlist:
2237            fmt = dfmt[1:]
2238            self.params[fmt] = False
2239            btn = G2G.G2CheckBox(mnpnl,dfmt,self.params,fmt)
2240            sizer.Add(btn)
2241        lblsizr.Add(sizer)
2242        sizer = wx.BoxSizer(wx.HORIZONTAL)
2243        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Separate dir for each format: '))
2244        self.params['SeparateDir'] = False
2245        sizer.Add(G2G.G2CheckBox(mnpnl,'',self.params,'SeparateDir'))
2246        lblsizr.Add(sizer)
2247        mnsizer.Add(lblsizr,0,wx.ALIGN_CENTER,1)
2248
2249        # buttons on bottom
2250        mnsizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'AutoIntegration controls'),0,wx.TOP,5)
2251        sizer = wx.BoxSizer(wx.HORIZONTAL)
2252        sizer.Add((20,-1))
2253        btnstart = wx.Button(mnpnl,  wx.ID_ANY, "Start")
2254        btnstart.Bind(wx.EVT_BUTTON, OnStart)
2255        sizer.Add(btnstart)
2256        btnstop = wx.Button(mnpnl,  wx.ID_ANY, "Reset")
2257        btnstop.Bind(wx.EVT_BUTTON, OnReset)
2258        sizer.Add(btnstop)
2259        sizer.Add((20,-1),wx.EXPAND,1)
2260        btnquit = wx.Button(mnpnl,  wx.ID_ANY, "Close")
2261        btnquit.Bind(wx.EVT_BUTTON, OnQuit)
2262        sizer.Add(btnquit)
2263        sizer.Add((20,-1))
2264        mnsizer.Add(sizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP,5)
2265       
2266        # finish up window
2267        mnpnl.SetSizer(mnsizer)
2268        OnRadioSelect(None) # disable widgets
2269        mnsizer.Fit(self)
2270        self.CenterOnParent()
2271        self.Show()
2272
2273    def ShowMatchingFiles(self,value,invalid=False,**kwargs):
2274        G2frame = self.G2frame
2275        if invalid: return
2276        msg = ''
2277        if self.PreventReEntryShowMatch: return
2278        self.PreventReEntryShowMatch = True
2279        imageFileList = []
2280        for img in G2gd.GetPatternTreeDataNames(G2frame,['IMG ']):
2281            imgId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,img)
2282            size,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(imgId)
2283            if imagefile not in imageFileList: imageFileList.append(imagefile)
2284            if img not in G2frame.IntegratedList:
2285                if msg: msg += '\n'
2286                msg += '  ' + img
2287        if msg: msg = "Loaded images to integrate:\n" + msg + "\n"
2288        msg1 = ""
2289        try:
2290            imageList = sorted(
2291                glob.glob(os.path.join(self.imagedir,value)))
2292            if not imageList:
2293                msg1 = 'Warning: No files match search string '+os.path.join(self.imagedir,value)
2294            else:
2295                for fil in imageList:
2296                    if fil not in imageFileList: msg1 += '\n  '+fil
2297                if msg1:
2298                    msg += 'Files to integrate from '+os.path.join(self.imagedir,value)+msg1
2299                else:
2300                    msg += 'All files integrated'
2301        except IndexError:
2302            msg += 'Error searching for files named '+os.path.join(self.imagedir,value)
2303        self.ListBox.Clear()
2304        self.ListBox.AppendItems(msg.split('\n'))
2305        self.PreventReEntryShowMatch = False
2306        return
2307       
2308    def IntegrateImage(self,img):
2309        '''Integrates a single image'''
2310        G2frame = self.G2frame
2311        imgId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,img)
2312        G2frame.Image = imgId
2313        G2frame.PickId = G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls')
2314        # do integration
2315        size,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(imgId)
2316#        G2frame.ImageZ = G2IO.GetImageData(G2frame,imagefile,True,imagetag)     #pointless since done in OnIntegrate?
2317        masks = G2frame.PatternTree.GetItemPyData(
2318                G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
2319        data = G2frame.PatternTree.GetItemPyData(G2frame.PickId)
2320        # simulate a Image Controls press, since that is where the
2321        # integration is hidden
2322        UpdateImageControls(G2frame,data,masks,IntegrateOnly=True)
2323        G2frame.IntegratedList.append(img) # note this as integrated
2324        # split name and control number
2325        s = re.split(r'(\d+)\Z',os.path.split(os.path.splitext(imagefile)[0])[1])
2326        namepre = s[0]
2327        if len(s) > 1:
2328            namenum = s[1]
2329        else:
2330            namenum = ''
2331        for Id in G2frame.IntgOutList: # loop over newly created PDWR entry(ies)
2332            # save the created PWDR tree names so that a reset can delete them
2333            G2frame.Image = Id
2334            treename = G2frame.PatternTree.GetItemText(Id)
2335            G2frame.AutointPWDRnames.append(treename)
2336            # write out the images in the selected formats
2337            Sdata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
2338            # determine the name for the current file
2339            fileroot = namepre
2340            if len(G2frame.IntgOutList) > 1:
2341                fileroot += "_AZM"
2342                if 'Azimuth' in Sdata:
2343                    fileroot += str(int(10*Sdata['Azimuth']))
2344                fileroot += "_" 
2345            fileroot += namenum
2346            # loop over selected formats
2347            for dfmt in self.fmtlist:
2348                if not self.params[dfmt[1:]]: continue
2349                if self.params['SeparateDir']:
2350                    subdir = dfmt[1:]
2351                else:
2352                    subdir = ''
2353                fil = os.path.join(self.params['outdir'],subdir,fileroot)
2354                print('writing file '+fil+dfmt)
2355                G2IO.ExportPowder(G2frame,treename,fil,dfmt)
2356               
2357    def ResetFromTable(self,dist):
2358        '''Sets integration parameters based on values from
2359        the lookup table
2360        '''
2361        #dist = self.controlsDict['distance']
2362        interpDict,imgctrl,immask = self.Evaluator(dist) # interpolated calibration values
2363        #if GSASIIpath.GetConfigValue('debug'):
2364        if GSASIIpath.GetConfigValue('debug'):
2365            print 'interpolated values: ',interpDict
2366        self.ImageControls = ReadControls(imgctrl)
2367        self.ImageControls.update(interpDict)
2368        self.ImageControls['showLines'] = True
2369        self.ImageControls['ring'] = []
2370        self.ImageControls['rings'] = []
2371        self.ImageControls['ellipses'] = []
2372        self.ImageControls['setDefault'] = False
2373        for i in 'range','size','GonioAngles':
2374            if i in self.ImageControls:
2375                del self.ImageControls[i]
2376        # load copy of Image Masks
2377        if immask:
2378            self.ImageMasks = ReadMask(immask)
2379            if list(self.ImageMasks['Thresholds'][0]) == self.ImageMasks['Thresholds'][1]:     #avoid copy of unchanged thresholds
2380                del self.ImageMasks['Thresholds']
2381        else:
2382            self.ImageMasks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Frames':[]}
2383       
2384    def StartLoop(self):
2385        '''Save current Image params for use in future integrations
2386        also label the window so users understand what is being used
2387        '''
2388        print '\nStarting new autointegration\n'
2389        G2frame = self.G2frame
2390        # show current IMG base
2391        if self.params['Mode'] != 'table':
2392            self.useActive.SetLabel("Active Image: "+
2393                                    G2frame.PatternTree.GetItemText(self.imageBase))
2394            # load copy of Image Controls from current image and clean up
2395            # items that should not be copied
2396            self.ImageControls = copy.deepcopy(
2397                G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(
2398                    G2frame,self.imageBase, 'Image Controls')))
2399            self.ImageControls['showLines'] = True
2400            self.ImageControls['ring'] = []
2401            self.ImageControls['rings'] = []
2402            self.ImageControls['ellipses'] = []
2403            self.ImageControls['setDefault'] = False
2404            del self.ImageControls['range']
2405            del self.ImageControls['size']
2406            del self.ImageControls['GonioAngles']
2407            # load copy of Image Masks, keep thresholds
2408            self.ImageMasks = copy.deepcopy(
2409                G2frame.PatternTree.GetItemPyData(
2410                    G2gd.GetPatternTreeItemId(G2frame,self.imageBase, 'Masks')))
2411            self.Thresholds = self.ImageMasks['Thresholds'][:]
2412            if list(self.Thresholds[0]) == self.Thresholds[1]:     #avoid copy of unchanged thresholds
2413                del self.ImageMasks['Thresholds']   
2414        # make sure all output directories exist
2415        if self.params['SeparateDir']:
2416            for dfmt in self.fmtlist:
2417                if not self.params[dfmt[1:]]: continue
2418                dir = os.path.join(self.params['outdir'],dfmt[1:])
2419                if not os.path.exists(dir): os.makedirs(dir)
2420        else:
2421            if not os.path.exists(self.params['outdir']):
2422                os.makedirs(self.params['outdir'])
2423        if self.Reset: # special things to do after Reset has been pressed
2424            self.G2frame.IntegratedList = []
2425           
2426            if self.params['Mode'] != 'table': # reset controls and masks for all IMG items in tree to master
2427                for img in G2gd.GetPatternTreeDataNames(G2frame,['IMG ']):
2428                    # update controls from master
2429                    controlsDict = G2frame.PatternTree.GetItemPyData(
2430                        G2gd.GetPatternTreeItemId(G2frame,self.imageBase, 'Image Controls'))
2431                    controlsDict.update(self.ImageControls)
2432                    # update masks from master
2433                    ImageMasks = G2frame.PatternTree.GetItemPyData(
2434                        G2gd.GetPatternTreeItemId(G2frame,self.imageBase, 'Masks'))
2435                    ImageMasks.update(self.ImageMasks)
2436            # delete all PWDR items created after last Start was pressed
2437            idlist = []
2438            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
2439            while item:
2440                itemName = G2frame.PatternTree.GetItemText(item)
2441                if itemName in G2frame.AutointPWDRnames:
2442                    idlist.append(item)
2443                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
2444            for item in idlist:
2445                G2frame.PatternTree.Delete(item)
2446            wx.Yield()
2447            self.Reset = False
2448        G2frame.AutointPWDRnames = [] # list of created PWDR tree item names
2449
2450    def OnTimerLoop(self,event):
2451        '''A method that is called every :meth:`PollTime` seconds that is
2452        used to check for new files and process them. This is called only
2453        after the "Start" button is pressed (when its label reads "Pause").
2454        '''
2455        G2frame = self.G2frame
2456        try:
2457            self.currImageList = sorted(
2458                glob.glob(os.path.join(self.imagedir,self.params['filter'])))
2459            self.ShowMatchingFiles(self.params['filter'])
2460        except IndexError:
2461            self.currImageList = []
2462            return
2463
2464        if self.PreventReEntryTimer: return
2465        self.PreventReEntryTimer = True
2466        imageFileList = []
2467        # integrate the images that have already been read in, but
2468        # have not yet been processed
2469        for img in G2gd.GetPatternTreeDataNames(G2frame,['IMG ']):
2470            imgId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,img)
2471            size,imagefile,imagetag = G2frame.PatternTree.GetImageLoc(imgId)
2472            # Create a list of image files that have been read in
2473            if imagefile not in imageFileList: imageFileList.append(imagefile)
2474            # skip if already integrated
2475            if img in G2frame.IntegratedList: continue
2476            if self.params['Mode'] == 'table': # look up parameter values from table
2477                controlsDict = G2frame.PatternTree.GetItemPyData(
2478                    G2gd.GetPatternTreeItemId(G2frame,imgId, 'Image Controls'))
2479                ImageMasks = G2frame.PatternTree.GetItemPyData(
2480                    G2gd.GetPatternTreeItemId(G2frame,imgId, 'Masks'))
2481                self.ResetFromTable(controlsDict['distance'])
2482                # update controls from master
2483                controlsDict.update(self.ImageControls)
2484                # update masks from master w/o Thresholds
2485                ImageMasks.update(self.ImageMasks)
2486            self.IntegrateImage(img)
2487            self.G2frame.oldImagefile = '' # mark image as changed; reread as needed
2488            wx.Yield()
2489            self.ShowMatchingFiles(self.params['filter'])
2490            wx.Yield()
2491            if self.Pause: return
2492
2493        # loop over image files matching glob, reading in any new ones
2494        for newImage in self.currImageList:
2495            if newImage in imageFileList: continue # already read?
2496            for imgId in G2IO.ReadImages(G2frame,newImage):
2497                controlsDict = G2frame.PatternTree.GetItemPyData(
2498                    G2gd.GetPatternTreeItemId(G2frame,imgId, 'Image Controls'))
2499                ImageMasks = G2frame.PatternTree.GetItemPyData(
2500                    G2gd.GetPatternTreeItemId(G2frame,imgId, 'Masks'))
2501                if self.params['Mode'] == 'table': # look up parameter values from table
2502                    self.ResetFromTable(controlsDict['distance'])
2503                # update controls from master
2504                controlsDict.update(self.ImageControls)
2505                # update masks from master w/o Thresholds
2506                ImageMasks.update(self.ImageMasks)
2507                # now integrate the image
2508                img = G2frame.PatternTree.GetItemText(imgId)
2509                self.IntegrateImage(img)
2510                self.G2frame.oldImagefile = '' # mark image as changed; reread as needed
2511                wx.Yield()
2512                self.ShowMatchingFiles(self.params['filter'])
2513                wx.Yield()
2514            if self.Pause: return
2515       
2516        if GSASIIpath.GetConfigValue('debug'):
2517            import datetime
2518            print ("Timer tick at {:%d %b %Y %H:%M:%S}\n".format(datetime.datetime.now()))
2519        self.PreventReEntryTimer = False
2520
2521def DefineEvaluator(dlg):
2522    '''Creates a function that provides interpolated values for a given distance value
2523    '''
2524    def Evaluator(dist):
2525        '''Interpolate image parameters for a supplied distance value
2526
2527        :param float dist: distance to use for interpolation
2528        :returns: a list with 3 items:
2529
2530          * a dict with parameter values,
2531          * the closest imctrl and
2532          * the closest maskfile (or None)
2533        '''           
2534        x = np.array([float(i) for i in parms[0]])
2535        closest = abs(x-dist).argmin()
2536        closeX = x[closest]
2537        D = {'distance':dist}
2538        imctfile = IMfileList[closest]
2539        if parms[-1][closest].lower() != '(none)':
2540            maskfile = parms[-1][closest]
2541        else:
2542            maskfile = None
2543        for c in range(1,cols-1):
2544            lbl = ParmList[c]
2545            if lbl in nonInterpVars:
2546                D[lbl] = float(parms[c][closest])
2547            else:
2548                y = np.array([float(i) for i in parms[c]])
2549                D[lbl] = np.interp(dist,x,y)
2550        # full integration when angular range is 0
2551        D['fullIntegrate'] = (D['LRazimuth_min'] == D['LRazimuth_max'])
2552        # conversion for paired values
2553        for a,b in ('center_x','center_y'),('LRazimuth_min','LRazimuth_max'),('IOtth_min','IOtth_max'):
2554            r = a.split('_')[0]
2555            D[r] = [D[a],D[b]]
2556            del D[a]
2557            del D[b]
2558        return D,imctfile,maskfile
2559    # save local copies of values needed in Evaluator
2560    parms = dlg.ReadImageParmTable()
2561    IMfileList = dlg.IMfileList
2562    cols = dlg.list.GetColumnCount()
2563    ParmList = dlg.ParmList
2564    nonInterpVars = dlg.nonInterpVars
2565    return Evaluator
2566
2567class IntegParmTable(wx.Dialog):
2568    '''Creates a dialog window with a table of integration parameters.
2569    :meth:`ShowModal` will return wx.ID_OK if the process has been successful.
2570    In this case, :func:`DefineEvaluator` should be called to obtain a function that
2571    creates a dictionary with interpolated parameter values.
2572    '''
2573    ParmList = ('distance','center_x','center_y','wavelength','tilt','rotation','DetDepth',
2574            'LRazimuth_min','LRazimuth_max','IOtth_min','IOtth_max','outChannels',
2575            'maskfile',
2576            )
2577    nonInterpVars = ('tilt','rotation','LRazimuth_min','LRazimuth_max','IOtth_min','IOtth_max',
2578                     'outChannels')  # values in this list are taken from nearest rather than interpolated
2579    HeaderList = ('Det Dist','X cntr','Y cntr','wavelength','tilt','rotation','DetDepth',
2580            'Azimuth min','Azimuth max','2Th min','2Th max','Int. pts',
2581            'Mask File',
2582            )
2583    def __init__(self,G2frame,parms=None,IMfileList=None):
2584        self.G2frame = G2frame
2585        wx.Dialog.__init__(self,G2frame,style=wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE)
2586        if parms:
2587            self.parms = parms # list of values by column
2588            self.IMfileList = IMfileList # list of .imctrl file names for each entry in table
2589        else:
2590            self.parms = [] # list of values by column
2591            self.IMfileList = [] # list of .imctrl file names for each entry in table
2592            files = []
2593            try:
2594                pth = G2G.GetImportPath(G2frame)
2595                if not pth: pth = '.'
2596                dlg = wx.FileDialog(self, 'Select image control files or previous table', pth,
2597                                    style=wx.OPEN| wx.MULTIPLE,
2598                                    wildcard='image control files (.imctrl)|*.imctrl|Integration table (*.imtbl)|*.imtbl')
2599                dlg.CenterOnParent()
2600                if dlg.ShowModal() == wx.ID_OK:
2601                    files = dlg.GetPaths()
2602                    self.parms,self.IMfileList = self.ReadFiles(files)
2603            finally:
2604                dlg.Destroy()
2605            if not files:
2606                wx.CallAfter(self.EndModal,wx.ID_CANCEL)
2607                return
2608        mainSizer = wx.BoxSizer(wx.VERTICAL)
2609        self.list = ImgIntLstCtrl(self, wx.ID_ANY,
2610                      style=wx.LC_REPORT
2611                          | wx.BORDER_SUNKEN
2612                         #| wx.BORDER_NONE
2613                         )
2614        mainSizer.Add(self.list,1,wx.EXPAND,1)
2615        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
2616        btn = wx.Button(self, wx.ID_OK)
2617        btnsizer.Add(btn)
2618        btn = wx.Button(self, wx.ID_ANY,'Save as file')
2619        btn.Bind(wx.EVT_BUTTON,self._onSave)
2620        btnsizer.Add(btn)
2621        btn = wx.Button(self, wx.ID_CLOSE,'Quit')
2622        btn.Bind(wx.EVT_BUTTON,self._onClose)
2623        btnsizer.Add(btn)
2624        mainSizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 5)   
2625        self.SetSizer(mainSizer)
2626        self.list.FillList(self.parms)
2627        mainSizer.Layout()
2628        mainSizer.Fit(self)
2629       
2630    def ReadFiles(self,files):
2631        '''Reads a list of .imctrl files or a single .imtbl file
2632        '''
2633        tmpDict = {}
2634        if not files: return
2635        # option 1, a dump from a previous save
2636        if os.path.splitext(files[0])[1] == '.imtbl':
2637            fp = open(files[0],'r')
2638            S = fp.readline()
2639            while S:
2640                if S[0] != '#':
2641                    [key,val] = S[:-1].split(':',1)
2642                    tmpDict[key] = eval(val)
2643                S = fp.readline()
2644            fp.close()
2645            # delete entries
2646            m1 = [i for i,f in enumerate(tmpDict['filenames']) if not os.path.exists(f)]
2647            if m1:
2648                print('\nimctrl file not found:')
2649                for i in m1: print('\t#'+str(i)+': '+tmpDict['filenames'][i])
2650            m2 = [i for i,f in enumerate(tmpDict['maskfile']) if not (os.path.exists(f) or f.startswith('('))]
2651            if m2:
2652                print('\nmask file not found')
2653                for i in m2: print('\t#'+str(i)+': '+tmpDict['maskfile'][i])
2654            m3 = [i for i,d in enumerate(tmpDict['distance']) if d < 0]
2655            if m3:
2656                print('\nDropping entries due to negative distance: '+str(m3))
2657            m = sorted(set(m1 + m2 + m3))
2658            m.reverse()
2659            for c in m:
2660                for key in tmpDict:
2661                    del tmpDict[key][c]
2662            fileList = tmpDict.get('filenames','[]')
2663            parms = []
2664            for key in self.ParmList:
2665                try:
2666                    float(tmpDict[key][0])
2667                    parms.append([str(G2py3.FormatSigFigs(val,sigfigs=5)) for val in tmpDict[key]])
2668                except ValueError:
2669                    parms.append(tmpDict[key])
2670            return parms,fileList
2671        # option 2, read in a list of files
2672        for file in files: # read all files; place in dict by distance
2673            imgDict = Read_imctrl(file)
2674            tmpDict[imgDict.get('distance')] = imgDict
2675        parms = [[] for key in self.ParmList]
2676        fileList = []
2677        for d in sorted(tmpDict):
2678            fileList.append(tmpDict[d].get('filename'))
2679            if d is None: continue
2680            if d < 0: continue
2681            for i,key in enumerate(self.ParmList):
2682                val = tmpDict[d].get(key)
2683                try:
2684                    val = str(G2py3.FormatSigFigs(val,sigfigs=5))
2685                except:
2686                    val = str(val)
2687                parms[i].append(val)
2688        return parms,fileList
2689   
2690    def ReadImageParmTable(self):
2691        '''Reads possibly edited values from the ListCtrl table and returns a list
2692        of values for each column.
2693        '''
2694        rows = self.list.GetItemCount()
2695        cols = self.list.GetColumnCount()
2696        parms = []
2697        for c in range(cols):
2698            lbl = self.ParmList[c]
2699            parms.append([])
2700            for r in range(rows):
2701                parms[c].append(self.list.GetItem(r,c).GetText())
2702        return parms
2703
2704    def _onClose(self,event):
2705        'Called when Cancel button is pressed'
2706        self.EndModal(wx.ID_CANCEL)
2707       
2708    def _onSave(self,event):
2709        'Called when save button is pressed; creates a .imtbl file'
2710        fil = ''
2711        if self.G2frame.GSASprojectfile:
2712            fil = os.path.splitext(self.G2frame.GSASprojectfile)[0]+'.imtbl'
2713        dir,f = os.path.split(fil)
2714        pth = G2G.GetExportPath(self.G2frame)
2715        try:
2716            dlg = wx.FileDialog(self, 'Save table data as',
2717                        defaultDir=pth, defaultFile=f, style=wx.SAVE,
2718                        wildcard='G2 Image Param Table file (*.imtbl)|*.imtbl')
2719            dlg.CenterOnParent()
2720            if dlg.ShowModal() != wx.ID_OK: return
2721            fil = dlg.GetPath()
2722            fil = os.path.splitext(fil)[0]+'.imtbl'
2723        finally:
2724            dlg.Destroy()       
2725        parms = self.ReadImageParmTable()
2726        print('Writing image parameter table as '+fil)
2727        fp = open(fil,'w')
2728        for c in range(len(parms)-1):
2729            lbl = self.ParmList[c]
2730            fp.write(lbl+': '+str([eval(i) for i in parms[c]])+'\n')
2731        lbl = self.ParmList[c+1]
2732        fp.write(lbl+': '+str(parms[c+1])+'\n')
2733        lbl = 'filenames'
2734        fp.write(lbl+': '+str(self.IMfileList)+'\n')
2735        fp.close()
2736   
2737class ImgIntLstCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin,listmix.TextEditMixin):
2738    '''Creates a custom ListCtrl for editing Image Integration parameters
2739    '''
2740    def __init__(self, parent, ID, pos=wx.DefaultPosition,
2741                 size=(1000,200), style=0):
2742        self.parent=parent
2743        wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
2744        listmix.ListCtrlAutoWidthMixin.__init__(self)
2745        listmix.TextEditMixin.__init__(self)
2746        self.Bind(wx.EVT_LEFT_DCLICK, self.OnDouble)
2747        #self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
2748    def FillList(self,parms):
2749        'Places the current parms into the table'
2750        self.ClearAll()
2751        self.rowlen = len(self.parent.ParmList)
2752        for i,lbl in enumerate(self.parent.HeaderList):
2753            self.InsertColumn(i, lbl)
2754        for r,d in enumerate(parms[0]):
2755            if float(d) < 0: continue
2756            index = self.InsertStringItem(sys.maxint, d)
2757            for j in range(1,len(parms)):
2758                self.SetStringItem(index, j, parms[j][r])
2759        for i,lbl in enumerate(self.parent.ParmList):
2760            self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
2761
2762    def OnDouble(self,evt):
2763        'respond to a double-click'
2764        self.CloseEditor()
2765        fil = '(none)'
2766        pth = G2G.GetImportPath(self.parent.G2frame)
2767        if not pth: pth = '.'
2768        try:
2769            dlg = wx.FileDialog(self, 'Select mask or control file to add (Press cancel if none)', pth,
2770                                style=wx.OPEN,
2771                                wildcard='Add GSAS-II mask file (.immask)|*.immask|add image control file (.imctrl)|*.imctrl')
2772            dlg.CenterOnParent()
2773            if dlg.ShowModal() == wx.ID_OK:
2774                fil = dlg.GetPath()
2775        finally:
2776            dlg.Destroy()
2777        if os.path.splitext(fil)[1] != '.imctrl':
2778            self.SetStringItem(self.curRow, self.rowlen-1, fil)
2779            self.SetColumnWidth(self.rowlen-1, wx.LIST_AUTOSIZE)
2780        else:
2781            # insert or overwrite an instrument parameter set
2782            if not os.path.exists(fil):
2783                print('Does not exist: '+fil)
2784                return
2785            imgDict = Read_imctrl(fil)
2786            dist = imgDict['distance']
2787            parms = self.parent.ReadImageParmTable()
2788            x = np.array([float(i) for i in parms[0]])
2789            closest = abs(x-dist).argmin()
2790            closeX = x[closest]
2791            # fix IMfileList
2792            for c,lbl in enumerate(self.parent.ParmList):
2793                try:
2794                    vali = G2py3.FormatSigFigs(float(imgDict[lbl]),sigfigs=5)
2795                except ValueError:
2796                    vali = imgDict[lbl]
2797                if abs(closeX-dist) < 1.: # distance is within 1 mm, replace
2798                    parms[c][closest] = vali
2799                elif dist > closeX: # insert after
2800                    parms[c].insert(closest+1,vali)
2801                else:
2802                    parms[c].insert(closest,vali)
2803            if abs(closeX-dist) < 1.: # distance is within 1 mm, replace
2804                self.parent.IMfileList[closest] = fil
2805            elif dist > closeX: # insert after
2806                self.parent.IMfileList.insert(closest+1,fil)
2807            else:
2808                self.parent.IMfileList.insert(closest,fil)
2809            self.FillList(parms)
2810# Autointegration end
2811###########################################################################
Note: See TracBrowser for help on using the repository browser.