source: trunk/autoint.py @ 2026

Last change on this file since 2026 was 2026, checked in by toby, 8 years ago

autoint minimal, but ready for testing; fixes to Exports

  • Property svn:eol-style set to native
File size: 17.2 KB
Line 
1import os
2import wx
3import copy
4import glob
5import re
6import GSASIIpath
7import GSASIIIO as G2IO
8import GSASIIctrls as G2G
9import GSASIIgrid as G2gd
10import GSASIIimgGUI as G2imG
11'''
12Define a class to be used for Andrey's AutoIntegration process
13'''
14
15class AutoIntFrame(wx.Frame):
16    '''Creates a wx.Frame window for the Image AutoIntegration.
17    The intent is that this will be used as a non-modal dialog window.
18   
19    Implements a Start button that morphs into a pause and resume button.
20    This button starts a processing loop that is repeated every
21    :meth:`PollTime` seconds.
22
23    :param wx.Frame G2frame: main GSAS-II frame
24    :param float PollTime: frequency in seconds to repeat calling the
25      processing loop. (Default is 3.0 seconds.)
26    '''
27    def OnTimerLoop(self,event):
28        '''A method that is called every :meth:`PollTime` seconds that is
29        used to check for new files and process them. This is called only
30        after the "Start" button is pressed (when its label reads "Pause").
31        '''
32        G2frame = self.G2frame
33        try:
34            self.currImageList = sorted(
35                glob.glob(os.path.join(self.imagedir,self.params['filter'])))
36        except IndexError:
37            self.currImageList = []
38            return
39
40        createdImageIdList = []
41        # loop over files that are found, reading in new ones
42        for newImage in self.currImageList:
43            if newImage in self.IntegratedList: continue # already processed
44            Comments,Data,Npix,Image = G2IO.GetImageData(G2frame,newImage)
45            if not Npix:
46                print('problem reading '+newImage)
47                continue
48            G2IO.LoadImage2Tree(newImage,G2frame,Comments,Data,Npix,Image)
49            # update controls from master
50            controlsDict = G2frame.PatternTree.GetItemPyData(
51                G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
52            controlsDict.update(self.ImageControls)
53            # update masks from master
54            ImageMasks = G2frame.PatternTree.GetItemPyData(
55                G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
56            createdImageIdList.append(G2frame.Image) # save IMG Id
57            self.IntegratedList.append(newImage) # save name of image so we don't process it again
58            #print('debug: read '+newImage)
59
60        # now integrate the images we have read
61        for newImagId in createdImageIdList:
62            G2frame.Image = newImagId
63            G2frame.PickId = G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls')
64            #  integrate in this entry
65            size,imagefile = G2frame.PatternTree.GetItemPyData(G2frame.Image)
66            masks = G2frame.PatternTree.GetItemPyData(
67                G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
68            data = G2frame.PatternTree.GetItemPyData(G2frame.PickId)
69            G2frame.ImageZ = G2IO.GetImageData(G2frame,imagefile,True)
70            self.oldImagefile = '' # mark image as changed; reread as needed
71            G2imG.UpdateImageControls(G2frame,data,masks,IntegrateOnly=True)
72            # split name and control number
73            s = re.split(r'(\d+)\Z',os.path.split(os.path.splitext(imagefile)[0])[1])
74            namepre = s[0]
75            if len(s) > 1:
76                namenum = s[1]
77            else:
78                namenum = ''
79            # write out the images in the selected formats
80            for Id in G2frame.IntgOutList:
81                treename = G2frame.PatternTree.GetItemText(Id)
82                Sdata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
83                # determine the name for the current file
84                fileroot = namepre
85                if len(G2frame.IntgOutList) > 1:
86                    fileroot += "_AZM"
87                    if 'Azimuth' in Sdata:
88                        fileroot += str(int(10*Sdata['Azimuth']))
89                    fileroot += "_" 
90                fileroot += namenum
91                # loop over selected formats
92                for dfmt in self.fmtlist:
93                    if not self.params[dfmt[1:]]: continue
94                    if self.params['SeparateDir']:
95                        subdir = dfmt[1:]
96                    else:
97                        subdir = ''
98                    fil = os.path.join(self.params['outdir'],subdir,fileroot)
99                    print('writing file '+fil+dfmt)
100                    G2IO.ExportPowder(G2frame,treename,fil,dfmt)
101       
102        if GSASIIpath.GetConfigValue('debug'):
103            import datetime
104            print ("Timer tick at {:%d %b %Y %H:%M:%S}\n".format(datetime.datetime.now()))
105
106    def StartLoop(self):
107        '''Save current Image params for use in future integrations
108        also label the window so users understand whatis being used
109        '''
110        print '\nStarting new autointegration\n'
111        # show current IMG base
112        self.ControlBaseLbl.SetLabel(self.G2frame.PatternTree.GetItemText(self.G2frame.Image))
113        if self.params['Mode'] == 'file':
114            'get file info'
115            GSASIIpath.IPyBreak()
116        else:
117            # load copy of Image Controls from current image and clean up
118            # items that should not be copied
119            self.ImageControls = copy.deepcopy(
120                self.G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(
121                    self.G2frame,self.G2frame.Image, 'Image Controls')))
122            self.ImageControls['showLines'] = True
123            self.ImageControls['ring'] = []
124            self.ImageControls['rings'] = []
125            self.ImageControls['ellipses'] = []
126            self.ImageControls['setDefault'] = False
127            del self.ImageControls['range']
128            del self.ImageControls['size']
129            del self.ImageControls['GonioAngles']
130            # load copy of Image Masks, keep thresholds
131            self.ImageMasks = copy.deepcopy(
132                self.G2frame.PatternTree.GetItemPyData(
133                    G2gd.GetPatternTreeItemId(self.G2frame,self.G2frame.Image, 'Masks')))
134            self.Thresholds = self.ImageMasks['Thresholds'][:]
135        # make sure all output directories exist
136        if self.params['SeparateDir']:
137            for dfmt in self.fmtlist:
138                if not self.params[dfmt[1:]]: continue
139                dir = os.path.join(self.params['outdir'],dfmt[1:])
140                if not os.path.exists(dir): os.makedirs(dir)
141        else:
142            if not os.path.exists(self.params['outdir']):
143                os.makedirs(self.params['outdir'])
144    def __init__(self,G2frame,PollTime=60.0):
145        def OnStart(event):
146            '''Called when the start button is pressed. Changes button label
147            to Pause. When Pause is pressed the label changes to Resume.
148            When either Start or Resume is pressed, the processing loop
149            is started. When Pause is pressed, the loop is stopped.
150            '''
151            #print self.params # for debug
152
153            # check inputs before starting
154            err = ''
155            #if not any([self.params[fmt] for fmt in self.fmtlist]):
156            #    err += '\nPlease select at least one output format\n'
157            if (self.params['Mode'] == 'file' and not
158                    os.path.exists(self.params['IMGfile'])):
159                err += '\nThe image controls file could not be found\n'
160            if (self.params['Mode'] == 'file' and
161                not self.params['IgnoreMask']
162                ) and not os.path.exists(self.params['MaskFile']): 
163                err += '\nThe mask file could not be found\n'
164            if err:
165                G2G.G2MessageBox(self,err)
166                return
167            # change button label
168            if btnstart.GetLabel() != 'Pause':
169                btnstart.SetLabel('Pause')
170                if self.timer.IsRunning(): self.timer.Stop()
171                self.StartLoop()
172                self.OnTimerLoop(None) # run once immediately and again after delay
173                self.timer.Start(int(1000*PollTime),oneShot=False)
174            else:
175                btnstart.SetLabel('Resume')
176                if self.timer.IsRunning(): self.timer.Stop()
177                print('\nPausing autointegration\n')
178
179        def OnStop(event):
180            '''Called when Stop button is pressed. At present this only
181            stops the processing loop (same as pressing Pause except the
182            label is reset to "Start".)
183            '''
184            btnstart.SetLabel('Start')
185            if self.timer.IsRunning(): self.timer.Stop()
186           
187        def OnQuit(event):
188            '''Stop the processing loop and close the Frame
189            '''
190            # make sure we stop first
191            OnStop(event)
192            self.Destroy()
193           
194        def OnBrowse(event):
195            '''Responds when the Browse button is pressed to load a file.
196            The routine determines which button was pressed and gets the
197            appropriate file type and loads it into the appropriate place
198            in the dict.
199            '''
200            if btn3 == event.GetEventObject():
201                dlg = wx.DirDialog(
202                    self, 'Select directory for output files',
203                    self.params['outdir'],wx.DD_DEFAULT_STYLE)
204                dlg.CenterOnParent()
205                try:
206                    if dlg.ShowModal() == wx.ID_OK:
207                        self.params['outdir'] = dlg.GetPath()
208                        fInp3.SetValue(self.params['outdir'])
209                finally:
210                    dlg.Destroy()
211                return
212            if btn1 == event.GetEventObject():
213                ext = '.imctrl'
214                title = 'Image control'
215            else:
216                ext = '.immask'
217                title = 'Image masks'               
218            dlg = wx.FileDialog(
219                self, 'Select name for '+title+' file to read',
220                '.', '',
221                title+'file (*'+ext+')|*'+ext,
222                wx.OPEN|wx.CHANGE_DIR)
223            dlg.CenterOnParent()
224            try:
225                if dlg.ShowModal() == wx.ID_OK:
226                    filename = dlg.GetPath()
227                    # make sure extension is correct
228                    #filename = os.path.splitext(filename)[0]+ext
229                    if btn1 == event.GetEventObject():
230                        fInp1.SetValue(filename)
231                    else:
232                        fInp2.SetValue(filename)
233                else:
234                    filename = None
235            finally:
236                dlg.Destroy()
237               
238        def OnRadioSelect(event):
239            '''Respond to a radiobutton selection and enable or
240            disable widgets accordingly. Also gets called when the
241            "Don't Use" flag for Mask use is called.
242            '''
243            lbl1.Disable()
244            fInp1.Disable()
245            btn1.Disable()
246            lbl2.Disable()
247            fInp2.Disable()
248            ign2.Disable()
249            btn2.Disable()
250            if r2.GetValue():
251                self.params['Mode'] = 'file'
252                fInp1.Enable()
253                btn1.Enable()
254                lbl1.Enable()
255                ign2.Enable()
256                if not self.params['IgnoreMask']:
257                    fInp2.Enable()
258                    btn2.Enable()
259                    lbl2.Enable()
260            else:
261                self.params['Mode'] = 'active'
262        ##################################################
263        # beginning of __init__ processing
264        ##################################################
265        self.G2frame = G2frame
266        self.params = {}
267        self.params['IMGfile'] = ''
268        self.params['MaskFile'] = ''
269        self.params['IgnoreMask'] = True
270        self.fmtlist = G2IO.ExportPowderList(G2frame)
271        self.timer = wx.Timer()
272        self.timer.Bind(wx.EVT_TIMER,self.OnTimerLoop)
273
274        controlsId = G2frame.PatternTree.GetSelection()
275        size,imagefile = G2frame.PatternTree.GetItemPyData(G2frame.Image)
276        self.imagedir,fileroot = os.path.split(imagefile)
277        self.params['filter'] = '*'+os.path.splitext(fileroot)[1]
278        self.params['outdir'] = os.path.abspath(self.imagedir)
279        # get image names that have already been read
280        self.IntegratedList = []
281        for img in G2gd.GetPatternTreeDataNames(G2frame,['IMG ']):
282            self.IntegratedList.append(G2frame.PatternTree.GetItemPyData(
283                G2gd.GetPatternTreeItemId(G2frame,G2frame.root,img)
284                )[1])
285           
286        wx.Frame.__init__(self, G2frame,title='Automatic Integration')
287        mnpnl = wx.Panel(self)
288        mnsizer = wx.BoxSizer(wx.VERTICAL)
289        sizer = wx.BoxSizer(wx.HORIZONTAL)
290        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Integration based on: '))
291        self.ControlBaseLbl = wx.StaticText(mnpnl, wx.ID_ANY,'?')
292        self.ControlBaseLbl.SetLabel(G2frame.PatternTree.GetItemText(G2frame.Image))
293        sizer.Add(self.ControlBaseLbl)
294        mnsizer.Add(sizer,0,wx.ALIGN_LEFT,1)
295        # file filter stuff
296        sizer = wx.BoxSizer(wx.HORIZONTAL)
297        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Image filter'))
298        flterInp = G2G.ValidatedTxtCtrl(mnpnl,self.params,'filter')
299        sizer.Add(flterInp)
300        mnsizer.Add(sizer,0,wx.ALIGN_RIGHT,1)
301        # box for integration controls & masks input
302        lbl = wx.StaticBox(mnpnl, wx.ID_ANY, "Integration Controls/Masks source")
303        lblsizr = wx.StaticBoxSizer(lbl, wx.VERTICAL)
304        r1 = wx.RadioButton(mnpnl, wx.ID_ANY, "Use Active Image",
305                            style = wx.RB_GROUP)
306        r1.Bind(wx.EVT_RADIOBUTTON, OnRadioSelect)
307        lblsizr.Add(r1)
308        r1.SetValue(True)
309        r2 = wx.RadioButton(mnpnl, wx.ID_ANY, "Use from file(s)")
310        lblsizr.Add(r2)
311        r2.Bind(wx.EVT_RADIOBUTTON, OnRadioSelect)
312        r2.Disable()         # deactivate this until implemented
313        # Image controls file
314        sizer = wx.BoxSizer(wx.HORIZONTAL)
315        sizer.Add((20,-1))
316        lbl1 = wx.StaticText(mnpnl, wx.ID_ANY,'IMG control file: ')
317        sizer.Add(lbl1)
318        fInp1 = G2G.ValidatedTxtCtrl(mnpnl,self.params,'IMGfile',
319                                       notBlank=False,size=(300,-1))
320        sizer.Add(fInp1)
321        btn1 = wx.Button(mnpnl,  wx.ID_ANY, "Browse")
322        btn1.Bind(wx.EVT_BUTTON, OnBrowse)
323        sizer.Add(btn1)
324        lblsizr.Add(sizer)
325        # Masks input file
326        sizer = wx.BoxSizer(wx.HORIZONTAL)
327        sizer.Add((20,-1))
328        lbl2 = wx.StaticText(mnpnl, wx.ID_ANY,'Mask file: ')
329        sizer.Add(lbl2)
330        fInp2 = G2G.ValidatedTxtCtrl(mnpnl,self.params,'MaskFile',
331                                       notBlank=False,size=(300,-1))
332        sizer.Add(fInp2)
333        ign2 = G2G.G2CheckBox(mnpnl,"Don't use",self.params,'IgnoreMask',
334                              OnChange=OnRadioSelect)
335        sizer.Add(ign2)
336        btn2 = wx.Button(mnpnl,  wx.ID_ANY, "Browse")
337        btn2.Bind(wx.EVT_BUTTON, OnBrowse)
338        sizer.Add(btn2)
339        lblsizr.Add(sizer)
340        mnsizer.Add(lblsizr)
341
342        # box for output selections
343        lbl = wx.StaticBox(mnpnl, wx.ID_ANY, "Output settings")
344        lblsizr = wx.StaticBoxSizer(lbl, wx.VERTICAL)
345        sizer = wx.BoxSizer(wx.HORIZONTAL)
346        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Write to: '))
347        fInp3 = G2G.ValidatedTxtCtrl(mnpnl,self.params,'outdir',
348                                       notBlank=False,size=(300,-1))
349        sizer.Add(fInp3)
350        btn3 = wx.Button(mnpnl,  wx.ID_ANY, "Browse")
351        btn3.Bind(wx.EVT_BUTTON, OnBrowse)
352        sizer.Add(btn3)
353        lblsizr.Add(sizer)
354        #lblsizr.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Select format(s): '))
355        sizer = wx.BoxSizer(wx.HORIZONTAL)
356        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Select format(s): '))
357        for dfmt in self.fmtlist:
358            fmt = dfmt[1:]
359            self.params[fmt] = False
360            btn = G2G.G2CheckBox(mnpnl,dfmt,self.params,fmt)
361            sizer.Add(btn)
362        lblsizr.Add(sizer)
363        sizer = wx.BoxSizer(wx.HORIZONTAL)
364        sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Separate dir for each format: '))
365        self.params['SeparateDir'] = False
366        sizer.Add(G2G.G2CheckBox(mnpnl,'',self.params,'SeparateDir'))
367        lblsizr.Add(sizer)
368        mnsizer.Add(lblsizr,0,wx.ALIGN_CENTER,1)
369
370        # buttons on bottom
371        mnsizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'AutoIntegration controls'),0,wx.TOP,5)
372        sizer = wx.BoxSizer(wx.HORIZONTAL)
373        sizer.Add((20,-1))
374        btnstart = wx.Button(mnpnl,  wx.ID_ANY, "Start")
375        btnstart.Bind(wx.EVT_BUTTON, OnStart)
376        sizer.Add(btnstart)
377        btnstop = wx.Button(mnpnl,  wx.ID_ANY, "Stop")
378        btnstop.Bind(wx.EVT_BUTTON, OnStop)
379        sizer.Add(btnstop)
380        sizer.Add((20,-1),wx.EXPAND,1)
381        btnquit = wx.Button(mnpnl,  wx.ID_ANY, "Close")
382        btnquit.Bind(wx.EVT_BUTTON, OnQuit)
383        sizer.Add(btnquit)
384        sizer.Add((20,-1))
385        mnsizer.Add(sizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP,5)
386       
387        # finish up window
388        mnpnl.SetSizer(mnsizer)
389        OnRadioSelect(None) # disable widgets
390        mnsizer.Fit(self)
391        self.CenterOnParent()
392        self.Show() 
393
394if __name__ == '__main__':
395    app = wx.PySimpleApp()
396    G2frame = wx.Frame(None) # create a top-level frame as a stand-in for the GSAS-II data tree
397    G2frame.Show() 
398    frm = AutoIntFrame(G2frame) # test the one above
399    app.MainLoop()
400 
Note: See TracBrowser for help on using the repository browser.