Coverage for larch/wxxrd/XRD2Dviewer.py: 12%
836 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
1#!/usr/bin/env python3
2'''
3GUI for displaying 2D XRD images
5'''
6import os
7import numpy as np
9import matplotlib.cm as colormap
10from functools import partial
12import h5py
14import wx
15try:
16 from wx._core import PyDeadObjectError
17except:
18 PyDeadObjectError = Exception
20from wxmplot import PlotPanel
21from wxmplot.imagepanel import ImagePanel
22from wxutils import MenuItem
23from wxmplot.imageconf import ImageConfig,ColorMap_List
25# import matplotlib.pyplot as plt
27import larch
28from larch import Group
29from larch.larchlib import read_workdir, save_workdir
30from larch.utils.strutils import bytes2str
31from larch.utils import get_cwd
32from larch.wxlib import LarchWxApp
33from larch.io import tifffile
34from larch.xrd import (integrate_xrd,E_from_lambda,xrd1d,read_lambda,
35 calc_cake,twth_from_q,twth_from_d,
36 return_ai,twth_from_xy,q_from_xy,eta_from_xy)
37from .XRDCalibrationFrame import CalibrationPopup
38from .XRDMaskFrame import MaskToolsPopup
39# from .XRD1Dviewer import Calc1DPopup
41###################################
43VERSION = '2 (14-March-2018)'
44SLIDER_SCALE = 1000. ## sliders step in unit 1. this scales to 0.001
45PIXELS = 1024 #2048
47QSTPS = 5000
49XLABEL = ['q','2th','d']
50XUNIT = [u'q (\u212B\u207B\u00B9)',u'2\u03B8 (\u00B0)',u'd (\u212B)']
52###################################
54class diFFit2DPanel(wx.Panel):
55 '''
56 Panel for housing 2D XRD Image
57 '''
58 label='2D XRD'
59 def __init__(self,parent,type='2D image',owner=None,_larch=None,size=(500, 500)):
61 wx.Panel.__init__(self, parent)
62 self.owner = owner
63 self.type = type
64 self.ai = None
65 self.on_calibration()
67 vbox = wx.BoxSizer(wx.VERTICAL)
68 self.plot2D = ImagePanel(self,size=size,messenger=self.owner.write_message)
69 vbox.Add(self.plot2D,proportion=1,flag=wx.ALL|wx.EXPAND,border = 10)
70 self.SetSizer(vbox)
72 self.plot2D.cursor_callback = self.on_cursor
75 def on_calibration(self):
77 if self.owner.calfile is not None and os.path.exists(self.owner.calfile):
78 self.ai = return_ai(self.owner.calfile)
80 self.ai.detector.shape = np.shape(self.owner.plt_img)
82 fit2d_param = self.ai.getFit2D()
83 self.center = (fit2d_param['centerX'],fit2d_param['centerY'])
85 def on_cursor(self,x=None, y=None, **kw):
87 if self.ai is not None:
88 if self.type == 'cake':
89 self.owner.twth = self.plot2D.xdata[int(x)]
91 self.owner.xrd2Dcake.plot_line(x=x)
92 self.owner.xrd2Dviewer.plot_ring()
93 else:
94 self.owner.twth = twth_from_xy(x,y,ai=self.ai)
96 self.owner.xrd2Dviewer.plot_ring(x=x,y=y)
97 self.owner.xrd2Dcake.plot_line()
98 else:
99 return
101 self.owner.xrd1Dviewer.plot_line()
103 def plot_line(self,x=None):
105 if x is None: x = np.abs(self.plot2D.xdata-self.owner.twth).argmin()
107 try:
108 self.xrd_line.remove()
109 except:
110 pass
112 self.xrd_line = self.plot2D.axes.axvline(x=x, color='r', linewidth=1)
113 self.plot2D.canvas.draw()
115 def plot_ring(self,x=None,y=None):
116 import matplotlib.pyplot as plt
117 if x is not None and y is not None:
118 radius = np.sqrt((x-self.center[0])**2+(y-self.center[1])**2)
119 else:
120 radius = self.ai._dist * np.tan(np.radians(self.owner.twth))
121 radius = radius / self.ai.detector.pixel1
122 xrd_ring = plt.Circle(self.center, radius, color='red', fill=False)
124 try:
125 self.xrd_ring.remove()
126 except:
127 pass
129 self.xrd_ring = self.plot2D.axes.add_artist(xrd_ring)
130 self.plot2D.canvas.draw()
132class diFFit1DPanel(wx.Panel):
133 '''
134 Panel for housing 1D XRD
135 '''
136 def __init__(self,parent,owner=None,_larch=None,size=(500, 100)):
138 wx.Panel.__init__(self, parent)
139 self.owner = owner
141 vbox = wx.BoxSizer(wx.VERTICAL)
142 self.plot1D = PlotPanel(self,size=size,messenger=self.owner.write_message)
143 vbox.Add(self.plot1D,proportion=1,flag=wx.ALL|wx.EXPAND,border = 10)
144 self.SetSizer(vbox)
146 self.plot1D.cursor_callback = self.on_cursor
148 def on_cursor(self,x=None, y=None, **kw):
150 xi = self.owner.xaxis_type.GetSelection()
151 if xi == 1:
152 self.owner.twth = x
153 else:
154 ix = np.abs(self.owner.data1dxrd[1]-self.owner.twth).argmin()
155 self.owner.twth = self.owner.data1dxrd[1][ix]
157 self.owner.xrd1Dviewer.plot_line(x=x)
158 self.owner.xrd2Dviewer.plot_ring()
159 self.owner.xrd2Dcake.plot_line()
161 def plot_line(self,x=None):
163 if x is None:
164 xi = self.owner.xaxis_type.GetSelection()
165 if xi != 1:
166 ix = np.abs(self.owner.data1dxrd[1]-self.owner.twth).argmin()
167 x = self.owner.data1dxrd[xi][ix]
168 else:
169 x = self.owner.twth
171 try:
172 self.xrd_line.remove()
173 except:
174 pass
176 self.xrd_line = self.plot1D.axes.axvline(x=x, color='r', linewidth=1)
177 self.plot1D.draw()
181class XRD2DViewerFrame(wx.Frame):
182 '''
183 Frame for housing all 2D XRD viewer widgets
184 '''
185 def __init__(self, _larch=None, xrd1Dviewer=None, ponifile=None, flip='vertical',
186 *args, **kw):
188 screenSize = wx.DisplaySize()
189 x,y = 1000,720 #1000,760
190 if x > screenSize[0] * 0.9:
191 x = int(screenSize[0] * 0.9)
192 y = int(x*0.6)
194 label = 'diFFit : 2D XRD Data Analysis Software'
195 wx.Frame.__init__(self, None,title=label, size=(x,y))
197 self.SetMinSize((700,500))
199 self.statusbar = self.CreateStatusBar(3,wx.CAPTION)
201 self.open_image = []
202 self.open_scale = []
204 ## Default image information
205 self.raw_img = np.zeros((PIXELS,PIXELS))
206 self.flp_img = np.zeros((PIXELS,PIXELS))
207 self.plt_img = np.zeros((PIXELS,PIXELS))
208 self.cake = None
209 self.twth = None
211 self.calfile = ponifile
213 self.msk_img = np.ones((PIXELS,PIXELS))
214 self.bkgd_img = np.zeros((PIXELS,PIXELS))
216 self.bkgd_scale = 0
217 self.bkgdMAX = 2
219 self.use_mask = False
220 self.use_bkgd = False
222 self.xrddisplay1D = xrd1Dviewer
224 self.xrd1Dviewer = None
225 self.xrd2Dcake = None
227 self.color = 'bone'
228 self.flip = flip
230 read_workdir('gsemap.dat')
232 self.XRD2DMenuBar()
233 self.Panel2DViewer()
235 self.Centre()
236 self.Show()
238 if ponifile is None:
239 self.btn_integ.Disable()
240 else:
241 self.btn_integ.Enable()
243 def write_message(self, s, panel=0):
244 '''write a message to the Status Bar'''
245 self.SetStatusText(s, panel)
247 def optionsON(self):
249 if len(self.open_image) > 0:
251 self.ch_clr.Enable()
252 self.sldr_cntrst.Enable()
253 self.entr_min.Enable()
254 self.entr_max.Enable()
255 self.btn_ct1.Enable()
256 self.ch_flp.Enable()
257 self.ch_scl.Enable()
258 self.btn_mask.Enable()
259 self.btn_bkgd.Enable()
261 img_no = self.ch_img.GetSelection()
262 if self.open_image[img_no].iframes > 1:
263 self.hrz_frm_sldr.Enable()
264 self.hrz_frm_sldr.SetRange(0, int(self.open_image[img_no].iframes-1))
265 self.hrz_frm_sldr.SetValue(int(self.open_image[img_no].i))
266 for btn in self.hrz_frm_btn: btn.Enable()
267 else:
268 self.hrz_frm_sldr.Disable()
269 self.hrz_frm_sldr.SetRange(0,0)
270 self.hrz_frm_sldr.SetValue(0)
271 for btn in self.hrz_frm_btn: btn.Disable()
273 if self.open_image[img_no].jframes > 1:
274 self.vrt_frm_sldr.Enable()
275 self.vrt_frm_sldr.SetRange(0,int(self.open_image[img_no].jframes-1))
276 self.vrt_frm_sldr.SetValue(int(self.open_image[img_no].j))
277 for btn in self.vrt_frm_btn: btn.Enable()
278 else:
279 self.vrt_frm_sldr.Disable()
280 self.vrt_frm_sldr.SetRange(0,0)
281 self.vrt_frm_sldr.SetValue(0)
282 for btn in self.vrt_frm_btn: btn.Disable()
284##############################################
285#### OPENING AND DISPLAYING IMAGES
287 def loadIMAGE(self,event=None):
288 wildcards = '2DXRD image files (*.*)|*.*|All files (*.*)|*.*'
289 dlg = wx.FileDialog(self, message='Choose 2D XRD image',
290 defaultDir=get_cwd(),
291 wildcard=wildcards, style=wx.FD_OPEN)
293 path, read = '', False
294 if dlg.ShowModal() == wx.ID_OK:
295 read = True
296 path = dlg.GetPath().replace('\\', '/')
297 dlg.Destroy()
299 if read:
300 print('\nReading XRD image file: %s' % path)
302 image,xrmfile = None,None
303 try:
304 xrmfile = h5py.File(path, 'r')
305 except IOError:
306 try:
307 from larch.io import read_xrd_netcdf
308 image = read_xrd_netcdf(path)
309 except TypeError:
310 try:
311 image = tifffile.imread(path)
312 except ValueError:
313 print('Could not read file.')
314 return
316 iname = os.path.split(path)[-1]
317 self.plot2Dxrd(iname, image, path=path, h5file=xrmfile)
319 def close2Dxrd(self,event=None):
321 img_no = self.ch_img.GetSelection()
322 try:
323 print('Closing XRD image file: %s' % self.open_image[img_no].path)
324 try:
325 self.open_image[img_no].h5file.close()
326 except:
327 pass
328 del self.open_image[img_no]
329 except:
330 pass
332 self.ch_img.Set([image.label for image in self.open_image])
333 if len(self.open_image) > 0:
334 self.ch_img.SetSelection(0)
335 self.selectIMAGE()
336 else:
337 self.clearIMAGE()
340 def plot2Dxrd(self,iname,image,path='',h5file=None):
342 self.write_message('Displaying image: %s' % iname, panel=0)
344 try:
345 new_img = XRDImg(label=iname, path=path, image=image, h5file=h5file)
346 except:
347 fail_msg = 'Image failed to load.'
348 self.write_message(fail_msg, panel=0)
349 print (fail_msg)
350 return
352 self.open_image.append(new_img)
354 if self.open_image[-1].calfile is not None:
355 if os.path.exists(self.open_image[-1].calfile):
356 self.calfile = self.open_image[-1].calfile
357 self.xrd2Dviewer.on_calibration()
360 self.ch_img.Set([image.label for image in self.open_image])
361 self.ch_img.SetStringSelection(iname)
363 self.raw_img = self.open_image[-1].get_image()
364 self.twth = None
365 self.displayIMAGE(auto_contrast=True,unzoom=True)
367 if self.open_image[-1].iframes > 1:
368 self.hrz_frm_sldr.SetRange(0,(self.open_image[-1].iframes-1))
369 self.hrz_frm_sldr.SetValue(int(self.open_image[-1].i))
370 else:
371 self.hrz_frm_sldr.Disable()
372 for btn in self.hrz_frm_btn: btn.Disable()
374 if self.open_image[-1].jframes > 1:
375 self.vrt_frm_sldr.SetRange(0,(self.open_image[-1].jframes-1))
376 self.vrt_frm_sldr.SetValue(int(self.open_image[-1].j))
377 else:
378 self.vrt_frm_sldr.Disable()
379 for btn in self.vrt_frm_btn: btn.Disable()
382 def changeFRAME(self,flag='hslider',event=None):
384 img_no = self.ch_img.GetSelection()
385 if self.open_image[img_no].iframes > 1 or self.open_image[img_no].jframes > 1:
386 i,j = self.open_image[img_no].i,self.open_image[img_no].j
387 if flag=='next': i = i + 1
388 elif flag=='previous': i = i - 1
389 elif flag=='hslider': i = self.hrz_frm_sldr.GetValue()
390 elif flag=='up': j = j + 1
391 elif flag=='down': j = j - 1
392 elif flag=='vslider': j = self.vrt_frm_sldr.GetValue()
394 if i < 0: i = self.open_image[img_no].iframes + i
395 if j < 0: j = self.open_image[img_no].jframes + j
396 if i > self.open_image[img_no].iframes: i = i - self.open_image[img_no].iframes
397 if j > self.open_image[img_no].jframes: j = j - self.open_image[img_no].jframes
399 self.raw_img = self.open_image[img_no].get_image(i=i,j=j)
401 self.hrz_frm_sldr.SetValue(i)
402 self.vrt_frm_sldr.SetValue(j)
403 self.displayIMAGE(auto_contrast=False,unzoom=False)#unzoom=True)
405 def clearIMAGE(self):
407 try:
408 self.xrd2Dviewer.plot2D.clear()
409 self.xrd2Dviewer.plot2D.redraw()
410 except:
411 pass
413 def displayIMAGE(self,auto_contrast=True,unzoom=False):
415 self.flipIMAGE()
416 self.checkIMAGE()
417 self.calcIMAGE()
419 if unzoom:
420 self.xrd2Dviewer.plot2D.display(self.plt_img,unzoom=unzoom)
421 else:
422 self.xrd2Dviewer.plot2D.conf.data = self.plt_img
423 self.xrd2Dviewer.plot2D.redraw()
424 self.display1DXRD()
426 if auto_contrast: self.setContrast(auto_contrast=True)
428 self.txt_ct2.SetLabel('[ image range: %i to %i ]' %
429 (np.min(self.plt_img),np.max(self.plt_img)))
431 self.optionsON()
432 self.xrd2Dviewer.plot2D.redraw()
434 def redrawIMAGE(self,unzoom=False):
436 self.flipIMAGE()
437 self.checkIMAGE()
438 self.calcIMAGE()
439 self.colorIMAGE()
441 self.xrd2Dviewer.plot2D.redraw()
442 self.display1DXRD()
444 def selectIMAGE(self,event=None):
446 img_no = self.ch_img.GetSelection()
447 self.raw_img = self.open_image[img_no].get_image()
449 self.write_message('Displaying image: %s' % self.open_image[img_no].label, panel=0)
450 try:
451 self.displayIMAGE(auto_contrast=False,unzoom=True)
452 self.setContrast()
453 except:
454 self.write_message('Image failed to load.', panel=0)
456 def onChangeXscale(self,event=None):
458 xi = self.xaxis_type.GetSelection()
460 self.xrd1Dviewer.plot1D.update_line(0, self.data1dxrd[xi],self.data1dxrd[3])
461 if self.twth is not None: self.xrd1Dviewer.plot_line()
462 self.xrd1Dviewer.plot1D.set_viewlimits()
463 self.xrd1Dviewer.plot1D.set_xlabel(XUNIT[xi])
464 if xi == 2: self.xrd1Dviewer.plot1D.axes.set_xlim(np.min(self.data1dxrd[xi]), 6)
465 self.xrd1Dviewer.plot1D.draw()
468##############################################
469#### IMAGE DISPLAY FUNCTIONS
471 def calcIMAGE(self):
472 if self.use_mask is True:
473 if self.use_bkgd is True:
474 self.plt_img = self.flp_img * self.msk_img - self.bkgd_img * self.bkgd_scale
475 else:
476 self.plt_img = self.flp_img * self.msk_img
477 else:
478 if self.use_bkgd is True:
479 self.plt_img = self.flp_img - self.bkgd_img * self.bkgd_scale
480 else:
481 self.plt_img = self.flp_img
483 def flipIMAGE(self):
484 if self.flip == 'vertical': # Vertical
485 self.flp_img = self.raw_img[::-1,:]
486 elif self.flip == 'horizontal': # Horizontal
487 self.flp_img = self.raw_img[:,::-1]
488 elif self.flip == 'both': # both
489 self.flp_img = self.raw_img[::-1,::-1]
490 else: # None
491 self.flp_img = self.raw_img
493 def checkIMAGE(self):
494 ## Reshapes/replaces mask and/or background if shape doesn't match that of image
495 if self.msk_img.shape != self.raw_img.shape:
496 self.msk_img = np.ones(self.raw_img.shape)
497 if self.bkgd_img.shape != self.raw_img.shape:
498 self.bkgd_img = np.zeros(self.raw_img.shape)
500 ## Calculates the number of pixels in image, masked pixels, and background pixels
501 img_pxls = self.raw_img.shape[0]*self.raw_img.shape[1]
502 msk_pxls = img_pxls - int(sum(sum(self.msk_img)))
503 bkgd_pxls = int(sum(sum(self.bkgd_img)))
505 ## Enables mask checkbox.
506 if msk_pxls == 0 or msk_pxls == img_pxls:
507 self.ch_msk.Disable()
508 self.msk_img = np.ones(self.raw_img.shape)
509 else:
510 self.ch_msk.Enable()
512 ## Enables background slider and sets range.
513 if bkgd_pxls == 0:
514 self.sldr_bkgd.Disable()
515 self.use_bkgd = False
516 else:
517 self.sldr_bkgd.Enable()
518 self.use_bkgd = True
520 self.sldr_bkgd.SetRange(0, int(self.bkgdMAX*SLIDER_SCALE))
521 self.sldr_bkgd.SetValue(int(self.bkgd_scale*SLIDER_SCALE))
523 def colorIMAGE(self,unzoom=False):
524 self.xrd2Dviewer.plot2D.conf.cmap[0] = getattr(colormap, self.color)
525 self.xrd2Dviewer.plot2D.display(self.plt_img) #,unzoom=unzoom)
527 if self.cake is not None:
528 self.xrd2Dcake.plot2D.conf.cmap[0] = getattr(colormap, self.color)
529 self.xrd2Dcake.plot2D.display(self.cake[0]) #,unzoom=unzoom)
531 def setCOLOR(self,event=None):
532 if self.color != self.ch_clr.GetString(self.ch_clr.GetSelection()):
533 self.color = self.ch_clr.GetString(self.ch_clr.GetSelection())
534 self.colorIMAGE()
536 def setFLIP(self,event=None):
538 if self.flip != self.ch_flp.GetString(self.ch_flp.GetSelection()):
539 self.flip = self.ch_flp.GetString(self.ch_flp.GetSelection())
540 self.redrawIMAGE(unzoom=False)
542 def setZSCALE(self,event=None):
543 if self.ch_scl.GetSelection() == 1: ## log
544 self.xrd2Dviewer.plot2D.conf.log_scale = True
545 if self.xrd2Dcake is not None:
546 self.xrd2Dcake.plot2D.conf.log_scale = True
547 if self.xrd1Dviewer is not None:
548 self.xrd1Dviewer.plot1D.axes.set_yscale('log')
549 self.xrd1Dviewer.plot1D.set_viewlimits()
550 self.xrd1Dviewer.plot1D.draw()
551 else: ## linear
552 self.xrd2Dviewer.plot2D.conf.log_scale = False
553 if self.xrd2Dcake is not None:
554 self.xrd2Dcake.plot2D.conf.log_scale = False
555 if self.xrd1Dviewer is not None:
556 self.xrd1Dviewer.plot1D.axes.set_yscale('linear')
557 self.xrd1Dviewer.plot1D.set_viewlimits()
558 self.xrd1Dviewer.plot1D.draw()
560 self.xrd2Dviewer.plot2D.redraw()
561 if self.cake is not None:
562 self.xrd2Dcake.plot2D.redraw()
565##############################################
566#### BACKGROUND FUNCTIONS
567 def onBkgdScale(self,event=None):
568 self.bkgd_scale = self.sldr_bkgd.GetValue()/SLIDER_SCALE
569 self.redrawIMAGE(unzoom=False)
571##############################################
572#### IMAGE CONTRAST FUNCTIONS
574 def onContrastRange(self,event=None):
576 img_no = self.ch_img.GetSelection()
577 img = self.open_image[img_no]
579 img.minval = int(self.entr_min.GetValue())
580 img.maxval = int(self.entr_max.GetValue())
582 self.setContrast()
585 def onSlider(self,event=None):
587 img_no = self.ch_img.GetSelection()
588 img = self.open_image[img_no]
590 curval = int(self.sldr_cntrst.GetValue())
592 self.xrd2Dviewer.plot2D.conf.auto_intensity = False
593 self.xrd2Dviewer.plot2D.conf.int_lo[0] = img.minval
594 self.xrd2Dviewer.plot2D.conf.int_hi[0] = curval
595 self.xrd2Dviewer.plot2D.redraw()
597 if self.cake is not None:
598 self.xrd2Dcake.plot2D.conf.auto_intensity = False
599 self.xrd2Dcake.plot2D.conf.int_lo[0] = img.minval
600 self.xrd2Dcake.plot2D.conf.int_hi[0] = curval
601 self.xrd2Dcake.plot2D.redraw()
603 def setContrast(self,event=None,auto_contrast=False):
604 img_no = self.ch_img.GetSelection()
605 img = self.open_image[img_no]
607 if auto_contrast: img.set_contrast(np.min(self.plt_img),np.max(self.plt_img))
609 self.xrd2Dviewer.plot2D.conf.auto_intensity = False
610 self.xrd2Dviewer.plot2D.conf.int_lo[0] = img.minval
611 if auto_contrast:
612 self.xrd2Dviewer.plot2D.conf.int_hi[0] = img.maxval*0.4
613 else:
614 self.xrd2Dviewer.plot2D.conf.int_hi[0] = img.maxval
615 self.xrd2Dviewer.plot2D.redraw()
617 self.sldr_cntrst.SetRange(int(img.minval), int(img.maxval))
618 if auto_contrast:
619 self.sldr_cntrst.SetValue(int(img.maxval*0.4))
620 else:
621 self.sldr_cntrst.SetValue(int(img.maxval))
622 self.entr_min.SetValue('%i' % img.minval)
623 self.entr_max.SetValue('%i' % img.maxval)
625 if self.cake is not None:
626 self.xrd2Dcake.plot2D.conf.auto_intensity = False
627 self.xrd2Dcake.plot2D.conf.int_lo[0] = img.minval
628 if auto_contrast:
629 self.xrd2Dcake.plot2D.conf.int_hi[0] = img.maxval*0.4
630 else:
631 self.xrd2Dcake.plot2D.conf.int_hi[0] = img.maxval
632 self.xrd2Dcake.plot2D.redraw()
635##############################################
636#### XRD MANIPULATION FUNTIONS
638 def saveIMAGE(self,event=None,raw=False):
639 wildcards = 'XRD image (*.tiff)|*.tiff|All files (*.*)|*.*'
640 dlg = wx.FileDialog(self, 'Save image as...',
641 defaultDir=get_cwd(),
642 wildcard=wildcards,
643 style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
645 path, save = None, False
646 if dlg.ShowModal() == wx.ID_OK:
647 save = True
648 path = dlg.GetPath().replace('\\', '/')
649 dlg.Destroy()
651 if save:
652 if raw:
653 tifffile.imsave(path,self.raw_img)
654 else:
655 tifffile.imsave(path,self.plt_img)
657 def on1DXRD(self,event=None):
658 pass
659 """ read, save, plot = False, False, False
660 if self.calfile is not None and self.plt_img is not None:
661 myDlg = Calc1DPopup(self,self.plt_img)
662 if myDlg.ShowModal() == wx.ID_OK:
663 read = True
664 save = myDlg.ch_save.GetValue()
665 plot = myDlg.ch_plot.GetValue()
666 unts = myDlg.save_choice.GetSelection()
667 wdgs = myDlg.wedges.GetValue()
668 if int(myDlg.xstep.GetValue()) < 1:
669 attrs = {'steps':5001}
670 else:
671 attrs = {'steps':int(myDlg.xstep.GetValue())}
672 unit = '2th' if unts == 1 else 'q'
673 attrs.update({'unit':unit,'verbose':True})
674 myDlg.Destroy()
675 else:
676 print('Data and calibration files must be available for this function.')
677 return
679 if read:
680 if save:
681 wildcards = '1D XRD file (*.xy)|*.xy|All files (*.*)|*.*'
682 dlg = wx.FileDialog(self, 'Save file as...',
683 defaultDir=get_cwd(),
684 wildcard=wildcards,
685 style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
686 if dlg.ShowModal() == wx.ID_OK:
687 filename = dlg.GetPath().replace('\\', '/')
688 if not filename.endswith('.xy'):
689 filename = '%s.xy' % filename
690 attrs.update({'file':filename})
692 dlg.Destroy()
693 data1D = integrate_xrd(self.plt_img,self.calfile,**attrs)
694 if wdgs > 1:
695 xrdq_wdg,xrd1d_wdg,lmts_wdg = [],[],[]
696 wdg_sz = 360./int(wdgs)
697 for iwdg in range(wdgs):
698 wdg_lmts = np.array([iwdg*wdg_sz, (iwdg+1)*wdg_sz]) - 180
699 attrs.update({'wedge_limits':wdg_lmts})
701 if save:
702 wedgename = '%s_%i_to_%ideg.xy' % (filename.split('.xy')[0],
703 (wdg_lmts[0]+180),
704 (wdg_lmts[1]+180))
705 attrs.update({'file':wedgename})
706 q,counts = integrate_xrd(self.plt_img,self.calfile,**attrs)
707 xrdq_wdg += [q]
708 xrd1d_wdg += [counts]
709 lmts_wdg += [wdg_lmts]
712 if plot:
713 if self.xrddisplay1D is None:
714 self.xrddisplay1D = diFFit1DFrame()
716 kwargs = {}
717 wvlngth = read_lambda(self.calfile)
718 kwargs.update({'wavelength':wvlngth,'energy':E_from_lambda(wvlngth)})
719 kwargs.update({'label':self.open_image[self.ch_img.GetSelection()].label})
720 data1dxrd = xrd1d(**kwargs)
721 data1dxrd.xrd_from_2d(data1D,attrs['unit'])
723 try:
724 self.xrddisplay1D.xrd1Dviewer.add1Ddata(data1dxrd)
725 except PyDeadObjectError:
726 self.xrddisplay1D = diFFit1DFrame()
727 self.xrddisplay1D.xrd1Dviewer.add1Ddata(data1dxrd)
729 if wdgs > 1:
730 for lmts,q,cnts in zip(lmts_wdg,xrdq_wdg,xrd1d_wdg):
731 label = '%s (%i to %i deg)' % (self.open_image[self.ch_img.GetSelection()].label,
732 (lmts[0]+180), (lmts[1]+180))
733 kwargs.update({'label':label})
734 data1dxrd = xrd1d(**kwargs)
735 data1dxrd.xrd_from_2d([q,cnts],'q')
736 self.xrddisplay1D.xrd1Dviewer.add1Ddata(data1dxrd)
737 self.xrddisplay1D.Show()
738 """
742##############################################
743#### CALIBRATION FUNCTIONS
744 def display1DXRD(self,event=None):
746 if len(self.open_image) > 0 and self.calfile is not None:
748 if self.xrd2Dcake is None or self.xrd1Dviewer is None:
749 rightside = self.RightSidePanel(self.panel)
750 self.panel2D.Add(rightside,proportion=1,flag=wx.EXPAND|wx.ALL,border=10)
751 self.panel2D.Layout()
752 self.Fit()
753 self.SetSize((1400,720))
755 tools1dxrd = self.ToolBox_1DXRD(self.panel)
756 self.leftside.Add(tools1dxrd,flag=wx.ALL|wx.EXPAND,border=10)
757 self.leftside.Layout()
759 self.panel2D.Layout()
760 self.Fit()
761 self.SetSize((1400,720))
763 self.btn_integ.Enable()
765 ## Cake calculations
766 xi = 1
767 self.xaxis_type.SetSelection(xi)
769 self.cake = calc_cake(self.plt_img, self.calfile, unit=XLABEL[xi], xsteps=QSTPS, ysteps=QSTPS)
770 self.xrd2Dcake.plot2D.display(self.cake[0],x=self.cake[1],y=self.cake[2],
771 xlabel=XLABEL[xi],ylabel='eta')
772 self.xrd2Dcake.plot2D.conf.auto_intensity = False
773 self.xrd2Dcake.plot2D.conf.int_lo[0] = self.xrd2Dviewer.plot2D.conf.int_lo[0]
774 self.xrd2Dcake.plot2D.conf.int_hi[0] = self.xrd2Dviewer.plot2D.conf.int_hi[0]
775 self.xrd2Dcake.plot2D.redraw()
777 ## 1DXRD calculations
779 q,I = integrate_xrd(self.plt_img, self.calfile, unit=XLABEL[xi], steps=QSTPS)
780 self.data1dxrd = xrd1d(x=q,xtype=XLABEL[xi],I=I).all_data()
782 self.xrd1Dviewer.plot1D.plot(self.data1dxrd[xi],self.data1dxrd[3],color='blue',
783 xlabel=XUNIT[xi])
784 self.xrd1Dviewer.plot1D.axes.yaxis.set_visible(False)
785 self.xrd1Dviewer.plot1D.axes.spines['left'].set_visible(False)
786 self.xrd1Dviewer.plot1D.axes.spines['right'].set_visible(False)
787 self.xrd1Dviewer.plot1D.axes.spines['top'].set_visible(False)
788 self.xrd1Dviewer.plot1D.draw()
791 def Calibrate(self,event=None):
793 CalibrationPopup(self)
795 def openPONI(self,event=None):
797 wildcards = 'pyFAI calibration file (*.poni)|*.poni|All files (*.*)|*.*'
798 dlg = wx.FileDialog(self, message='Choose pyFAI calibration file',
799 defaultDir=get_cwd(),
800 wildcard=wildcards, style=wx.FD_OPEN)
802 path, read = None, False
803 if dlg.ShowModal() == wx.ID_OK:
804 read = True
805 path = dlg.GetPath().replace('\\', '/')
806 dlg.Destroy()
808 if read:
809 print('Loading calibration file:\n\t%s' % path)
810 self.calfile = path
811 self.xrd2Dviewer.on_calibration()
812 self.display1DXRD()
815##############################################
816#### BACKGROUND FUNCTIONS
817 def clearBkgd(self,event=None):
819 self.bkgd = np.zeros(self.raw_img.shape)
820 self.checkIMAGE()
822 def openBkgd(self,event=None):
824 wildcards = 'XRD background image (*.edf,*.tif,*.tiff)|*.tif;*.tiff;*.edf|All files (*.*)|*.*'
825 dlg = wx.FileDialog(self, message='Choose XRD background image',
826 defaultDir=get_cwd(),
827 wildcard=wildcards, style=wx.FD_OPEN)
829 path, read = None, False
830 if dlg.ShowModal() == wx.ID_OK:
831 read = True
832 path = dlg.GetPath().replace('\\', '/')
833 dlg.Destroy()
835 if read:
836 try:
837 self.bkgd_img = np.array(tifffile.imread(path))
838 self.checkIMAGE()
839 print('Reading background:\n\t%s' % path)
840 except:
841 print('\nCannot read as an image file: %s\n' % path)
842 return
845##############################################
846#### MASK FUNCTIONS
847 def openMask(self,event=None):
849 wildcards = 'pyFAI mask file (*.edf)|*.edf|All files (*.*)|*.*'
850 dlg = wx.FileDialog(self, message='Choose pyFAI mask file',
851 defaultDir=get_cwd(),
852 wildcard=wildcards, style=wx.FD_OPEN)
854 path, read = None, False
855 if dlg.ShowModal() == wx.ID_OK:
856 read = True
857 path = dlg.GetPath().replace('\\', '/')
858 dlg.Destroy()
860 if read:
861 try:
862 try:
863 raw_mask = np.array(tifffile.imread(path))
864 except:
865 import fabio
866 raw_mask = fabio.open(path).data
867 self.msk_img = np.ones(raw_mask.shape)-raw_mask
868 self.checkIMAGE()
869 print('Reading mask:\n\t%s' % path)
870 except:
871 print('\nCannot read as mask file: %s\n' % path)
872 return
874 self.ch_msk.SetValue(True)
875 self.applyMask(event=True)
877# def createMask(self,event=None):
878#
879# MaskToolsPopup(self)
880# print('Popup to create mask!')
882 def clearMask(self,event=None):
884 self.msk_img = np.zeros(self.raw_img.shape)
885 self.checkIMAGE()
887 def applyMask(self,event=None):
889 self.use_mask = self.ch_msk.GetValue()
890 self.redrawIMAGE(unzoom=False)
892##############################################
893#### HELP FUNCTIONS
894 def onAbout(self, event=None):
895 info = wx.AboutDialogInfo()
896 info.SetName('diFFit2D XRD Data Viewer')
897 desc = 'Using X-ray Larch version: %s' % larch.version.__version__
898 info.SetDescription(desc)
899 info.SetVersion(VERSION)
900 info.AddDeveloper('Margaret Koker: koker at cars.uchicago.edu')
901 dlg = wx.AboutBox(info)
903##############################################
904#### MENU FUNCTIONS
905 def onFolderSelect(self, evt=None):
906 style = wx.DD_DIR_MUST_EXIST|wx.DD_DEFAULT_STYLE
907 dlg = wx.DirDialog(self, 'Select Working Directory:', get_cwd(),
908 style=style)
910 if dlg.ShowModal() == wx.ID_OK:
911 basedir = Path(dlg.GetPath()).absolute().as_posix()
912 try:
913 if len(basedir) > 0:
914 os.chdir(basedir)
915 save_workdir(basedir)
916 except OSError:
917 print( 'Changed folder failed')
918 pass
919 save_workdir('gsemap.dat')
920 dlg.Destroy()
922 def onClose(self, event=None):
923 for image in self.open_image:
924 try:
925 image.h5file.close()
926 except:
927 pass
929 try:
930 self.Destroy()
931 except:
932 pass
935 def onExit(self, event=None):
936 dlg = wx.MessageDialog(None, 'Really Quit?', 'Question',
937 wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
939 ret = dlg.ShowModal()
940 if ret != wx.ID_YES:
941 return
942 self.onClose()
945##############################################
946#### PANEL DEFINITIONS
947 def XRD2DMenuBar(self):
949 menubar = wx.MenuBar()
951 ###########################
952 ## diFFit2D
953 diFFitMenu = wx.Menu()
955 MenuItem(self, diFFitMenu, '&Open diffration image', '', self.loadIMAGE)
956 MenuItem(self, diFFitMenu, 'Sa&ve displayed image to file', '', partial(self.saveIMAGE,raw=False))
957 MenuItem(self, diFFitMenu, 'Save r&aw image to file', '', partial(self.saveIMAGE,raw=True))
958 MenuItem(self, diFFitMenu, 'Change larch &working folder', '', self.onFolderSelect)
960# MenuItem(self, diFFitMenu, '&Save settings', '', None)
961# MenuItem(self, diFFitMenu, '&Load settings', '', None)
962# MenuItem(self, diFFitMenu, 'A&dd analysis to map file', '', None)
963 MenuItem(self, diFFitMenu, '&Quit', 'Quit program', self.onExit)
965 menubar.Append(diFFitMenu, '&diFFit2D')
967 ###########################
968 ## Process
969 ProcessMenu = wx.Menu()
971 MenuItem(self, ProcessMenu, 'Load &mask file', '', self.openMask)
972 MenuItem(self, ProcessMenu, 'Remove current mas&k', '', self.clearMask)
973# MenuItem(self, ProcessMenu, 'C&reate mas&k', '', self.createMask)
974 ProcessMenu.AppendSeparator()
975 MenuItem(self, ProcessMenu, 'Load &background image', '', self.openBkgd)
976 MenuItem(self, ProcessMenu, 'Remove current back&ground image', '', self.clearBkgd)
977 ProcessMenu.AppendSeparator()
978 MenuItem(self, ProcessMenu, 'Close current image', '', self.close2Dxrd)
980 menubar.Append(ProcessMenu, '&Process')
982 ###########################
983 ## Analyze
984 AnalyzeMenu = wx.Menu()
986# MenuItem(self, AnalyzeMenu, '&Calibrate', '', self.Calibrate)
987 MenuItem(self, AnalyzeMenu, 'Load cali&bration file', '', self.openPONI)
988# MenuItem(self, AnalyzeMenu, 'Show current calibratio&n', '', None)
989 AnalyzeMenu.AppendSeparator()
990 MenuItem(self, AnalyzeMenu, '&Integrate (open 1D viewer)', '', self.on1DXRD)
992 menubar.Append(AnalyzeMenu, 'Anal&yze')
994 ###########################
995 ## Help
996 HelpMenu = wx.Menu()
998 MenuItem(self, HelpMenu, '&About', 'About diFFit2D viewer', self.onAbout)
1000 menubar.Append(HelpMenu, '&Help')
1002 ###########################
1003 ## Create Menu Bar
1004 self.SetMenuBar(menubar)
1005 self.Bind(wx.EVT_CLOSE, self.onExit)
1007 def LeftSidePanel(self,panel):
1009 vbox = wx.BoxSizer(wx.VERTICAL)
1011 imgbox = self.ImageBox(self.panel)
1012 vistools = self.Toolbox(self.panel)
1014 vbox.Add(imgbox,flag=wx.ALL|wx.EXPAND,border=10)
1015 vbox.Add(vistools,flag=wx.ALL|wx.EXPAND,border=10)
1017 return vbox
1019 def Panel2DViewer(self):
1020 '''
1021 Frame for housing all 2D XRD viewer widgets
1022 '''
1023 self.panel = wx.Panel(self)
1025 self.leftside = self.LeftSidePanel(self.panel)
1026 center = self.CenterPanel(self.panel)
1027 #rightside = self.RightSidePanel(self.panel)
1029 self.panel2D = wx.BoxSizer(wx.HORIZONTAL)
1030 self.panel2D.Add(self.leftside,flag=wx.ALL,border=10)
1031 self.panel2D.Add(center,proportion=1,flag=wx.EXPAND|wx.ALL,border=10)
1032 #self.panel2D.Add(rightside,proportion=1,flag=wx.EXPAND|wx.ALL,border=10)
1034 self.panel.SetSizer(self.panel2D)
1037 def ToolBox_1DXRD(self,panel):
1039 tlbx = wx.StaticBox(self.panel,label='1DXRD TOOLBOX')
1040 hbox = wx.StaticBoxSizer(tlbx,wx.HORIZONTAL)
1042 ttl_xaxis = wx.StaticText(self, label='X-SCALE')
1043 xunits = [u'q (\u212B\u207B\u00B9)',u'2\u03B8 (\u00B0)',u'd (\u212B)']
1045 self.xaxis_type = wx.Choice(self,choices=xunits)
1046 self.xaxis_type.Bind(wx.EVT_CHOICE, self.onChangeXscale)
1048 hbox.Add(ttl_xaxis, flag=wx.RIGHT, border=8)
1049 hbox.Add(self.xaxis_type, flag=wx.EXPAND, border=8)
1051 return hbox
1053 def ImageBox(self,panel):
1054 '''
1055 Frame for data toolbox
1056 '''
1058 tlbx = wx.StaticBox(self.panel,label='DISPLAYED IMAGE')
1059 vbox = wx.StaticBoxSizer(tlbx,wx.VERTICAL)
1062 ###########################
1063 ## DATA CHOICE
1066 self.ch_img = wx.Choice(self.panel,choices=[])
1067 self.ch_img.Bind(wx.EVT_CHOICE, self.selectIMAGE)
1068 vbox.Add(self.ch_img, flag=wx.EXPAND|wx.ALL, border=8)
1070 self.hrz_frm_sldr = wx.Slider(self.panel, minValue=0, maxValue=100, size=(120,-1),
1071 style = wx.SL_HORIZONTAL|wx.SL_LABELS)
1072 self.vrt_frm_sldr = wx.Slider(self.panel, minValue=0, maxValue=100, size=(-1,120),
1073 style = wx.SL_VERTICAL|wx.SL_LABELS|wx.SL_INVERSE)
1075 self.vrt_frm_btn = [ wx.Button(self.panel,label=u'\u2191', size=(40, -1)),
1076 wx.Button(self.panel,label=u'\u2193', size=(40, -1))]
1077 self.hrz_frm_btn = [ wx.Button(self.panel,label=u'\u2190', size=(40, -1)),
1078 wx.Button(self.panel,label=u'\u2192', size=(40, -1))]
1080 self.hrz_frm_btn[0].Bind(wx.EVT_BUTTON, partial(self.changeFRAME,'previous') )
1081 self.hrz_frm_btn[1].Bind(wx.EVT_BUTTON, partial(self.changeFRAME,'next') )
1082 self.hrz_frm_sldr.Bind(wx.EVT_SLIDER, partial(self.changeFRAME,'hslider') )
1084 self.vrt_frm_btn[0].Bind(wx.EVT_BUTTON, partial(self.changeFRAME,'up') )
1085 self.vrt_frm_btn[1].Bind(wx.EVT_BUTTON, partial(self.changeFRAME,'down') )
1086 self.vrt_frm_sldr.Bind(wx.EVT_SLIDER, partial(self.changeFRAME,'vslider') )
1088 aszr = wx.BoxSizer(wx.HORIZONTAL)
1089 bszr = wx.BoxSizer(wx.VERTICAL)
1090 cszr = wx.BoxSizer(wx.VERTICAL)
1091 dszr = wx.BoxSizer(wx.HORIZONTAL)
1093 aszr.Add(self.hrz_frm_btn[0], flag=wx.RIGHT|wx.CENTER, border=18)
1094 aszr.Add(self.hrz_frm_btn[1], flag=wx.LEFT|wx.CENTER, border=18)
1096 bszr.Add(self.vrt_frm_btn[0], flag=wx.BOTTOM|wx.CENTER, border=8)
1097 bszr.Add(aszr, flag=wx.CENTER, border=8)
1098 bszr.Add(self.vrt_frm_btn[1], flag=wx.TOP|wx.CENTER, border=8)
1100 cszr.Add(bszr, flag=wx.CENTER, border=6)
1101 cszr.Add(self.hrz_frm_sldr, flag=wx.CENTER, border=6)
1103 dszr.AddSpacer(50)
1104 dszr.Add(cszr, flag=wx.CENTER, border=6)
1105 dszr.Add(self.vrt_frm_sldr, flag=wx.CENTER, border=6)
1109 vbox.Add(dszr, flag=wx.EXPAND|wx.CENTER|wx.ALL, border=8)
1111 return vbox
1114 def Toolbox(self,panel):
1115 '''
1116 Frame for visual toolbox
1117 '''
1119 tlbx = wx.StaticBox(self.panel,label='2DXRD TOOLBOX')#, size=(200, 200))
1120 vbox = wx.StaticBoxSizer(tlbx,wx.VERTICAL)
1122 ###########################
1123 ## Color
1124 hbox_clr = wx.BoxSizer(wx.HORIZONTAL)
1125 self.txt_clr = wx.StaticText(self.panel, label='COLOR')
1127 colors = []
1128 for key in colormap.datad:
1129 if not key.endswith('_r'):
1130 colors.append(key)
1131 self.ch_clr = wx.Choice(self.panel,choices=colors)
1132 #self.ch_clr = wx.Choice(self.panel,choices=ColorMap_List)
1134 self.ch_clr.Bind(wx.EVT_CHOICE,self.setCOLOR)
1136 hbox_clr.Add(self.txt_clr, flag=wx.RIGHT, border=6)
1137 hbox_clr.Add(self.ch_clr, flag=wx.RIGHT, border=6)
1138 vbox.Add(hbox_clr, flag=wx.ALL, border=4)
1140 ###########################
1141 ## Contrast
1142 vbox_ct = wx.BoxSizer(wx.VERTICAL)
1144 hbox_ct1 = wx.BoxSizer(wx.HORIZONTAL)
1145 self.txt_ct1 = wx.StaticText(self.panel, label='CONTRAST')
1146 self.txt_ct2 = wx.StaticText(self.panel, label='', size=(175,-1))
1148 hbox_ct1.Add(self.txt_ct1, flag=wx.RIGHT, border=6)
1149 hbox_ct1.Add(self.txt_ct2, flag=wx.RIGHT, border=6)
1150 vbox_ct.Add(hbox_ct1, flag=wx.TOP|wx.BOTTOM, border=4)
1152 hbox_ct2 = wx.BoxSizer(wx.HORIZONTAL)
1154 self.sldr_cntrst = wx.Slider(self.panel, style=wx.SL_LABELS,
1155 size=(275,-1), minValue=0, maxValue=5000000)
1157 self.entr_min = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER, size=(50,-1))
1158 self.entr_max = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER, size=(80,-1))
1160 self.sldr_cntrst.Bind(wx.EVT_SLIDER,self.onSlider)
1161 self.entr_min.Bind(wx.EVT_TEXT_ENTER,self.onContrastRange)
1162 self.entr_max.Bind(wx.EVT_TEXT_ENTER,self.onContrastRange)
1164 self.btn_ct1 = wx.Button(self.panel,label='reset',size=(50,-1))
1166 self.btn_ct1.Bind(wx.EVT_BUTTON,partial(self.setContrast,auto_contrast=True) )
1168 ttl_to = wx.StaticText(self.panel, label='to')
1169 hbox_ct2.Add(self.entr_min, flag=wx.RIGHT, border=6)
1170 hbox_ct2.Add(ttl_to, flag=wx.RIGHT, border=6)
1171 hbox_ct2.Add(self.entr_max, flag=wx.RIGHT, border=6)
1172 hbox_ct2.Add(self.btn_ct1, flag=wx.RIGHT, border=6)
1174 vbox_ct.Add(self.sldr_cntrst, flag=wx.EXPAND|wx.RIGHT, border=6)
1175 vbox_ct.Add(hbox_ct2, flag=wx.CENTER|wx.TOP, border=6)
1176 vbox.Add(vbox_ct, flag=wx.ALL, border=4)
1178 ###########################
1179 ## Flip
1180 hbox_flp = wx.BoxSizer(wx.HORIZONTAL)
1181 self.txt_flp = wx.StaticText(self.panel, label='IMAGE FLIP')
1182 flips = ['none','vertical','horizontal','both']
1183 self.ch_flp = wx.Choice(self.panel,choices=flips)
1185 self.ch_flp.Bind(wx.EVT_CHOICE,self.setFLIP)
1187 hbox_flp.Add(self.txt_flp, flag=wx.RIGHT|wx.TOP|wx.BOTTOM, border=6)
1188 hbox_flp.Add(self.ch_flp, flag=wx.RIGHT|wx.TOP|wx.BOTTOM, border=6)
1189 vbox.Add(hbox_flp, flag=wx.ALL, border=4)
1191 ###########################
1192 ## Scale
1193 hbox_scl = wx.BoxSizer(wx.HORIZONTAL)
1194 self.txt_scl = wx.StaticText(self.panel, label='SCALE')
1195 scales = ['linear','log']
1196 self.ch_scl = wx.Choice(self.panel,choices=scales)
1198 self.ch_scl.Bind(wx.EVT_CHOICE,self.setZSCALE)
1200 hbox_scl.Add(self.txt_scl, flag=wx.RIGHT|wx.TOP|wx.BOTTOM, border=6)
1201 hbox_scl.Add(self.ch_scl, flag=wx.RIGHT|wx.TOP|wx.BOTTOM, border=6)
1202 vbox.Add(hbox_scl, flag=wx.ALL, border=4)
1205 ###########################
1206 ## Mask
1207 hbox_msk = wx.BoxSizer(wx.HORIZONTAL)
1208 self.btn_mask = wx.Button(panel,label='MASK')
1209 self.ch_msk = wx.CheckBox(self.panel,label='Apply?')
1211 self.ch_msk.Bind(wx.EVT_CHECKBOX,self.applyMask)
1212 self.btn_mask.Bind(wx.EVT_BUTTON,self.openMask)
1214 hbox_msk.Add(self.btn_mask, flag=wx.RIGHT|wx.TOP|wx.BOTTOM, border=6)
1215 hbox_msk.Add(self.ch_msk, flag=wx.RIGHT|wx.TOP|wx.BOTTOM, border=6)
1216 vbox.Add(hbox_msk, flag=wx.ALL, border=4)
1218 ###########################
1219 ## Background
1220 hbox_bkgd1 = wx.BoxSizer(wx.HORIZONTAL)
1221 self.btn_bkgd = wx.Button(panel,label='BACKGROUND')
1222 self.sldr_bkgd = wx.Slider(self.panel,style=wx.SL_VALUE_LABEL, minValue=0, maxValue=1000)
1224 self.sldr_bkgd.Bind(wx.EVT_SLIDER,self.onBkgdScale)
1225 self.btn_bkgd.Bind(wx.EVT_BUTTON,self.openBkgd)
1227 hbox_bkgd1.Add(self.btn_bkgd, flag=wx.RIGHT|wx.TOP, border=6)
1228 hbox_bkgd1.Add(self.sldr_bkgd, flag=wx.EXPAND|wx.TOP, border=6)
1229 vbox.Add(hbox_bkgd1, flag=wx.TOP|wx.BOTTOM, border=4)
1231 self.sldr_bkgd.SetValue(int(self.bkgd_scale*SLIDER_SCALE))
1233 ###########################
1234 ## Set defaults
1235 self.ch_clr.SetStringSelection(self.color)
1236 self.ch_flp.SetStringSelection(self.flip)
1237 self.ch_scl.SetSelection(0)
1238 self.ch_msk.Disable()
1239 self.ch_clr.Disable()
1240 self.sldr_cntrst.Disable()
1241 self.entr_min.Disable()
1242 self.entr_max.Disable()
1243 self.btn_ct1.Disable()
1244 self.ch_flp.Disable()
1245 self.ch_scl.Disable()
1246 self.btn_mask.Disable()
1247 self.btn_bkgd.Disable()
1248 self.sldr_bkgd.Disable()
1250 self.hrz_frm_sldr.Disable()
1251 for btn in self.hrz_frm_btn: btn.Disable()
1253 self.vrt_frm_sldr.Disable()
1254 for btn in self.vrt_frm_btn: btn.Disable()
1256 return vbox
1259 def RightSidePanel(self,panel):
1260 vbox = wx.BoxSizer(wx.VERTICAL)
1262 self.xrd2Dcake = diFFit2DPanel(panel,owner=self,size=(400,400),type='cake')
1263 self.xrd1Dviewer = diFFit1DPanel(panel,owner=self,size=(400,100))
1265 vbox.Add(self.xrd2Dcake, proportion=1, flag=wx.TOP|wx.EXPAND, border = 10)
1266 vbox.Add(self.xrd1Dviewer, proportion=1, flag=wx.BOTTOM|wx.EXPAND, border = 10)
1268 return vbox
1270 def CenterPanel(self,panel):
1272 self.xrd2Dviewer = diFFit2DPanel(panel,owner=self)
1273 btnbox = self.QuickButtons(panel)
1275 vbox = wx.BoxSizer(wx.VERTICAL)
1276 vbox.Add(self.xrd2Dviewer,proportion=1,flag=wx.ALL|wx.EXPAND,border = 10)
1277 vbox.Add(btnbox,flag=wx.ALL, border = 10)
1278 return vbox
1280 def QuickButtons(self,panel):
1281 buttonbox = wx.BoxSizer(wx.HORIZONTAL)
1282 self.btn_img = wx.Button(panel,label='LOAD IMAGE')
1283 self.btn_calib = wx.Button(panel,label='CALIBRATION')
1284 self.btn_integ = wx.Button(panel,label='INTEGRATE (1D)')
1286 self.btn_img.Bind(wx.EVT_BUTTON,self.loadIMAGE)
1287 self.btn_calib.Bind(wx.EVT_BUTTON,self.openPONI)
1288 self.btn_integ.Bind(wx.EVT_BUTTON,self.on1DXRD)
1290 buttonbox.Add(self.btn_img, flag=wx.ALL, border=8)
1291 buttonbox.Add(self.btn_calib, flag=wx.ALL, border=8)
1292 buttonbox.Add(self.btn_integ, flag=wx.ALL, border=8)
1294 return buttonbox
1297class XRDImg(Group):
1298 '''
1299 XRD image class
1301 Attributes:
1302 ------------
1303 * self.label = 'Data: CeO2_Allende' # name of data set
1304 * self.path = '/Volumes/Data/CeO2_Allende.tif' # file containing x-y data
1305 * self.type = 'tiff' # file type
1307 # Data parameters
1308 * self.image = None or array # should be a 3-D array [no * x * y]
1309 * self.iframes = 1 # number of frames in self.image (row)
1310 * self.i = 0 # integer indicating current frame (row)
1311 * self.jframes = 1 # number of frames in self.image (col)
1312 * self.j = 0 # integer indicating current frame (col)
1313 * self.minval = 0 # integer of minimum display contrast
1314 * self.maxval = 100 # integer of maximum display contrast
1316 mkak 2017.08.15
1317 '''
1319 def __init__(self, label=None, path='', type='tiff', image=None, h5file=None):
1321 self.label = label
1322 self.path = path
1323 self.type = type
1325 self.calfile = None
1327 self.h5file = h5file
1328 self.image = np.zeros((1,1,PIXELS,PIXELS)) if image is None else image
1330 self.check_image()
1331 self.calc_range()
1334 def check_image(self):
1336 if self.h5file is None:
1337 shp = np.shape(self.image)
1338 if len(shp) == 2:
1339 self.image = np.reshape(self.image,(1,1,shp[0],shp[1]))
1340 if len(shp) == 3:
1341 self.image = np.reshape(self.image,(1,shp[0],shp[1],shp[2]))
1343 self.jframes,self.iframes,self.xpix,self.ypix = np.shape(self.image)
1344 else:
1345 try:
1346 self.h5xrd = self.h5file['xrmmap/xrd2D/counts']
1347 except:
1348 self.image = None
1349 print('No 2DXRD data in %s' % os.path.split(self.h5file.filename)[-1])
1350 return
1351 self.calfile = bytes2str(self.h5file['xrmmap/xrd1D'].attrs.get('calfile',''))
1352 if not os.path.exists(self.calfile):
1353 self.calfile = None
1355 ## making an assumption that h5 map file always has multiple rows and cols
1356 self.jframes,self.iframes,self.xpix,self.ypix = self.h5xrd.shape
1358 self.i = 0 if self.iframes < 4 else int(self.iframes)/2
1359 self.j = 0 if self.jframes < 4 else int(self.jframes)/2
1361 def calc_range(self):
1363 if self.h5file is None:
1364 self.minval = self.image[self.j,self.i].min()
1365 self.maxval = self.image[self.j,self.i].max()
1366 else:
1367 self.minval = self.h5xrd[self.j,self.i].min()
1368 self.maxval = self.h5xrd[self.j,self.i].max()
1370 def get_image(self,i=None,j=None):
1372 if i is not None and i != self.i:
1373 if i < 0: i == self.iframes-1
1374 if i >= self.iframes: i = 0
1375 self.i = i
1377 if j is not None and j != self.j:
1378 if j < 0: j == self.jframes-1
1379 if j >= self.jframes: j = 0
1380 self.j = j
1382 if self.h5file is None:
1383 return self.image[self.j,self.i]
1384 else:
1385 return self.h5xrd[self.j,self.i]
1387 def set_contrast(self,minval,maxval):
1389 if maxval == minval: maxval = minval+100
1391 self.minval = int(minval)
1392 self.maxval = int(maxval)
1395class XRD2DViewer(LarchWxApp):
1396 def __init__(self, **kws):
1397 LarchWxApp.__init__(self, **kws)
1399 def createApp(self):
1400 frame = XRD2DViewerFrame()
1401 frame.Show()
1402 self.SetTopWindow(frame)
1403 return True
1406if __name__ == '__main__':
1407 XRD2DViewer().MainLoop()