source: trunk/scanCCD.py @ 451

Last change on this file since 451 was 451, checked in by vondreele, 10 years ago
File size: 30.6 KB
Line 
1#scanCCD data processing
2
3import os
4import os.path as ospath
5import sys
6import math
7import time
8import numpy as np
9import numpy.linalg as nl
10import numpy.ma as ma
11import wx
12import matplotlib as mpl
13import GSASIIpath
14import GSASIIIO as G2IO
15import GSASIIimage as G2img
16import GSASIIplot as G2plt
17
18npsind = lambda x: np.sin(x*np.pi/180.)
19npcosd = lambda x: np.cos(x*np.pi/180.)
20npacosd = lambda x: 180.*np.arccos(x)/np.pi
21npasind = lambda x: 180.*np.arcsin(x)/np.pi
22
23def create(parent):
24    return scanCCD(parent)
25   
26[wxID_FILEEXIT, wxID_FILEOPEN, wxID_INTEGRATE, wxID_OUTPUT,
27] = [wx.NewId() for _init_coll_File_Items in range(4)]
28
29class scanCCD(wx.Frame):
30
31    def _init_ctrls(self, parent):
32        wx.Frame.__init__(self, name='scanCCD', parent=parent,
33            size=wx.Size(460, 250),style=wx.DEFAULT_FRAME_STYLE, title='scanCCD')
34        self.scanCCDMenu = wx.MenuBar()
35        self.File = wx.Menu(title='')
36        self.File.Append(help='Open scanCCD image files (*.tif)', id=wxID_FILEOPEN,
37             kind=wx.ITEM_NORMAL,text='Open scanCCD files')
38        self.File.Append(help='Integrate scanCCD images',id=wxID_INTEGRATE,
39             kind=wx.ITEM_NORMAL,text='Integrate scanCCD images')
40        self.File.Append(help='Output fxye file from integration',id=wxID_OUTPUT,
41             kind=wx.ITEM_NORMAL,text='Output pattern')
42        self.File.Append(help='Exit from scanCCD', id=wxID_FILEEXIT, kind=wx.ITEM_NORMAL,
43            text='Exit')
44        self.Bind(wx.EVT_MENU, self.OnImageRead, id=wxID_FILEOPEN)
45        self.Bind(wx.EVT_MENU,self.OnImageIntegrate,id=wxID_INTEGRATE)
46        self.Bind(wx.EVT_MENU,self.OnOutput,id=wxID_OUTPUT)
47        self.Bind(wx.EVT_MENU, self.OnFileExit, id=wxID_FILEEXIT)
48        self.scanCCDMenu.Append(menu=self.File, title='File')
49        self.SetMenuBar(self.scanCCDMenu)
50        self.SCCDPanel = wx.Panel(self)       
51        plotFrame = wx.Frame(None,-1,'scanCCD Plots',size=wx.Size(700,600), \
52            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
53        self.plotNB = G2plt.G2PlotNoteBook(plotFrame)
54        plotFrame.Show()
55
56    def __init__(self, parent):
57        self._init_ctrls(parent)
58        self.Bind(wx.EVT_CLOSE, self.ExitMain)   
59        self.dirname = ''
60        self.imagefiles = []
61        self.dataFrame = None
62        self.itemPicked = None
63        self.Image = []
64        self.Hxyw = []
65        self.data = {'color':'Paired','range':[[0,1000],[0,1000]]}
66
67    def ExitMain(self, event):
68        sys.exit()
69       
70    def OnFileExit(self,event):
71        if self.dataFrame:
72            self.dataFrame.Clear() 
73            self.dataFrame.Destroy()
74        self.Close()
75       
76    def OnImageRead(self,event):
77        dlg = wx.FileDialog(self, 'Choose scanCCD image files', '.', '',\
78        'Any detector tif (*.tif;*.tiff)|*.tif;*.tiff|\
79        All files (*.*)|*.*',
80        wx.OPEN | wx.MULTIPLE)
81        if self.dirname:
82            dlg.SetDirectory(self.dirname)
83        try:
84            self.imagefiles = []
85            if dlg.ShowModal() == wx.ID_OK:
86                self.dirname = dlg.GetDirectory()
87                self.imagefiles = dlg.GetPaths()
88                self.imagefiles.sort()
89                self.data['imScale'] = 8
90                self.Image = []
91                for imagefile in self.imagefiles:
92                    Comments,Data,Npix,image = G2IO.GetImageData(self,imagefile)
93                    if Comments:
94                        A = G2img.ImageCompress(image,self.data['imScale'])
95                        if len(self.Image):
96                            self.Image = np.concatenate((self.Image,A))
97                        else:
98                            self.Image = A
99                self.data['range'][0] = self.data['range'][1] = np.max(self.Image)
100                self.data['pixel'] = Data['pixelSize']
101                self.data['size'] = self.Image.shape
102                self.data['Zmin'] = np.min(self.Image)
103                self.data['Zmax'] = np.max(self.Image)
104                self.data['Zeros'] = [-15.3096,16.4]        #for bob1-3 files
105                self.data['mm/deg'] = 15.56012              #from bob1 fit to 2333 peak positions
106                self.data['radius'] = 180.0*self.data['mm/deg']/math.pi
107                self.data['TBlimits'] = [0,len(image)]
108                self.data['LRlimits'] = [0,len(image)*len(self.imagefiles)]
109                self.data['PtScan'] = len(image)/2
110                self.data['2thScan'] = [0.0,90.0,0.001]
111                self.data['showBlk'] = False
112                self.data['skip'] = 1               #default - skip ramp block
113                if len(self.imagefiles) == 1:
114                    self.data['skip'] = 0
115                self.UpdateControls(event)
116                self.PlotImage()
117        finally:
118            dlg.Destroy()
119           
120    def OnImageIntegrate(self,event):
121       
122        def Make2ThetaMap(data,iLim,jLim):
123            #transforms scanCCD image from x,y space to 2-theta,y space
124            pixelSize = data['pixel']
125            scalex = pixelSize[0]/1000.
126            scaley = pixelSize[1]/1000.
127            vecA = np.asfarray([1.,0.,0.],dtype=np.float32)
128           
129            tay,tax = np.mgrid[jLim[0]+.5:jLim[1]+.5,iLim[0]+.5:iLim[1]+.5]        #bin centers not corners
130            tax = np.asfarray((tax*scalex-data['Zeros'][0])/data['mm/deg'],dtype=np.float32)  #scanCCD 2-thetas
131            tay = np.asfarray(tay*scaley-data['Zeros'][1],dtype=np.float32)
132            vecB = np.array([npcosd(tax)*data['radius'],npsind(tax)*data['radius'],tay])
133            norm = np.sqrt(np.sum((vecB.T*vecB.T),axis=2))
134            vecB /= norm.T
135            tax = npacosd(np.dot(vecB.T,vecA))*tax/np.abs(tax)      #to get sign of 2-theta
136            tay += data['Zeros'][1]
137            return tax,tay.T           #2-theta arrays & turn y array around!!
138
139   
140        def Fill2ThetaMap(data,TA,image):
141            import numpy.ma as ma
142            Zmin = data['Zmin']
143            Zmax = data['Zmax']
144            tax,tay = TA    # 2-theta & yaxis
145            taz = ma.masked_outside(image.flatten()-Zmin,0,Zmax-Zmin)
146            tam = ma.getmask(taz)
147            tax = ma.compressed(ma.array(tax.flatten(),mask=tam))
148            tay = ma.compressed(ma.array(tay.flatten(),mask=tam))
149            taz = ma.compressed(ma.array(taz.flatten(),mask=tam))
150            del(tam)
151            return tax,tay,taz
152       
153        import histosigma2d as h2d
154        print 'Begin image integration'
155        scaley = self.data['pixel'][1]/1000.
156        tthStart,tthEnd,tthStep = self.data['2thScan']
157        LUtth = [tthStart,tthEnd]
158        TBlim = np.array(self.data['TBlimits'],dtype=np.float32)
159        nYpix = TBlim[1]-TBlim[0]
160        TBlim *= scaley
161        TBdelt = TBlim[1]-TBlim[0]
162        nTB = 1
163        numChans = (tthEnd-tthStart)/tthStep
164        NST = np.zeros(shape=(numChans,1),order='F',dtype=np.float32)
165        H0 = np.zeros(shape=(numChans,1),order='F',dtype=np.float32)
166        Amat = np.zeros(shape=(numChans,1),order='F',dtype=np.float32)
167        Qmat = np.zeros(shape=(numChans,1),order='F',dtype=np.float32)
168        imSize = np.array(self.data['size'])*self.data['imScale']
169        H1 = [tth for tth in np.linspace(LUtth[0],LUtth[1],numChans)]
170        blkSize = 2048
171        N = 4096/blkSize
172        nBlk = N**2*len(self.imagefiles)       #assume 4Kx4K CCD images - done in 1Kx1K blocks
173        t0 = time.time()
174        dlg = wx.ProgressDialog("Elapsed time","2D image integration",nBlk,
175            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
176        try:
177            nBlk = 0
178            iBegi = 0
179            iFin = 0
180            GoOn = True
181            for ifile,imagefile in enumerate(self.imagefiles):
182                if ifile >= self.data['skip']:
183                    image = G2IO.GetImageData(self,imagefile)[3]
184                    image = np.fliplr(image)
185                    for iBlk in range(N):
186                        iBeg = iBegi+iBlk*blkSize
187                        iFin = iBeg+blkSize
188                        for jBlk in range(N):
189                            jBeg = jBlk*blkSize
190                            jFin = jBeg+blkSize               
191                            print 'Process map block:',nBlk,iBlk,jBlk,' offset:',iBegi,' limits:',iBeg,iFin,jBeg,jFin
192                            TA = Make2ThetaMap(self.data,(iBeg,iFin),(jBeg,jFin))           #2-theta & Y arrays & create position mask                       
193                            Block = image[iBeg-iBegi:iFin-iBegi,jBeg:jFin]
194                            tax,tay,taz = Fill2ThetaMap(self.data,TA,Block)                 #and apply masks
195                            NST,H0,Amat,Qmat = h2d.histosigma2d(len(tax),tax,tay,taz,numChans,nTB,LUtth,TBlim,tthStep,TBdelt,NST,H0,Amat,Qmat)
196                            H0temp = np.nan_to_num(np.divide(H0,NST))
197                            Qtemp = np.nan_to_num(np.divide(Qmat,NST))
198                            if self.data['showBlk']:
199                                self.PlotBlock(Block.T,'%s %d %d'%('Block',iBlk,jBlk))
200                                OKdlg = wx.MessageDialog(self,'','Continue',wx.OK)
201                                try:
202                                    result = OKdlg.ShowModal()
203                                finally:
204                                    OKdlg.Destroy()
205                            del tax,tay,taz
206                            nBlk += 1
207                            GoOn = dlg.Update(nBlk)[0]
208                            if not GoOn:
209                                break
210                else:
211                    print 'file '+imagefile+' skipped'
212                    nBlk += N*N
213                    GoOn = dlg.Update(nBlk)[0]
214                    iFin += N*blkSize
215                if not GoOn:
216                    break
217                iBegi = iFin
218            H0 = np.divide(H0,NST)
219            H0 = np.nan_to_num(H0)
220            Qmat = np.divide(Qmat,NST)
221            Qmat = np.nan_to_num(Qmat)
222            del NST
223            t1 = time.time()
224        finally:
225            dlg.Destroy()
226        Scale = np.sum(Qmat)/np.sum(H0)
227        print 'SumI: ',np.sum(H0),' SumV: ',np.sum(Qmat),' Scale:',Scale
228        print 'Integration complete'
229        print "Elapsed time:","%8.3f"%(t1-t0), "s"
230        self.Hxyw = [H1,Scale*H0.T[0],np.sqrt(Qmat.T[0])]
231        print 
232        self.PlotXY(self.Hxyw,True,type='Integration result')
233       
234    def OnOutput(self,event):
235
236        def powderSave(self,powderfile,Fxye=False):
237            file = open(powderfile,'w')
238            file.write('#%s\n'%('from scanCCD image '+self.imagefiles[0]))
239            print 'save powder pattern to file: ',powderfile
240            wx.BeginBusyCursor()
241            try:
242                x,y,e = self.Hxyw
243                if Fxye:
244                    file.write(powderfile+'\n')
245                    file.write('BANK 1 %d %d CONS %.2f %.2f 0 0 FXYE\n'%(len(x),len(x),\
246                        100.*x[0],100.*(x[1]-x[0])))                   
247                XYE = zip(x,y,e)
248                for X,Y,E in XYE:
249                    if Fxye:
250                        file.write("%15.6g %15.6g %15.6g\n" % (100.*X,Y,max(E,1.0)))                       
251                    else:
252                        file.write("%15.6g %15.6g %15.6g\n" % (X,Y,max(E,1.0)))
253                file.close()
254            finally:
255                wx.EndBusyCursor()
256            print 'powder pattern file written'
257       
258        if not self.Hxyw:
259            return
260        dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
261            'GSAS fxye file (*.fxye)|*.fxye|xye file (*.xye)|*.xye',
262            wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
263        if self.dirname:
264            dlg.SetDirectory(self.dirname)
265        try:
266            if dlg.ShowModal() == wx.ID_OK:
267                powderfile = dlg.GetPath()
268                if 'fxye' in powderfile:
269                    powderSave(self,powderfile,Fxye=True)
270                else:       #just xye
271                    powderSave(self,powderfile)
272                self.dirname = dlg.GetDirectory()
273        finally:
274            dlg.Destroy()
275
276    def UpdateControls(self,event):
277        ObjIndx = {}
278        self.SCCDPanel.DestroyChildren()
279       
280        def ColorSizer(data):
281           
282            def OnNewColorBar(event):
283                colSel = event.GetEventObject()
284                data['color'] = colSel.GetValue()
285                self.PlotImage()
286               
287            def OnShowBlk(event):
288                data['showBlk'] = shoBlk.GetValue()
289               
290            def OnSkipFiles(event):
291                data['skip'] = int(skipFile.GetValue())
292                           
293            colorList = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
294            colorSizer = wx.FlexGridSizer(1,5,5,5)
295            colorSizer.Add(wx.StaticText(self.SCCDPanel,label=' Color bar '),0,wx.ALIGN_CENTER_VERTICAL)
296            colSel = wx.ComboBox(self.SCCDPanel,value=data['color'],choices=colorList,
297                style=wx.CB_READONLY|wx.CB_DROPDOWN|wx.CB_SORT)
298            colSel.Bind(wx.EVT_COMBOBOX, OnNewColorBar)
299            colorSizer.Add(colSel,0,wx.ALIGN_CENTER_VERTICAL)
300            colorSizer.Add(wx.StaticText(self.SCCDPanel,label='image files to skip:'),0,wx.ALIGN_CENTER_VERTICAL)
301            skipFile = wx.ComboBox(self.SCCDPanel,value=str(data['skip']),
302                choices=[str(i) for i in range(len(self.imagefiles))],
303                style=wx.CB_READONLY|wx.CB_DROPDOWN)
304            skipFile.Bind(wx.EVT_COMBOBOX,OnSkipFiles)
305            colorSizer.Add(skipFile,0,wx.ALIGN_CENTER_VERTICAL)
306            shoBlk = wx.CheckBox(self.SCCDPanel,-1,label='Show image blocks?')
307            shoBlk.SetValue(data['showBlk'])
308            shoBlk.Bind(wx.EVT_CHECKBOX, OnShowBlk)
309            colorSizer.Add(shoBlk,0,wx.ALIGN_CENTER_VERTICAL)
310            return colorSizer                   
311           
312        def MaxSizer(data):
313           
314            def OnMaxSlider(event):           
315                imax = int(self.maxSel.GetValue())*data['range'][0]/100.
316                data['range'][1] = imax
317                self.maxVal.SetValue('%d'%(data['range'][1]))
318                self.PlotImage()
319               
320            def OnMaxValue(event):
321                try:
322                    value = int(self.maxVal.GetValue())
323                    if value < 0 or value > data['range'][0]:
324                        raise ValueError
325                except ValueError:
326                    value = data['range'][1]
327                data['range'][1] = value
328                self.maxSel.SetValue(int(100*value/data['range'][0]))
329                self.PlotImage()
330           
331            maxSizer = wx.FlexGridSizer(1,3,0,5)
332            maxSizer.AddGrowableCol(1,1)
333            maxSizer.SetFlexibleDirection(wx.HORIZONTAL)
334            maxSizer.Add(wx.StaticText(parent=self.SCCDPanel,label=' Max intensity'),0,
335                wx.ALIGN_CENTER_VERTICAL)
336            self.maxSel = wx.Slider(parent=self.SCCDPanel,style=wx.SL_HORIZONTAL,
337                value=int(100*data['range'][1]/data['range'][0]))
338            maxSizer.Add(self.maxSel,1,wx.EXPAND)
339            self.maxSel.Bind(wx.EVT_SLIDER, OnMaxSlider)
340            self.maxVal = wx.TextCtrl(parent=self.SCCDPanel,value='%d'%(data['range'][1]))
341            self.maxVal.Bind(wx.EVT_TEXT_ENTER,OnMaxValue)
342            self.maxVal.Bind(wx.EVT_KILL_FOCUS,OnMaxValue)
343            maxSizer.Add(self.maxVal,0,wx.ALIGN_CENTER_VERTICAL)   
344            return maxSizer   
345                   
346        def ZSizer(data):
347           
348            def OnZValue(event):
349                Obj = event.GetEventObject()
350                try:
351                    value = int(Obj.GetValue())
352                except ValueError:
353                    value = data[ObjIndx[Obj.GetId()]]
354                data[ObjIndx[Obj.GetId()]] = value
355                self.PlotImage()
356           
357            zSizer = wx.FlexGridSizer(1,4,5,5)
358            zSizer.Add(wx.StaticText(self.SCCDPanel,label='Upper intensity mask:'),0,wx.ALIGN_CENTER_VERTICAL)
359            zMax = wx.TextCtrl(self.SCCDPanel,value='%d'%(data['Zmax']))
360            zMax.Bind(wx.EVT_TEXT_ENTER,OnZValue)
361            zMax.Bind(wx.EVT_KILL_FOCUS,OnZValue)
362            ObjIndx[zMax.GetId()] = 'Zmax'
363            zSizer.Add(zMax)
364            zSizer.Add(wx.StaticText(self.SCCDPanel,label='Intensity subtraction:'),0,wx.ALIGN_CENTER_VERTICAL)
365            zMin = wx.TextCtrl(self.SCCDPanel,value='%d'%(data['Zmin']))
366            ObjIndx[zMin.GetId()] = 'Zmin'
367            zMin.Bind(wx.EVT_TEXT_ENTER,OnZValue)
368            zMin.Bind(wx.EVT_KILL_FOCUS,OnZValue)
369            zSizer.Add(zMin)
370            return zSizer
371                       
372        def ZeroSizer(data):
373           
374            def OnZeroValue(event):
375                Obj = event.GetEventObject()
376                item = ObjIndx[Obj.GetId()]
377                try:
378                    value = float(Obj.GetValue())
379                except ValueError:
380                    value = data[item[0]][item[1]]
381                data[item[0]][item[1]] = value
382                Obj.SetValue('%.3f'%(value))
383                self.PlotImage()
384               
385            def OnZpdgValue(event):
386                Obj = event.GetEventObject()
387                item = ObjIndx[Obj.GetId()]
388                try:
389                    value = float(Obj.GetValue())
390                except ValueError:
391                    value = self.data[item[0]]
392                self.data[item[0]] = value
393                self.data['radius'] = 180.0*value/math.pi
394                Obj.SetValue('%.3f'%(value))
395                self.PlotImage()
396           
397            zeroSizer = wx.FlexGridSizer(1,6,5,5)
398            zeroSizer.Add(wx.StaticText(self.SCCDPanel,label='X-zero:'),0,wx.ALIGN_CENTER_VERTICAL)
399            zMax = wx.TextCtrl(self.SCCDPanel,value='%.3f'%(data['Zeros'][0]))
400            zMax.Bind(wx.EVT_TEXT_ENTER,OnZeroValue)
401            zMax.Bind(wx.EVT_KILL_FOCUS,OnZeroValue)
402            ObjIndx[zMax.GetId()] = ['Zeros',0]
403            zeroSizer.Add(zMax)
404            zeroSizer.Add(wx.StaticText(self.SCCDPanel,label='Y-zero:'),0,wx.ALIGN_CENTER_VERTICAL)
405            zMin = wx.TextCtrl(self.SCCDPanel,value='%.3f'%(data['Zeros'][1]))
406            ObjIndx[zMin.GetId()] = ['Zeros',1]
407            zMin.Bind(wx.EVT_TEXT_ENTER,OnZeroValue)
408            zMin.Bind(wx.EVT_KILL_FOCUS,OnZeroValue)
409            zeroSizer.Add(zMin)
410            zeroSizer.Add(wx.StaticText(self.SCCDPanel,label='mm per deg:'),0,wx.ALIGN_CENTER_VERTICAL)
411            zpdeg = wx.TextCtrl(self.SCCDPanel,value='%.3f'%(data['mm/deg']))
412            ObjIndx[zpdeg.GetId()] = ['mm/deg']
413            zpdeg.Bind(wx.EVT_TEXT_ENTER,OnZpdgValue)
414            zpdeg.Bind(wx.EVT_KILL_FOCUS,OnZpdgValue)
415            zeroSizer.Add(zpdeg)
416            return zeroSizer
417                       
418        def TBLRSizer(data):
419           
420            def OnTBLRValue(event):
421                Obj = event.GetEventObject()
422                item = ObjIndx[Obj.GetId()]
423                try:
424                    value = int(Obj.GetValue())
425                except ValueError:
426                    value = data[item[0]][item[1]]
427                data[item[0]][item[1]] = value
428                Obj.SetValue('%d'%(value))
429                self.PlotImage()
430           
431            TBLRsizer = wx.FlexGridSizer(2,4,5,5)
432            for i,item in enumerate(['Bottom','Top']): 
433                TBLRsizer.Add(wx.StaticText(self.SCCDPanel,label=item+' limit, pixels:'),0,wx.ALIGN_CENTER_VERTICAL)
434                TBlim = wx.TextCtrl(self.SCCDPanel,value='%d'%(data['TBlimits'][i]))
435                TBlim.Bind(wx.EVT_TEXT_ENTER,OnTBLRValue)
436                TBlim.Bind(wx.EVT_KILL_FOCUS,OnTBLRValue)
437                ObjIndx[TBlim.GetId()] = ['TBlimits',i]
438                TBLRsizer.Add(TBlim)
439            return TBLRsizer
440           
441        def ScanSizer(data):
442           
443            def OnScanValue(event):
444                Obj = event.GetEventObject()
445                item = ObjIndx[Obj.GetId()][0]
446                try:
447                    value = float(Obj.GetValue())
448                except ValueError:
449                    value = self.data['2thScan'][item]
450                data['2thScan'][item] = value
451                Obj.SetValue('%.3f'%(value))
452                if item in [0,1]:
453                    pixel = data['pixel']
454                    zero = data['Zeros'][0]
455                    tthscale = data['mm/deg']
456                    npixel = (value*tthscale+zero)*1000/pixel[0]
457                    data['LRlimits'][item] = npixel
458                self.PlotImage()
459           
460            scanSizer = wx.FlexGridSizer(1,6,5,5)
461            for i,item in enumerate(['Lower 2-th','Upper 2-th','2-th step']):
462                scanSizer.Add(wx.StaticText(self.SCCDPanel,label=item+':'),0,wx.ALIGN_CENTER_VERTICAL)
463                scanParm = wx.TextCtrl(self.SCCDPanel,value='%.3f'%(data['2thScan'][i]))
464                scanParm.Bind(wx.EVT_TEXT_ENTER,OnScanValue)
465                scanParm.Bind(wx.EVT_KILL_FOCUS,OnScanValue)
466                ObjIndx[scanParm.GetId()] = [i]
467                scanSizer.Add(scanParm)
468            return scanSizer               
469                       
470        mainSizer = wx.BoxSizer(wx.VERTICAL)
471        mainSizer.Add(ColorSizer(self.data),0,wx.ALIGN_CENTER_VERTICAL)       
472        mainSizer.Add(MaxSizer(self.data),0,wx.ALIGN_LEFT|wx.EXPAND)
473        mainSizer.Add(ZSizer(self.data),0,wx.ALIGN_CENTER_VERTICAL)
474        mainSizer.Add(ZeroSizer(self.data),0,wx.ALIGN_CENTER_VERTICAL)
475        mainSizer.Add(ScanSizer(self.data),0,wx.ALIGN_CENTER_VERTICAL)
476        mainSizer.Add(TBLRSizer(self.data),0,wx.ALIGN_CENTER_VERTICAL)
477        self.SCCDPanel.SetSizer(mainSizer)
478        mainSizer.Layout()   
479        fitSize = mainSizer.Fit(self.SCCDPanel)
480#        self.SCCDPanel.GetParent().SetSize(fitSize)
481           
482    def PlotImage(self):
483        pixel = self.data['pixel']
484        scalex = pixel[0]/1000.
485        scaley = pixel[1]/1000.
486
487       
488        def OnMotion(event):
489            Page.canvas.SetToolTipString('')
490            sizexy = self.data['size']
491            if event.xdata and event.ydata:                 #avoid out of frame errors
492                Page.canvas.SetCursor(wx.CROSS_CURSOR)
493                item = self.itemPicked
494                if item:
495                    if 'Line' in str(item):
496                        Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
497                else:
498                    xpos = event.xdata
499                    ypos = event.ydata
500                    xpix = xpos/(self.data['imScale']*scalex)
501                    ypix = sizexy[1]-ypos/(self.data['imScale']*scaley)
502                    Int = 0
503                    if (0 <= xpix <= sizexy[0]) and (0 <= ypix <= sizexy[1]):
504                        Int = self.Image[xpix][ypix]-self.data['Zmin']
505                        tth = (xpos-self.data['Zeros'][0])/self.data['mm/deg']
506                        vecA = np.array([1.0,0,0])
507                        vecB = np.array([npcosd(tth)*self.data['radius'],npsind(tth)*self.data['radius'],(ypos-self.data['Zeros'][1])])
508                        vecB /= nl.norm(vecB)
509                        tth2 = npacosd(np.dot(vecA,vecB))*tth/abs(tth)
510                        self.plotNB.status.SetFields(\
511                            ['','Detector x,y =%9.3fmm %9.3fmm, 2-th =%9.3f I = %6d'%(xpos,ypos,tth2,Int)])
512                           
513        def OnPick(event):
514            if self.itemPicked is not None: return
515            self.itemPicked = event.artist
516            self.mousePicked = event.mouseevent
517           
518        def OnRelease(event):
519            if self.itemPicked is None: return
520            xpos,ypos = [event.xdata,event.ydata]
521            if '_line0' in str(self.itemPicked):    #X-zero
522                self.data['Zeros'][0] = xpos               
523            elif '_line1' in str(self.itemPicked):  #Y-zero
524                self.data['Zeros'][1] = ypos
525            elif '_line2' in str(self.itemPicked): #Y-lower limit
526                self.data['TBlimits'][0] = int(ypos/scaley)
527            elif '_line3' in str(self.itemPicked): #Y-upper limit
528                self.data['TBlimits'][1] = int(ypos/scaley)
529            elif '_line4' in str(self.itemPicked): #X-lower limit
530                self.data['LRlimits'][0] = int(xpos/scalex)
531            elif '_line5' in str(self.itemPicked): #X-upper limit
532                self.data['LRlimits'][1] = int(xpos/scalex)
533            self.itemPicked = None   
534            self.PlotImage()
535            self.UpdateControls(event)
536       
537        try:
538            plotNum = self.plotNB.plotList.index('scanCCD image')
539            Page = self.plotNB.nb.GetPage(plotNum)
540            Plot = Page.figure.gca()          #get previous powder plot & get limits
541            xylim = Plot.get_xlim(),Plot.get_ylim()
542            Page.figure.clf()
543            Plot = Page.figure.gca()
544            if not Page.IsShown():
545                Page.Show()
546        except ValueError:
547            Plot = self.plotNB.addMpl('scanCCD image').gca()
548            plotNum = self.plotNB.plotList.index('scanCCD image')
549            Page = self.plotNB.nb.GetPage(plotNum)
550            Page.canvas.mpl_connect('motion_notify_event', OnMotion)
551            Page.canvas.mpl_connect('pick_event', OnPick)
552            Page.canvas.mpl_connect('button_release_event', OnRelease)
553            xylim = []
554        xlim,ylim = self.data['size']
555        Imin,Imax = [0,self.data['range'][1]]
556        Xmax = scalex*xlim*self.data['imScale']
557        Ymax = scaley*ylim*self.data['imScale']
558        TBlimit = np.array(self.data['TBlimits'])*scalex
559        LRlimit = np.array(self.data['LRlimits'])*scaley
560
561        self.plotNB.status.SetFields(['',''])
562        Zmin = self.data['Zmin']
563        Zmax = self.data['Zmax']
564        Zeros = self.data['Zeros']
565        Lines = []
566           
567#        MA = ma.masked_greater(ma.masked_less(self.Image.T,Zmin),Zmax)
568#        MaskA = ma.getmaskarray(MA)
569#        ImgM = Plot.imshow(MaskA,aspect='auto',cmap='Reds',
570#            interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,0,Ymax])
571        Img = Plot.imshow(self.Image.T-Zmin,interpolation='nearest',vmin=Imin,vmax=Imax,
572            aspect='auto',cmap=self.data['color'],extent=[0,Xmax,0,Ymax])
573        Lines.append(Plot.axvline(Zeros[0],color='b',dashes=(5,5),picker=3.))   
574        Lines.append(Plot.axhline(Zeros[1],color='b',dashes=(5,5),picker=3.))   
575        Lines.append(Plot.axhline(TBlimit[0],color='g',dashes=(5,5),picker=3.))   
576        Lines.append(Plot.axhline(TBlimit[1],color='r',dashes=(5,5),picker=3.))   
577        Lines.append(Plot.axvline(LRlimit[0],color='g',dashes=(5,5),picker=3.))   
578        Lines.append(Plot.axvline(LRlimit[1],color='r',dashes=(5,5),picker=3.))
579        for blk in range(len(self.imagefiles)):
580            Lines.append(Plot.axvline(blk*4096*scalex,color='k'))   
581        Plot.set_title('')
582        Plot.set_xlabel('Scan, mm')
583        Plot.set_ylabel('Detector Y, mm')
584        if xylim:
585            Page.toolbar.push_current()
586            Plot.set_xlim(xylim[0])
587            Plot.set_ylim(xylim[1])
588            xylim = []
589            Page.toolbar.push_current()
590            Page.toolbar.draw()
591        else:
592            Page.canvas.draw()
593           
594    def PlotBlock(self,block,title):
595        try:
596            plotNum = self.plotNB.plotList.index('Block')
597            Page = self.plotNB.nb.GetPage(plotNum)
598            Plot = Page.figure.gca()          #get previous powder plot & get limits
599            xylim = Plot.get_xlim(),Plot.get_ylim()
600            Page.figure.clf()
601            Plot = Page.figure.gca()
602            if not Page.IsShown():
603                Page.Show()
604        except ValueError:
605            Plot = self.plotNB.addMpl('Block').gca()
606            plotNum = self.plotNB.plotList.index('Block')
607            Page = self.plotNB.nb.GetPage(plotNum)
608            xylim = []
609        Img = Plot.imshow(block,interpolation='nearest',aspect='equal',cmap=self.data['color'])
610        Plot.invert_yaxis()
611        Plot.set_title(title)
612        if xylim:
613            Page.toolbar.push_current()
614            Plot.set_xlim(xylim[0])
615            Plot.set_ylim(xylim[1])
616            xylim = []
617            Page.toolbar.push_current()
618            Page.toolbar.draw()
619        else:
620            Page.canvas.draw()
621                   
622    def PlotXY(self,XY,newPlot=False,type=''):
623        '''simple plot of xy data, used for diagnostic purposes
624        '''
625        def OnMotion(event):
626            xpos = event.xdata
627            if xpos:                                        #avoid out of frame mouse position
628                ypos = event.ydata
629                Page.canvas.SetCursor(wx.CROSS_CURSOR)
630                try:
631                    self.plotNB.status.SetStatusText('X =%9.3f %s =%9.3f'%(xpos,type,ypos),1)                   
632                except TypeError:
633                    self.plotNB.status.SetStatusText('Select '+type+' pattern first',1)
634   
635        try:
636            plotNum = self.plotNB.plotList.index(type)
637            Page = self.plotNB.nb.GetPage(plotNum)
638            if not newPlot:
639                Plot = Page.figure.gca()
640                xylim = Plot.get_xlim(),Plot.get_ylim()
641            Page.figure.clf()
642            Plot = Page.figure.gca()
643        except ValueError:
644            newPlot = True
645            Plot = self.plotNB.addMpl(type).gca()
646            plotNum = self.plotNB.plotList.index(type)
647            Page = self.plotNB.nb.GetPage(plotNum)
648            Page.canvas.mpl_connect('motion_notify_event', OnMotion)
649       
650        Page.SetFocus()
651        self.plotNB.status.DestroyChildren()
652        Plot.set_title(type)
653        if type == 'line scan':
654            Plot.set_xlabel(r'image x, mm',fontsize=14)
655        else:
656            Plot.set_xlabel(r'2-theta, deg',fontsize=14)           
657        Plot.set_ylabel(r''+type,fontsize=14)
658        colors=['b','g','r','c','m','k']
659        lenX = 0
660        X,Y,S = XY
661        Plot.plot(X,Y,'k',picker=False)
662        Plot.plot(X,S,'r',picker=False)
663        if not newPlot:
664            Page.toolbar.push_current()
665            Plot.set_xlim(xylim[0])
666            Plot.set_ylim(xylim[1])
667            xylim = []
668            Page.toolbar.push_current()
669            Page.toolbar.draw()
670        else:
671            Page.canvas.draw()
672
673class scanCCDmain(wx.App):
674    def OnInit(self):
675        self.main = scanCCD(None)
676        self.main.Show()
677        self.SetTopWindow(self.main)
678        return True
679
680def main():
681    application = scanCCDmain(0)
682    application.MainLoop()
683   
684if __name__ == '__main__':
685    main()
Note: See TracBrowser for help on using the repository browser.