source: trunk/GSASIIimgGUI.py @ 2213

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

force delete of images after they are no longer needed during integration

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