Coverage for /Users/Newville/Codes/xraylarch/larch/wxmap/mapviewer.py: 10%

1929 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-09 10:08 -0600

1#!/usr/bin/env python 

2""" 

3GUI for displaying maps from HDF5 files 

4 

5""" 

6 

7import os 

8import platform 

9import sys 

10import time 

11import json 

12import socket 

13import datetime 

14from functools import partial 

15from threading import Thread 

16from collections import namedtuple 

17 

18import wx 

19from wx.adv import AboutBox, AboutDialogInfo 

20import wx.lib.scrolledpanel as scrolled 

21import wx.lib.mixins.inspection 

22 

23import wx.dataview as dv 

24DVSTY = dv.DV_SINGLE|dv.DV_VERT_RULES|dv.DV_ROW_LINES 

25 

26HAS_EPICS = False 

27try: 

28 from epics import caput 

29 HAS_EPICS = True 

30except: 

31 pass 

32 

33import numpy as np 

34import scipy.stats as stats 

35 

36#from matplotlib.widgets import Slider, Button, RadioButtons 

37 

38from wxmplot import PlotFrame 

39 

40import larch 

41from larch.larchlib import read_workdir, save_workdir 

42from larch.wxlib import (LarchPanel, LarchFrame, EditableListBox, SimpleText, 

43 FloatCtrl, Font, pack, Popup, Button, MenuItem, 

44 Choice, Check, GridPanel, FileSave, HLine, flatnotebook, 

45 HLine, OkCancel, LEFT, LarchUpdaterDialog, LarchWxApp) 

46from larch.wxxas.xas_dialogs import fit_dialog_window 

47from larch.utils.strutils import bytes2str, version_ge 

48from larch.utils import get_cwd 

49from larch.io import nativepath 

50from larch.site_config import icondir 

51from larch.version import check_larchversion 

52 

53from ..xrd import lambda_from_E, xrd1d, save1D, calculate_xvalues, read_poni 

54from ..xrmmap import GSEXRM_MapFile, GSEXRM_FileStatus, h5str, ensure_subgroup, DEFAULT_XRAY_ENERGY 

55from ..apps import check_larchversion, update_larch 

56from ..epics import pv_fullname 

57from ..wxlib.xrfdisplay import XRFDisplayFrame 

58 

59from .mapimageframe import MapImageFrame, CorrelatedMapFrame 

60from .mapmathpanel import MapMathPanel 

61from .maptomopanel import TomographyPanel 

62from .mapxrfpanel import XRFAnalysisPanel 

63 

64from ..wxxrd import XRD2DViewerFrame 

65from ..wxxrd.xrd1d_display import XRD1DFrame 

66 

67def timestring(): 

68 return datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') 

69 

70FONTSIZE = 8 

71if platform.system() in ('Windows', 'Darwin'): 

72 FONTSIZE = 10 

73 

74CEN = wx.ALIGN_CENTER 

75LEFT = wx.ALIGN_LEFT 

76RIGHT = wx.ALIGN_RIGHT 

77ALL_CEN = wx.ALL|CEN 

78ALL_LEFT = wx.ALL|LEFT 

79ALL_RIGHT = wx.ALL|RIGHT 

80 

81 

82FILE_WILDCARDS = 'X-ray Maps (*.h5)|*.h5|All files (*.*)|*.*' 

83 

84XRF_ICON_FILE = 'gse_xrfmap.ico' 

85 

86NOT_OWNER_MSG = """The File 

87 '%s' 

88appears to be open by another process. Having two 

89processes writing to the file can cause corruption. 

90 

91Do you want to take ownership of the file? 

92""" 

93 

94NOT_GSEXRM_FILE = """The File 

95 '%s' 

96doesn't seem to be a Map File 

97""" 

98 

99NOT_GSEXRM_FOLDER = """The Folder 

100 '%s' 

101doesn't seem to be a Map Folder 

102""" 

103FILE_ALREADY_READ = """The File 

104 '%s' 

105has already been read. 

106""" 

107 

108FRAMESTYLE = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL 

109BEAMLINE = '13-ID-E' 

110FACILITY = 'APS' 

111 

112PLOT_TYPES = ('Single ROI Map', 'Three ROI Map', 'Correlation Plot') 

113PROCROWS_CHOICES = ('All', '500', '200', '100', '50', '20', '10') 

114PLOT_OPERS = ('/', '*', '-', '+') 

115 

116ESCAN_CRED = os.environ.get('ESCAN_CREDENTIALS', None) 

117if ESCAN_CRED is not None: 

118 try: 

119 from ..epics.larchscan import connect_scandb 

120 except ImportError: 

121 ESCAN_CRED = None 

122 

123CWID = 150 

124WWID = 100 + CWID*4 

125 

126class MapPanel(GridPanel): 

127 '''Panel of Controls for viewing maps''' 

128 label = 'ROI Map' 

129 def __init__(self, parent, owner=None, **kws): 

130 

131 self.owner = owner 

132 self.cfile, self.xrmmap = None,None 

133 self.last_process_time = 0 

134 self.detectors_set = False 

135 GridPanel.__init__(self, parent, nrows=8, ncols=6, **kws) 

136 

137 self.plot_choice = Choice(self, choices=PLOT_TYPES, size=(CWID, -1)) 

138 self.plot_choice.Bind(wx.EVT_CHOICE, self.plotSELECT) 

139 

140 self.det_choice = [Choice(self, size=(CWID, -1)), 

141 Choice(self, size=(CWID, -1)), 

142 Choice(self, size=(CWID, -1)), 

143 Choice(self, size=(CWID, -1))] 

144 

145 self.roi_choice = [Choice(self, size=(CWID, -1)), 

146 Choice(self, size=(CWID, -1)), 

147 Choice(self, size=(CWID, -1)), 

148 Choice(self, size=(CWID, -1))] 

149 for i,det_chc in enumerate(self.det_choice): 

150 det_chc.Bind(wx.EVT_CHOICE, partial(self.detSELECT,i)) 

151 

152 for i,roi_chc in enumerate(self.roi_choice): 

153 roi_chc.Bind(wx.EVT_CHOICE, partial(self.roiSELECT,i)) 

154 

155 self.det_label = [SimpleText(self,'Intensity'), 

156 SimpleText(self,''), 

157 SimpleText(self,''), 

158 SimpleText(self, 'Normalization')] 

159 self.roi_label = [SimpleText(self,''), 

160 SimpleText(self,''), 

161 SimpleText(self,''), 

162 SimpleText(self,'')] 

163 

164 fopts = dict(minval=-50000, precision=0, size=(70, -1)) 

165 self.lims = [FloatCtrl(self, value= 0, **fopts), 

166 FloatCtrl(self, value=-1, **fopts), 

167 FloatCtrl(self, value= 0, **fopts), 

168 FloatCtrl(self, value=-1, **fopts)] 

169 

170 self.zigoff = FloatCtrl(self, value=0, minval=-15, maxval=15, 

171 precision=0, size=(70, -1)) 

172 for wid in self.lims: 

173 wid.Disable() 

174 

175 self.use_dtcorr = Check(self, default=True, 

176 label='Correct for Detector Deadtime', 

177 action=self.onDTCorrect) 

178 self.use_hotcols = Check(self, default=False, 

179 label='Remove First and Last columns', 

180 action=self.onHotCols) 

181 

182 self.use_zigzag = Check(self, default=False, label='Fix ZigZag', 

183 action=self.onZigZag) 

184 

185 self.limrange = Check(self, default=False, 

186 label=' Limit Map Range to Pixel Range:', 

187 action=self.onLimitRange) 

188 

189 map_shownew = Button(self, 'Show New Map', size=(CWID, -1), 

190 action=partial(self.onROIMap, new=True)) 

191 map_update = Button(self, 'Replace Last Map', size=(CWID, -1), 

192 action=partial(self.onROIMap, new=False)) 

193 self.mapproc_btn = Button(self, 'Add More Rows', size=(CWID, -1), 

194 action=self.onProcessMap) 

195 

196 map_showxrf = Button(self, 'Show Full XRF', size=(CWID, -1), 

197 action=self.onShowXRF) 

198 

199 self.mapproc_nrows = Choice(self, choices=PROCROWS_CHOICES, size=(CWID, -1)) 

200 self.mapproc_nrows.SetStringSelection('100') 

201 

202 self.Add(SimpleText(self, 'Build Map From Raw Data Folder:'), 

203 dcol=2, style=LEFT, newrow=True) 

204 self.Add(self.mapproc_btn, dcol=1, style=LEFT) 

205 self.Add(SimpleText(self, 'Max # Rows to Add:'), dcol=1, 

206 style=LEFT, newrow=False) 

207 self.Add(self.mapproc_nrows, dcol=1, style=LEFT) 

208 

209 self.Add(HLine(self, size=(WWID, 5)), dcol=8, style=LEFT, newrow=True) 

210 self.Add((5, 5), newrow=True) 

211 

212 self.Add(SimpleText(self, 'Display ROI Maps: Plot Type:'), dcol=2, 

213 style=LEFT, newrow=True) 

214 self.Add(self.plot_choice, dcol=1, style=LEFT) 

215 self.AddMany((SimpleText(self,''), self.det_label[0], 

216 self.det_label[1], self.det_label[2], self.det_label[3]), 

217 style=LEFT, newrow=True) 

218 

219 self.AddMany((SimpleText(self,'Detector:'), self.det_choice[0], 

220 self.det_choice[1], self.det_choice[2], self.det_choice[3]), 

221 style=LEFT, newrow=True) 

222 

223 self.AddMany((SimpleText(self,'ROI:'),self.roi_choice[0], 

224 self.roi_choice[1],self.roi_choice[2], self.roi_choice[3]), 

225 style=LEFT, newrow=True) 

226 

227 self.AddMany((SimpleText(self,''),self.roi_label[0], 

228 self.roi_label[1],self.roi_label[2], self.roi_label[3]), 

229 style=LEFT, newrow=True) 

230 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

231 self.Add(map_shownew, dcol=1, style=LEFT) 

232 self.Add(map_update, dcol=1, style=LEFT) 

233 

234 self.Add(HLine(self, size=(WWID, 5)), dcol=8, style=LEFT, newrow=True) 

235 self.Add(SimpleText(self,'Options:'), dcol=1, style=LEFT, newrow=True) 

236 self.Add(self.use_dtcorr, dcol=2, style=LEFT) 

237 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

238 self.Add(self.use_hotcols, dcol=2, style=LEFT) 

239 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

240 self.Add(self.use_zigzag, dcol=1, style=LEFT) 

241 self.Add(self.zigoff, dcol=1, style=LEFT) 

242 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

243 self.Add(self.limrange, dcol=2, style=LEFT) 

244 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

245 self.Add(SimpleText(self, 'X Range:'), dcol=1, style=LEFT) 

246 self.Add(self.lims[0], dcol=1, style=LEFT) 

247 self.Add(self.lims[1], dcol=1, style=LEFT) 

248 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

249 self.Add(SimpleText(self, 'Y Range:'), dcol=1, style=LEFT) 

250 self.Add(self.lims[2], dcol=1, style=LEFT) 

251 self.Add(self.lims[3], dcol=1, style=LEFT) 

252 self.Add((5, 5), dcol=1, style=LEFT, newrow=True) 

253 self.Add(map_showxrf, dcol=1, style=LEFT) 

254 self.Add(HLine(self, size=(WWID, 5)), dcol=8, style=LEFT, newrow=True) 

255 self.pack() 

256 

257 def onDTCorrect(self, event=None): 

258 xrmfile = self.owner.current_file 

259 if xrmfile is not None: 

260 xrmfile.dtcorrect = self.use_dtcorr.IsChecked() 

261 

262 def onHotCols(self, event=None): 

263 xrmfile = self.owner.current_file 

264 if xrmfile is not None: 

265 xrmfile.hotcols = self.use_hotcols.IsChecked() 

266 

267 def onZigZag(self, event=None): 

268 xrmfile = self.owner.current_file 

269 if xrmfile is not None: 

270 zigzag = 0 

271 if self.use_zigzag.IsChecked(): 

272 zigzag = int(self.zigoff.GetValue()) 

273 xrmfile.zigzag = zigzag 

274 

275 def update_xrmmap(self, xrmfile=None, set_detectors=False): 

276 if xrmfile is None: 

277 xrmfile = self.owner.current_file 

278 self.cfile = xrmfile 

279 self.xrmmap = self.cfile.xrmmap 

280 #if set_detectors or not self.detectors_set: 

281 self.set_det_choices() 

282 self.plotSELECT() 

283 

284 def onLimitRange(self, event=None): 

285 if self.limrange.IsChecked(): 

286 for wid in self.lims: 

287 wid.Enable() 

288 else: 

289 for wid in self.lims: 

290 wid.Disable() 

291 

292 def detSELECT(self, idet, event=None): 

293 self.set_roi_choices(idet=idet) 

294 

295 def roiSELECT(self,iroi,event=None): 

296 

297 detname = self.det_choice[iroi].GetStringSelection() 

298 roiname = self.roi_choice[iroi].GetStringSelection() 

299 

300 if version_ge(self.cfile.version, '2.0.0'): 

301 try: 

302 roi = self.cfile.xrmmap['roimap'][detname][roiname] 

303 limits = roi['limits'][:] 

304 units = bytes2str(roi['limits'].attrs.get('units','')) 

305 roistr = '[%0.1f to %0.1f %s]' % (limits[0],limits[1],units) 

306 except: 

307 roistr = '' 

308 else: 

309 try: 

310 roi = self.cfile.xrmmap[detname] 

311 en = list(roi['energy'][:]) 

312 index = list(roi['roi_name'][:]).index(roiname) 

313 limits = list(roi['roi_limits'][:][index]) 

314 roistr = '[%0.1f to %0.1f keV]' % (en[limits[0]],en[limits[1]]) 

315 except: 

316 roistr = '' 

317 

318 self.roi_label[iroi].SetLabel(roistr) 

319 

320 def plotSELECT(self,event=None): 

321 if len(self.owner.filemap) > 0: 

322 plot_type = self.plot_choice.GetStringSelection().lower() 

323 if 'single' in plot_type: 

324 for i in (1, 2): 

325 self.det_choice[i].Disable() 

326 self.roi_choice[i].Disable() 

327 self.roi_label[i].SetLabel('') 

328 for i, label in enumerate(['Intensity', ' ', ' ']): 

329 self.det_label[i].SetLabel(label) 

330 elif 'three' in plot_type: 

331 for i in (1, 2): 

332 self.det_choice[i].Enable() 

333 self.roi_choice[i].Enable() 

334 for i, label in enumerate(['Red', 'Green', 'Blue']): 

335 self.det_label[i].SetLabel(label) 

336 self.set_roi_choices() 

337 elif 'correl' in plot_type: 

338 self.det_choice[1].Enable() 

339 self.roi_choice[1].Enable() 

340 self.det_choice[2].Disable() 

341 self.roi_choice[2].Disable() 

342 for i, label in enumerate([' X ',' Y ', '']): 

343 self.det_label[i].SetLabel(label) 

344 self.set_roi_choices() 

345 

346 def onClose(self): 

347 for p in self.plotframes: 

348 try: 

349 p.Destroy() 

350 except: 

351 pass 

352 

353 def ShowMap(self, xrmfile=None, new=True): 

354 subtitles = None 

355 plt3 = 'three' in self.plot_choice.GetStringSelection().lower() 

356 

357 if xrmfile is None: 

358 xrmfile = self.owner.current_file 

359 

360 self.onZigZag() 

361 

362 args={'hotcols' : xrmfile.hotcols, 

363 'dtcorrect' : xrmfile.dtcorrect} 

364 

365 det_name, roi_name, plt_name = [], [], [] 

366 for det, roi in zip(self.det_choice, self.roi_choice): 

367 det_name += [det.GetStringSelection()] 

368 roi_name += [roi.GetStringSelection()] 

369 if det_name[-1] == 'scalars': 

370 plt_name += ['%s' % roi_name[-1]] 

371 else: 

372 plt_name += ['%s(%s)' % (roi_name[-1],det_name[-1])] 

373 

374 mapx = 1.0 

375 if roi_name[-1] != '1': 

376 mapx = xrmfile.get_roimap(roi_name[-1], det=det_name[-1], **args) 

377 mapx[np.where(mapx==0)] = 1. 

378 

379 r_map = xrmfile.get_roimap(roi_name[0], det=det_name[0], **args) 

380 if plt3: 

381 g_map = xrmfile.get_roimap(roi_name[1], det=det_name[1], **args) 

382 b_map = xrmfile.get_roimap(roi_name[2], det=det_name[2], **args) 

383 

384 x = xrmfile.get_pos(0, mean=True) 

385 y = xrmfile.get_pos(1, mean=True) 

386 

387 pref, fname = os.path.split(xrmfile.filename) 

388 

389 if plt3: 

390 map = np.array([r_map/mapx, g_map/mapx, b_map/mapx]) 

391 map = np.einsum('kij->ijk', map) 

392 

393 title = fname 

394 info = '' 

395 if roi_name[-1] == '1': 

396 subtitles = {'red': 'Red: %s' % plt_name[0], 

397 'green': 'Green: %s' % plt_name[1], 

398 'blue': 'Blue: %s' % plt_name[2]} 

399 else: 

400 subtitles = {'red': 'Red: %s / %s' % (plt_name[0], plt_name[-1]), 

401 'green': 'Green: %s / %s' % (plt_name[1], plt_name[-1]), 

402 'blue': 'Blue: %s / %s' % (plt_name[2], plt_name[-1])} 

403 

404 else: 

405 map = r_map/mapx 

406 if roi_name[-1] == '1': 

407 title = plt_name[0] 

408 else: 

409 title = '%s / %s' % (plt_name[0], plt_name[-1]) 

410 title = '%s: %s' % (fname, title) 

411 info = 'Intensity: [%g, %g]' %(map.min(), map.max()) 

412 subtitle = None 

413 

414 det = None 

415 if (plt3 and det_name[0]==det_name[1] and det_name[0]==det_name[2]) or not plt3: 

416 for s in det_name[0]: 

417 if s.isdigit(): det = int(s) 

418 

419 if len(self.owner.im_displays) == 0 or new: 

420 iframe = self.owner.add_imdisplay(title, det=det) 

421 

422 xoff, yoff = 0, 0 

423 if self.limrange.IsChecked(): 

424 lims = [wid.GetValue() for wid in self.lims] 

425 map = map[lims[2]:lims[3], lims[0]:lims[1]] 

426 xoff, yoff = lims[0], lims[2] 

427 self.owner.display_map(map, title=title, info=info, x=x, y=y, det=det, 

428 xoff=xoff, yoff=yoff, subtitles=subtitles, 

429 xrmfile=self.cfile) 

430 

431 def onLasso(self, selected=None, mask=None, data=None, xrmfile=None, **kws): 

432 if xrmfile is None: 

433 xrmfile = self.owner.current_file 

434 ny, nx = xrmfile.get_shape() 

435 indices = [] 

436 for idx in selected: 

437 iy, ix = divmod(idx, ny) 

438 indices.append((ix, iy)) 

439 

440 

441 def ShowCorrel(self, xrmfile=None, new=True): 

442 

443 if xrmfile is None: 

444 xrmfile = self.owner.current_file 

445 self.onZigZag() 

446 args={'hotcols' : xrmfile.hotcols, 

447 'dtcorrect' : xrmfile.dtcorrect} 

448 det_name,roi_name = [],[] 

449 plt_name = [] 

450 

451 xdet = self.det_choice[0].GetStringSelection() 

452 xroi = self.roi_choice[0].GetStringSelection() 

453 xlab = "%s(%s)" % (xroi, xdet) 

454 if 'scalar' in xdet.lower(): 

455 xlab = xroi 

456 ydet = self.det_choice[1].GetStringSelection() 

457 yroi = self.roi_choice[1].GetStringSelection() 

458 

459 ylab = "%s(%s)" % (yroi, ydet) 

460 if 'scalar' in ydet.lower(): 

461 ylab = yroi 

462 

463 map1 = xrmfile.get_roimap(xroi, det=xdet, **args) 

464 map2 = xrmfile.get_roimap(yroi, det=ydet, **args) 

465 

466 x = xrmfile.get_pos(0, mean=True) 

467 y = xrmfile.get_pos(1, mean=True) 

468 

469 pref, fname = os.path.split(xrmfile.filename) 

470 title ='%s: %s vs. %s' %(fname, ylab, xlab) 

471 

472 correl_plot = CorrelatedMapFrame(parent=self.owner, xrmfile=xrmfile) 

473 correl_plot.display(map1, map2, name1=xlab, name2=ylab, 

474 x=x, y=y, title=title) 

475 correl_plot.Show() 

476 correl_plot.Raise() 

477 self.owner.plot_displays.append(correl_plot) 

478 

479 def onProcessMap(self, event=None, max_new_rows=None): 

480 xrmfile = self.owner.current_file 

481 if xrmfile is None: 

482 return 

483 pref, fname = os.path.split(xrmfile.filename) 

484 if max_new_rows is None: 

485 max_new_rows = self.mapproc_nrows.GetStringSelection().lower() 

486 if max_new_rows.lower() == 'all': 

487 max_new_rows = None 

488 else: 

489 max_new_rows = int(max_new_rows) 

490 self.owner.process_file(fname, max_new_rows=max_new_rows) 

491 self.update_xrmmap(xrmfile=self.owner.current_file, set_detectors=True) 

492 

493 def onROIMap(self, event=None, new=True): 

494 plotcmd = partial(self.ShowMap, new=new) 

495 if 'correlation' in self.plot_choice.GetStringSelection().lower(): 

496 plotcmd = partial(self.ShowCorrel, new=new) 

497 plotcmd() 

498 

499 def onShowXRF(self, event=None): 

500 owner = self.owner 

501 det_list = owner.current_file.get_detector_list() 

502 detname = self.det_choice[0].GetStringSelection() 

503 ny, nx = owner.current_file.get_shape() 

504 

505 xmin, ymin = 0, 0 

506 xmax, ymax = nx, ny 

507 if self.limrange.IsChecked(): 

508 xmin = int(self.lims[0].GetValue()) 

509 xmax = int(self.lims[1].GetValue()) 

510 ymin = int(self.lims[2].GetValue()) 

511 ymax = int(self.lims[3].GetValue()) 

512 if xmax < 0: 

513 xmax += nx 

514 if ymax < 0: 

515 ymax += ny 

516 my, mx= (ymax - ymin), (xmax - xmin) 

517 

518 owner.show_XRFDisplay() 

519 self._mca = owner.current_file.get_mca_rect(ymin, ymax, xmin, xmax, det=detname, 

520 dtcorrect=owner.dtcor) 

521 pref, fname = os.path.split(self.owner.current_file.filename) 

522 self._mca.filename = fname 

523 self._mca.title = "(%d x %d pixels)" % (mx, my) 

524 self._mca.npixels = my*mx 

525 self.owner.message("Plotting Full XRF Spectra (%d x %d) for '%s'" % (mx, my, fname)) 

526 

527 self.owner.subframes['xrfdisplay'].add_mca(self._mca, label=fname, plot=True) 

528 

529 

530 def set_det_choices(self): 

531 det_list = self.cfile.get_detector_list() 

532 for det_ch in self.det_choice: 

533 det_ch.SetChoices(det_list) 

534 if 'scalars' in det_list: ## should set 'denominator' to scalars as default 

535 self.det_choice[-1].SetStringSelection('scalars') 

536 self.set_roi_choices() 

537 

538 def set_roi_choices(self, idet=None): 

539 force_rois = True # not self.detectors_set 

540 if idet is None: 

541 for idet, det_ch in enumerate(self.det_choice): 

542 detname = self.det_choice[idet].GetStringSelection() 

543 rois = self.cfile.get_roi_list(detname, force=force_rois) 

544 cur = self.roi_choice[idet].GetStringSelection() 

545 self.roi_choice[idet].SetChoices(rois) 

546 if cur in rois: 

547 self.roi_choice[idet].SetStringSelection(cur) 

548 self.roiSELECT(idet) 

549 else: 

550 detname = self.det_choice[idet].GetStringSelection() 

551 rois = self.cfile.get_roi_list(detname, force=force_rois) 

552 cur = self.roi_choice[idet].GetStringSelection() 

553 self.roi_choice[idet].SetChoices(rois) 

554 if cur in rois: 

555 self.roi_choice[idet].SetStringSelection(cur) 

556 self.roiSELECT(idet) 

557 

558 def update_roi(self, detname): 

559 force = True # not self.detectors_set 

560 return self.cfile.get_roi_list(detname, force=force) 

561 

562class MapInfoPanel(scrolled.ScrolledPanel): 

563 """Info Panel """ 

564 label = 'Map Info' 

565 def __init__(self, parent, owner=None, **kws): 

566 scrolled.ScrolledPanel.__init__(self, parent, -1, 

567 style=wx.GROW|wx.TAB_TRAVERSAL, **kws) 

568 self.owner = owner 

569 

570 sizer = wx.GridBagSizer(3, 3) 

571 self.wids = {} 

572 

573 ir = 0 

574 for label in ('Facility','Run Cycle','Proposal Number','User group', 

575 'H5 Map Created', 

576 'Scan Time','File Compression','Map Data', 

577 'Ring Current', 'X-ray Energy', 'X-ray Intensity (I0)', 

578 'Original data path', 'User Comments 1', 'User Comments 2', 

579 'Scan Fast Motor', 'Scan Slow Motor', 'Dwell Time', 

580 'Sample Fine Stages', 

581 'Sample Stage X', 'Sample Stage Y', 

582 'Sample Stage Z', 'Sample Stage Theta', 

583 'XRD Calibration'): 

584 

585 ir += 1 

586 thislabel = SimpleText(self, '%s:' % label, style=wx.LEFT, size=(125, -1)) 

587 self.wids[label] = SimpleText(self, ' ' , style=wx.LEFT, size=(350, -1)) 

588 

589 sizer.Add(thislabel, (ir, 0), (1, 1), 1) 

590 sizer.Add(self.wids[label], (ir, 1), (1, 1), 1) 

591 

592 pack(self, sizer) 

593 self.SetupScrolling() 

594 

595 def update_xrmmap(self, xrmfile=None, set_detectors=None): 

596 if xrmfile is None: 

597 xrmfile = self.owner.current_file 

598 xrmmap = xrmfile.xrmmap 

599 def time_between(d1, d2): 

600 d1 = datetime.datetime.strptime(d1, "%Y-%m-%d %H:%M:%S") 

601 d2 = datetime.datetime.strptime(d2, "%Y-%m-%d %H:%M:%S") 

602 diff = d2 - d1 if d2 > d1 else d1 - d2 

603 return diff.days,diff.seconds 

604 

605 config_grp = ensure_subgroup('config',xrmmap) 

606 notes_grp = ensure_subgroup('notes',config_grp) 

607 time_str = bytes2str(notes_grp.attrs.get('h5_create_time','')) 

608 

609 self.wids['H5 Map Created'].SetLabel(time_str) 

610 

611 try: 

612 d,s = time_between(bytes2str(notes_grp.attrs.get('scan_start_time','')), 

613 bytes2str(notes_grp.attrs.get('scan_end_time',''))) 

614 time_str = str(datetime.timedelta(days=d,seconds=s)) 

615 except: 

616 time_str = bytes2str(xrmmap.attrs.get('Start_Time','')) 

617 

618 self.wids['Scan Time'].SetLabel( time_str ) 

619 self.wids['File Compression'].SetLabel(bytes2str(xrmmap.attrs.get('Compression',''))) 

620 

621 comments = h5str(xrmmap['config/scan/comments'][()]).split('\n', 2) 

622 for i, comm in enumerate(comments): 

623 self.wids['User Comments %i' %(i+1)].SetLabel(comm) 

624 

625 pos_addrs = [str(x) for x in xrmmap['config/positioners'].keys()] 

626 pos_label = [h5str(x[()]) for x in xrmmap['config/positioners'].values()] 

627 

628 scan_pos1 = h5str(xrmmap['config/scan/pos1'][()]) 

629 scan_pos2 = h5str(xrmmap['config/scan/pos2'][()]) 

630 i1 = pos_addrs.index(scan_pos1) 

631 i2 = pos_addrs.index(scan_pos2) 

632 

633 start1 = float(xrmmap['config/scan/start1'][()]) 

634 start2 = float(xrmmap['config/scan/start2'][()]) 

635 stop1 = float(xrmmap['config/scan/stop1'][()]) 

636 stop2 = float(xrmmap['config/scan/stop2'][()]) 

637 

638 step1 = float(xrmmap['config/scan/step1'][()]) 

639 step2 = float(xrmmap['config/scan/step2'][()]) 

640 

641 npts1 = int((abs(stop1 - start1) + 1.1*step1)/step1) 

642 npts2 = int((abs(stop2 - start2) + 1.1*step2)/step2) 

643 

644 sfmt = '%s: [%.4f:%.4f], step=%.4f, %i pixels' 

645 scan1 = sfmt % (pos_label[i1], start1, stop1, step1, npts1) 

646 scan2 = sfmt % (pos_label[i2], start2, stop2, step2, npts2) 

647 

648 rowtime = float(xrmmap['config/scan/time1'][()]) 

649 

650 self.wids['Scan Fast Motor'].SetLabel(scan1) 

651 self.wids['Scan Slow Motor'].SetLabel(scan2) 

652 pixtime = xrmfile.pixeltime 

653 if pixtime is None: 

654 pixtime = xrmfile.calc_pixeltime() 

655 pixtime =int(round(1000.0*pixtime)) 

656 self.wids['Dwell Time'].SetLabel('%.1f ms per pixel' % pixtime) 

657 

658 env_names = list(xrmmap['config/environ/name']) 

659 env_vals = list(xrmmap['config/environ/value']) 

660 env_addrs = list(xrmmap['config/environ/address']) 

661 

662 fines = {'X': '?', 'Y': '?'} 

663 i0vals = {'flux':'?', 'current':'?'} 

664 

665 en = xrmfile.get_incident_energy() 

666 enmsg = '%0.1f eV (%0.3f \u00c5)' % (en, lambda_from_E(en, E_units='eV')) 

667 if abs(en - DEFAULT_XRAY_ENERGY) < 1.0: 

668 enmsg = "%s : PROBABLY NOT CORRECT" % enmsg 

669 self.wids['X-ray Energy'].SetLabel(enmsg) 

670 

671 

672 for name, addr, val in zip(env_names, env_addrs, env_vals): 

673 name = bytes2str(name).lower() 

674 val = h5str(val) 

675 if 'ring_current' in name or 'ring current' in name: 

676 self.wids['Ring Current'].SetLabel('%s mA' % val) 

677 elif 'beamline.fluxestimate' in name or 'transmitted flux' in name: 

678 i0vals['flux'] = val 

679 elif 'i0 current' in name: 

680 i0vals['current'] = val 

681 

682 elif name.startswith('sample'): 

683 name = name.replace('samplestage.', '') 

684 if 'coarsex' in name or 'coarse x' in name: 

685 self.wids['Sample Stage X'].SetLabel('%s mm' % val) 

686 elif 'coarsey' in name or 'coarse y' in name: 

687 self.wids['Sample Stage Y'].SetLabel('%s mm' % val) 

688 elif 'coarsez' in name or 'coarse z' in name: 

689 self.wids['Sample Stage Z'].SetLabel('%s mm' % val) 

690 elif 'theta' in name: 

691 self.wids['Sample Stage Theta'].SetLabel('%s deg' % val) 

692 elif 'finex' in name or 'fine x' in name: 

693 fines['X'] = val 

694 elif 'finey' in name or 'fine y' in name: 

695 fines['Y'] = val 

696 

697 if i0vals['current'] == '?': 

698 i0val = 'Flux=%(flux)s Hz' % i0vals 

699 else: 

700 i0val = u'Flux=%(flux)s Hz, I0 Current=%(current)s \u03BCA' % i0vals 

701 self.wids['X-ray Intensity (I0)'].SetLabel(i0val) 

702 self.wids['Sample Fine Stages'].SetLabel('X, Y = %(X)s, %(Y)s mm' % (fines)) 

703 

704 folderpath = bytes2str(xrmmap.attrs.get('Map_Folder','')) 

705 if len(folderpath) > 35: 

706 folderpath = '...'+folderpath[-35:] 

707 self.wids['Original data path'].SetLabel(folderpath) 

708 

709 self.wids['XRD Calibration'].SetLabel('') 

710 xrd_calibration = '' 

711 if 'xrd1d' in xrmmap: 

712 xrd_calibration = bytes2str(xrmmap['xrd1d'].attrs.get('calfile','')) 

713 if not os.path.exists(xrd_calibration): 

714 xrd_calibration = '' 

715 self.wids['XRD Calibration'].SetLabel(os.path.split(xrd_calibration)[-1]) 

716 

717 notes = {} 

718 config_grp = ensure_subgroup('config',xrmmap) 

719 notes_grp = ensure_subgroup('notes',config_grp) 

720 for key in notes_grp.attrs.keys(): 

721 try: 

722 notes[key] = bytes2str(notes_grp.attrs[key]) 

723 except: 

724 pass 

725 note_title = ['Facility','Run Cycle','Proposal Number','User group'] 

726 note_str = ['','','',''] 

727 if 'beamline' in notes and 'facility' in notes: 

728 note_str[0] = '%s @ %s' % (notes['beamline'],notes['facility']) 

729 if 'run' in notes: 

730 note_str[1] = notes['run'] 

731 if 'proposal' in notes: 

732 note_str[2] = notes['proposal'] 

733 if 'user' in notes: 

734 note_str[3] = notes['user'] 

735 

736 for title,note in zip(note_title,note_str): 

737 self.wids[title].SetLabel(note) 

738 

739 xrmfile.reset_flags() 

740 if xrmfile.has_xrf: 

741 if xrmfile.has_xrd2d and xrmfile.has_xrd1d: 

742 datastr = 'XRF, 2D- and 1D-XRD data' 

743 elif xrmfile.has_xrd2d: 

744 datastr = 'XRF, 2D-XRD data' 

745 elif xrmfile.has_xrd1d: 

746 datastr = 'XRF, 1D-XRD data' 

747 else: 

748 datastr = 'XRF data' 

749 else: 

750 if xrmfile.has_xrd2d and xrmfile.has_xrd1d: 

751 datastr = '2D- and 1D-XRD data' 

752 elif xrmfile.has_xrd2d: 

753 datastr = '2D-XRD data' 

754 elif xrmfile.has_xrd1d: 

755 datastr = '1D-XRD data' 

756 else: 

757 datastr = '' 

758 

759 self.wids['Map Data'].SetLabel(datastr) 

760 

761 def onClose(self): 

762 pass 

763 

764 

765class MapAreaPanel(scrolled.ScrolledPanel): 

766 

767 label = 'Map Areas' 

768 delstr = """ Delete Area '%s'? 

769 

770 WARNING: This cannot be undone! 

771 

772 """ 

773 

774 def __init__(self, parent, owner=None, **kws): 

775 scrolled.ScrolledPanel.__init__(self, parent, -1, 

776 style=wx.GROW|wx.TAB_TRAVERSAL, **kws) 

777 

778 ###################################### 

779 ## GENERAL MAP AREAS 

780 self.owner = owner 

781 pane = wx.Panel(self) 

782 sizer = wx.GridBagSizer(3, 3) 

783 self.choices = {} 

784 bsize = (CWID, -1) 

785 self.choice = Choice(pane, size=(225, -1), action=self.onSelect) 

786 self.desc = wx.TextCtrl(pane, -1, '', size=(225, -1)) 

787 self.info1 = wx.StaticText(pane, -1, '', size=(275, -1)) 

788 self.info2 = wx.StaticText(pane, -1, '', size=(275, -1)) 

789 self.onmap = Button(pane, 'Show on Map', size=bsize, action=self.onShow) 

790 self.clear = Button(pane, 'Clear Map', size=bsize, action=self.onClear) 

791 self.bdelete = Button(pane, 'Delete', size=bsize, action=self.onDelete) 

792 self.update = Button(pane, 'Apply', size=bsize, action=self.onLabel) 

793 self.bexport = Button(pane, 'Export Areas', size=bsize, action=self.onExport) 

794 self.bimport = Button(pane, 'Import Areas', size=bsize, action=self.onImport) 

795 self.bcopy = Button(pane, 'Copy to Other Maps', size=bsize, action=self.onCopy) 

796 self.xrf = Button(pane, 'Show XRF (Fore)', size=bsize, action=self.onXRF) 

797 self.xrf2 = Button(pane, 'Show XRF (Back)', size=bsize, 

798 action=partial(self.onXRF, as_mca2=True)) 

799 

800 self.onstats = Button(pane, 'Calculate XRF Stats', size=bsize, 

801 action=self.onShowStats) 

802 self.onreport = Button(pane, 'Save XRF Stats', size=bsize, 

803 action=self.onReport) 

804 

805 self.xrd1d_plot = Button(pane, 'Show 1D XRD', size=bsize, 

806 action=partial(self.onXRD, show=True, xrd1d=True)) 

807 

808 self.xrd2d_plot = Button(pane, 'Show 2D XRD', size=bsize, 

809 action=partial(self.onXRD, show=True, xrd2d=True)) 

810 

811 legend = wx.StaticText(pane, -1, 'Values in Counts per second', size=(200, -1)) 

812 

813 def txt(s): 

814 return SimpleText(pane, s) 

815 irow = 1 

816 sizer.Add(txt('Map Areas and Saved Points'), ( 0, 0), (1, 5), ALL_CEN, 2) 

817 sizer.Add(txt('Area: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

818 sizer.Add(self.choice, (irow, 1), (1, 2), ALL_LEFT, 2) 

819 sizer.Add(self.bdelete, (irow, 3), (1, 1), ALL_LEFT, 2) 

820 

821 

822 irow += 1 

823 sizer.Add(txt('Info: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

824 sizer.Add(self.info1, (irow, 1), (1, 2), ALL_LEFT, 2) 

825 sizer.Add(self.info2, (irow, 3), (1, 2), ALL_LEFT, 2) 

826 

827 irow += 1 

828 sizer.Add(txt('Rename: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

829 sizer.Add(self.desc, (irow, 1), (1, 2), ALL_LEFT, 2) 

830 sizer.Add(self.update, (irow, 3), (1, 1), ALL_LEFT, 2) 

831 

832 irow += 1 

833 sizer.Add(txt('Show: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

834 sizer.Add(self.onmap, (irow, 1), (1, 1), ALL_LEFT, 2) 

835 sizer.Add(self.clear, (irow, 2), (1, 1), ALL_LEFT, 2) 

836 

837 irow += 1 

838 sizer.Add(txt('Save: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

839 sizer.Add(self.bexport, (irow, 1), (1, 1), ALL_LEFT, 2) 

840 sizer.Add(self.bimport, (irow, 2), (1, 1), ALL_LEFT, 2) 

841 sizer.Add(self.bcopy, (irow, 3), (1, 1), ALL_LEFT, 2) 

842 

843 irow += 1 

844 sizer.Add(txt('XRF: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

845 sizer.Add(self.xrf, (irow, 1), (1, 1), ALL_LEFT, 2) 

846 sizer.Add(self.xrf2, (irow, 2), (1, 1), ALL_LEFT, 2) 

847 sizer.Add(self.onstats, (irow, 3), (1, 1), ALL_LEFT, 2) 

848 sizer.Add(self.onreport, (irow, 4), (1, 1), ALL_LEFT, 2) 

849 

850 

851 irow += 1 

852 sizer.Add(txt('XRD: '), (irow, 0), (1, 1), ALL_LEFT, 2) 

853 sizer.Add(self.xrd1d_plot, (irow, 1), (1, 1), ALL_LEFT, 2) 

854 sizer.Add(self.xrd2d_plot, (irow, 2), (1, 1), ALL_LEFT, 2) 

855 

856 # sizer.Add(self.xrd1d_save, (irow, 0), (1, 2), ALL_LEFT, 2) 

857 # sizer.Add(self.xrd2d_save, (irow, 2), (1, 2), ALL_LEFT, 2) 

858 irow += 1 

859 sizer.Add(legend, (irow, 1), (1, 2), ALL_LEFT, 2) 

860 pack(pane, sizer) 

861 

862 for btn in (self.xrd1d_plot, self.xrd2d_plot): 

863 btn.Disable() 

864 

865 # main sizer 

866 msizer = wx.BoxSizer(wx.VERTICAL) 

867 msizer.Add(pane, 0, wx.ALIGN_LEFT|wx.ALL, 1) 

868 

869 msizer.Add(wx.StaticLine(self, size=(375, 2), style=wx.LI_HORIZONTAL), 

870 0, wx.EXPAND|wx.ALL, 1) 

871 

872 self.report = None 

873 rep = self.report = dv.DataViewListCtrl(self, style=DVSTY) 

874 rep.AppendTextColumn('ROI ', width=150) 

875 rep.AppendTextColumn('Min', width=90) 

876 rep.AppendTextColumn('Max', width=90) 

877 rep.AppendTextColumn('Mean ', width=90) 

878 rep.AppendTextColumn('Sigma', width=90) 

879 rep.AppendTextColumn('Median', width=90) 

880 rep.AppendTextColumn('Mode', width=90) 

881 for col in range(7): 

882 align = wx.ALIGN_RIGHT 

883 if col == 0: align = wx.ALIGN_LEFT 

884 rep.Columns[col].Sortable = False 

885 rep.Columns[col].Renderer.Alignment = align 

886 rep.Columns[col].Alignment = align 

887 

888 rep.SetMinSize((800, 300)) 

889 msizer.Add(rep, 1, wx.ALIGN_LEFT|wx.ALL, 1) 

890 

891 pack(self, msizer) 

892 self.SetupScrolling() 

893 

894 def onCopy(self, event=None): 

895 xrmfile = self.owner.current_file 

896 xrmmap = xrmfile.xrmmap 

897 print("Copy Area : shape", xrmfile, xrmmap.shape) 

898 

899 def show_stats(self): 

900 # self.stats = self.xrmfile.get_area_stats(self.areaname) 

901 if self.report is None: 

902 return 

903 

904 self.report.DeleteAllItems() 

905 self.report_data = [] 

906 

907 def report_info(dname,d): 

908 try: 

909 hmean, gmean = stats.gmean(d), stats.hmean(d) 

910 skew, kurtosis = stats.skew(d), stats.kurtosis(d) 

911 except ValueError: 

912 hmean, gmean, skew, kurtosis = 0, 0, 0, 0 

913 

914 smode = '--' 

915 fmt = '{:,.1f}'.format # use thousands commas, 1 decimal place 

916 mode = stats.mode(d) 

917 if len(mode) > 0: 

918 mode = mode[0] 

919 if len(mode) > 0: 

920 smode = fmt(mode[0]) 

921 dat = (dname, fmt(d.min()), fmt(d.max()), fmt(d.mean()), 

922 fmt(d.std()), fmt(np.median(d)), smode) 

923 self.report_data.append(dat) 

924 self.report.AppendItem(dat) 

925 

926 areaname = self._getarea() 

927 xrmfile = self.owner.current_file 

928 xrmmap = xrmfile.xrmmap 

929 ctime = xrmfile.pixeltime 

930 

931 area = xrmfile.get_area(name=areaname) 

932 amask = area[()] 

933 

934 def match_mask_shape(det, mask): 

935 if mask.shape[1] == det.shape[1] - 2: # hotcols 

936 det = det[:,1:-1] 

937 if mask.shape[0] < det.shape[0]: 

938 det = det[:mask.shape[0]] 

939 return det[mask] 

940 

941 if 'roistats' in area.attrs: 

942 for dat in json.loads(area.attrs.get('roistats','')): 

943 dat = tuple(dat) 

944 self.report_data.append(dat) 

945 self.report.AppendItem(dat) 

946 self.choice.Enable() 

947 return 

948 

949 version = xrmmap.attrs.get('Version','1.0.0') 

950 

951 if version_ge(version, '2.0.0'): 

952 d_pref = 'mca' 

953 d_scas = [d for d in xrmmap['scalars']] 

954 det_list = xrmfile.get_detector_list() 

955 detnames = [x for x in det_list if d_pref in x] 

956 d_rois = xrmfile.get_roi_list(detnames[0]) 

957 

958 else: 

959 d_addrs = [d.lower() for d in xrmmap['roimap/det_address']] 

960 d_names = [d for d in xrmmap['roimap/det_name']] 

961 d_pref = 'det' 

962 

963 # MNREAL 

964 #for i in range(1, xrmfile.nmca+1): 

965 # tname = '%s%i/realtime' % (d_pref, i) 

966 # rtime = xrmmap[tname][()] 

967 # if amask.shape[1] == rtime.shape[1] - 2: # hotcols 

968 # rtime = rtime[:,1:-1] 

969 

970 if version_ge(version, '2.0.0'): 

971 for scalar in d_scas: 

972 d = xrmmap['scalars'][scalar][()] 

973 d = match_mask_shape(d, amask) 

974 report_info(scalar, d/ctime) 

975 

976 for roi in d_rois: 

977 for det in detnames: 

978 d = xrmfile.get_roimap(roi, det=det, dtcorrect=False) 

979 d = match_mask_shape(d, amask) 

980 report_info('%s (%s)' % (roi, det), d/ctime) 

981 

982 else: 

983 for idet, dname in enumerate(d_names): 

984 try: 

985 daddr = h5str(d_addrs[idet]) 

986 except IndexError: 

987 break 

988 if 'mca' in daddr: 

989 det = 1 

990 words = daddr.split('mca') 

991 if len(words) > 1: 

992 det = int(words[1].split('.')[0]) 

993 

994 d = xrmmap['roimap/det_raw'][:,:,idet] 

995 d = match_mask_shape(d, amask) 

996 report_info(dname, d/ctime) 

997 

998 if 'roistats' not in area.attrs: 

999 area.attrs['roistats'] = json.dumps(self.report_data) 

1000 xrmfile.h5root.flush() 

1001 

1002 def update_xrmmap(self, xrmfile=None, set_detectors=None): 

1003 if xrmfile is None: xrmfile = self.owner.current_file 

1004 xrmmap = xrmfile.xrmmap 

1005 self.set_area_choices(xrmmap, show_last=True) 

1006 self.set_enabled_btns(xrmfile=xrmfile) 

1007 self.report.DeleteAllItems() 

1008 self.report_data = [] 

1009 try: 

1010 self.onSelect() 

1011 except: 

1012 pass 

1013 

1014 def set_enabled_btns(self, xrmfile=None): 

1015 if xrmfile is None: 

1016 xrmfile = self.owner.current_file 

1017 

1018 xrmfile.reset_flags() 

1019 self.xrd2d_plot.Enable(xrmfile.has_xrd1d) 

1020 self.xrd1d_plot.Enable(xrmfile.has_xrd1d) 

1021 

1022 def clear_area_choices(self): 

1023 

1024 self.info1.SetLabel('') 

1025 self.info2.SetLabel('') 

1026 self.desc.SetValue('') 

1027 self.choice.Clear() 

1028 

1029 def set_area_choices(self, xrmmap, show_last=False): 

1030 

1031 self.clear_area_choices() 

1032 

1033 areas = xrmmap['areas'] 

1034 

1035 c = self.choice 

1036 c.Clear() 

1037 self.choices = {} 

1038 choice_labels = [] 

1039 for a in areas: 

1040 desc = bytes2str(areas[a].attrs.get('description', a)) 

1041 self.choices[desc] = a 

1042 choice_labels.append(desc) 

1043 

1044 c.AppendItems(choice_labels) 

1045 this_label = '' 

1046 if len(self.choices) > 0: 

1047 idx = 0 

1048 if show_last: 

1049 idx = len(self.choices)-1 

1050 try: 

1051 this_label = choice_labels[idx] 

1052 except: 

1053 return 

1054 c.SetStringSelection(this_label) 

1055 self.desc.SetValue(this_label) 

1056 

1057 

1058 def onReport(self, event=None): 

1059 aname = self._getarea() 

1060 path, fname = os.path.split(self.owner.current_file.filename) 

1061 deffile = '%s_%s' % (fname, aname) 

1062 deffile = deffile.replace('.', '_') + '.dat' 

1063 outfile = FileSave(self, 'Save Area XRF Statistics File', 

1064 default_file=deffile, 

1065 wildcard=FILE_WILDCARDS) 

1066 

1067 if outfile is None: 

1068 return 

1069 

1070 area = self.owner.current_file.xrmmap['areas/%s' % aname] 

1071 npix = area[()].sum() 

1072 pixtime = self.owner.current_file.pixeltime 

1073 

1074 mca = self.owner.current_file.get_mca_area(aname) 

1075 dtime = mca.real_time 

1076 info_fmt = '%i Pixels, %i ms/pixel, %.3f total seconds' 

1077 buff = ['# Map %s, Area %s' % (self.owner.current_file.filename, aname), 

1078 '# %i Pixels' % npix, 

1079 '# %i ms per pixel' % int(round(1000.0*pixtime)), 

1080 '# %.3f total seconds' % dtime, 

1081 '# Time (TSCALER) in ms', 

1082 '# All other values in counts per second', 

1083 '#----------------------------------', 

1084 '# ROI Min Max Mean Sigma Median Mode'] 

1085 for dat in self.report_data: 

1086 buff.append(' '.join(dat)) 

1087 buff.append('') 

1088 try: 

1089 fout = open(outfile, 'w', encoding=sys.getdefaultencoding()) 

1090 fout.write('\n'.join(buff)) 

1091 fout.close() 

1092 except IOError: 

1093 print('could not write %s' % outfile) 

1094 

1095 def _getarea(self): 

1096 return self.choices[self.choice.GetStringSelection()] 

1097 

1098 def onExport(self, event=None): 

1099 ofile = self.owner.current_file.export_areas() 

1100 self.owner.message('Exported Areas to %s' % ofile) 

1101 

1102 def onImport(self, event=None): 

1103 wildcards = 'Area Files (*_Areas.npz)|*_Areas.npz|All files (*.*)|*.*' 

1104 dlg = wx.FileDialog(self, message='Read Areas File', 

1105 defaultDir=get_cwd(), 

1106 wildcard=wildcards, style=wx.FD_OPEN) 

1107 

1108 if dlg.ShowModal() == wx.ID_OK: 

1109 fname = dlg.GetPath().replace('\\', '/') 

1110 self.owner.current_file.import_areas(fname) 

1111 self.owner.message('Imported Areas from %s' % fname) 

1112 self.set_area_choices(self.owner.current_file.xrmmap) 

1113 self.onSelect() 

1114 

1115 def onSelect(self, event=None): 

1116 try: 

1117 aname = self._getarea() 

1118 except: 

1119 return 

1120 area = self.owner.current_file.xrmmap['areas/%s' % aname] 

1121 npix = area[()].sum() 

1122 yvals, xvals = np.where(area[()]) 

1123 pixtime = self.owner.current_file.pixeltime 

1124 dtime = npix*pixtime 

1125 info1_fmt = '%i Pixels, %.3f seconds' 

1126 info2_fmt = ' Range (pixels) X: [%i:%i], Y: [%i:%i] ' 

1127 self.info1.SetLabel(info1_fmt % (npix, dtime)) 

1128 self.info2.SetLabel(info2_fmt % (xvals.min(), xvals.max(), 

1129 yvals.min(), yvals.max())) 

1130 

1131 self.desc.SetValue(area.attrs.get('description', aname)) 

1132 self.report.DeleteAllItems() 

1133 self.report_data = [] 

1134 if 'roistats' in area.attrs: 

1135 self.show_stats() 

1136 

1137 def onShowStats(self, event=None): 

1138 if self.report is None: 

1139 return 

1140 self.show_stats() 

1141 

1142 def onLabel(self, event=None): 

1143 aname = self._getarea() 

1144 area = self.owner.current_file.xrmmap['areas/%s' % aname] 

1145 new_label = str(self.desc.GetValue()) 

1146 area.attrs['description'] = new_label 

1147 self.owner.current_file.h5root.flush() 

1148 self.set_area_choices(self.owner.current_file.xrmmap) 

1149 self.choice.SetStringSelection(new_label) 

1150 self.desc.SetValue(new_label) 

1151 

1152 def onShow(self, event=None): 

1153 aname = self._getarea() 

1154 area = self.owner.current_file.xrmmap['areas'][aname] 

1155 label = bytes2str(area.attrs.get('description', aname)) 

1156 

1157 if len(self.owner.tomo_displays) > 0: 

1158 imd = self.owner.tomo_displays[-1] 

1159 try: 

1160 imd.add_highlight_area(area[()], label=label) 

1161 except: 

1162 pass 

1163 

1164 if len(self.owner.im_displays) > 0: 

1165 imd = self.owner.im_displays[-1] 

1166 h, w = self.owner.current_file.get_shape() 

1167 highlight = np.zeros((h, w)) 

1168 

1169 highlight[np.where(area[()])] = 1 

1170 imd.panel.add_highlight_area(highlight, label=label) 

1171 

1172 def onDone(self, event=None): 

1173 self.Destroy() 

1174 

1175 def onDelete(self, event=None): 

1176 aname = self._getarea() 

1177 erase = (wx.ID_YES == Popup(self.owner, self.delstr % aname, 

1178 'Delete Area?', style=wx.YES_NO)) 

1179 

1180 if erase: 

1181 xrmmap = self.owner.current_file.xrmmap 

1182 del xrmmap['areas/%s' % aname] 

1183 

1184 self.set_area_choices(xrmmap) 

1185 

1186 self.onSelect() 

1187 

1188 def onClear(self, event=None): 

1189 if len(self.owner.im_displays) > 0: 

1190 imd = self.owner.im_displays[-1] 

1191 try: 

1192 for area in imd.panel.conf.highlight_areas: 

1193 for w in area.collections + area.labelTexts: 

1194 w.remove() 

1195 imd.panel.conf.highlight_areas = [] 

1196 imd.panel.redraw() 

1197 except: 

1198 pass 

1199 

1200 if len(self.owner.tomo_displays) > 0: 

1201 imd = self.owner.tomo_displays[-1] 

1202 try: 

1203 imd.clear_highlight_area() 

1204 except: 

1205 pass 

1206 

1207 def onXRF(self, event=None, as_mca2=False): 

1208 aname = self._getarea() 

1209 xrmfile = self.owner.current_file 

1210 area = xrmfile.xrmmap['areas/%s' % aname] 

1211 

1212 label = bytes2str(area.attrs.get('description', aname)) 

1213 self._mca = None 

1214 self.owner.message("Getting XRF Spectra for area '%s'..." % aname) 

1215 def _getmca_area(aname): 

1216 o = self.owner 

1217 self._mca = o.current_file.get_mca_area(aname, 

1218 dtcorrect=o.dtcor) 

1219 mca_thread = Thread(target=_getmca_area, args=(aname,)) 

1220 mca_thread.start() 

1221 self.owner.show_XRFDisplay() 

1222 mca_thread.join() 

1223 

1224 pref, fname = os.path.split(self.owner.current_file.filename) 

1225 

1226 npix = area[()].sum() 

1227 self._mca.filename = fname 

1228 self._mca.title = label 

1229 self._mca.npixels = npix 

1230 self.owner.message("Plotting XRF Spectra for area '%s'..." % aname) 

1231 self.owner.subframes['xrfdisplay'].add_mca(self._mca, label="%s:%s" % (fname, label), 

1232 plot=not as_mca2) 

1233 if as_mca2: 

1234 self.owner.subframes['xrfdisplay'].swap_mcas() 

1235 

1236 def onXRD(self, event=None, save=False, show=False, 

1237 xrd1d=False, xrd2d=False, verbose=True): 

1238 try: 

1239 aname = self._getarea() 

1240 xrmfile = self.owner.current_file 

1241 area = xrmfile.xrmmap['areas/%s' % aname] 

1242 

1243 title = area.attrs.get('description', aname) 

1244 

1245 env_names = list(xrmfile.xrmmap['config/environ/name']) 

1246 env_vals = list(xrmfile.xrmmap['config/environ/value']) 

1247 for name, val in zip(env_names, env_vals): 

1248 if 'mono.energy' in str(name).lower(): 

1249 energy = float(val)/1000. 

1250 except: 

1251 if verbose: 

1252 print('No map file and/or areas specified.') 

1253 return 

1254 

1255 xrmfile.reset_flags() 

1256 if not xrmfile.has_xrd1d and not xrmfile.has_xrd2d: 

1257 if verbose: 

1258 print('No XRD data in map file: %s' % self.owner.current_file.filename) 

1259 return 

1260 

1261 ponifile = bytes2str(xrmfile.xrmmap['xrd1d'].attrs.get('calfile','')) 

1262 ponifile = ponifile if os.path.exists(ponifile) else None 

1263 

1264 if show: 

1265 self.owner.message('Plotting XRD pattern for \'%s\'...' % title) 

1266 if save: 

1267 self.owner.message('Saving XRD pattern for \'%s\'...' % title) 

1268 path,stem = os.path.split(self.owner.current_file.filename) 

1269 stem = '%s_%s' % (stem,title) 

1270 

1271 kwargs = dict(filename=self.owner.current_file.filename, 

1272 npixels=area[()].sum(), 

1273 energy=0.001*xrmfile.get_incident_energy(), 

1274 calfile=ponifile, title=title, xrd2d=False) 

1275 

1276 if xrd1d and xrmfile.has_xrd1d: 

1277 self._xrd = xrmfile.get_xrd1d_area(aname, **kwargs) 

1278 

1279 if show: 

1280 label = '%s: %s' % (os.path.split(self._xrd.filename)[-1], title) 

1281 self.owner.display_xrd1d(self._xrd.data1D, self._xrd.q, 

1282 self._xrd.energy, label=label) 

1283 if save: 

1284 wildcards = '1D XRD file (*.xy)|*.xy|All files (*.*)|*.*' 

1285 dlg = wx.FileDialog(self, 'Save file as...', 

1286 defaultDir=get_cwd(), 

1287 defaultFile='%s.xy' % stem, 

1288 wildcard=wildcards, 

1289 style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) 

1290 if dlg.ShowModal() == wx.ID_OK: 

1291 filename = dlg.GetPath().replace('\\', '/') 

1292 

1293 dlg.Destroy() 

1294 

1295 print('\nSaving 1D XRD in file: %s' % (filename)) 

1296 save1D(filename, self._xrd.data1D[0], self._xrd.data1D[1], calfile=ponifile) 

1297 

1298 ## turns off flag since it has already been displayed/saved 

1299 xrd1d = False 

1300 

1301 

1302 if xrd2d: 

1303 print("Looking for 2D XRD Data") 

1304 try: 

1305 _xrd = xrmfile.get_xrd2d_area(aname, **kwargs) 

1306 except: 

1307 _xrd = None 

1308 if _xrd is None: 

1309 print("no 2D XRD Data") 

1310 return 

1311 

1312 label = '%s: %s' % (os.path.split(_xrd.filename)[-1], title) 

1313 self.owner.display_2Dxrd(_xrd.data2D, label=label, xrmfile=xrmfile) 

1314 wildcards = '2D XRD file (*.tiff)|*.tif;*.tiff;*.edf|All files (*.*)|*.*' 

1315 fname = xrmfile.filename + '_' + aname 

1316 dlg = wx.FileDialog(self, 'Save file as...', 

1317 defaultDir=get_cwd(), 

1318 defaultFile='%s.tiff' % fname, 

1319 wildcard=wildcards, 

1320 style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) 

1321 if dlg.ShowModal() == wx.ID_OK: 

1322 filename = os.path.abspath(dlg.GetPath().replace('\\', '/')) 

1323 _xrd.save_2D(file=filename, verbose=True) 

1324 dlg.Destroy() 

1325 

1326 

1327class MapViewerFrame(wx.Frame): 

1328 cursor_menulabels = {'lasso': ('Select Points for XRF Spectra\tCtrl+X', 

1329 'Left-Drag to select points for XRF Spectra')} 

1330 

1331 def __init__(self, parent=None, filename=None, _larch=None, 

1332 use_scandb=False, check_version=True, 

1333 size=(925, 650), **kwds): 

1334 

1335 if check_version: 

1336 def check_version(): 

1337 self.vinfo = check_larchversion() 

1338 version_thread = Thread(target=check_version) 

1339 version_thread.start() 

1340 

1341 kwds['style'] = wx.DEFAULT_FRAME_STYLE 

1342 wx.Frame.__init__(self, parent, -1, size=size, **kwds) 

1343 

1344 self.data = None 

1345 self.use_scandb = use_scandb 

1346 self.filemap = {} 

1347 self.im_displays = [] 

1348 self.tomo_displays = [] 

1349 self.plot_displays = [] 

1350 self.current_file = None 

1351 

1352 self.larch_buffer = parent 

1353 if not isinstance(parent, LarchFrame): 

1354 self.larch_buffer = LarchFrame(_larch=_larch, is_standalone=False, with_raise=False) 

1355 

1356 self.larch = self.larch_buffer.larchshell 

1357 

1358 self.subframes = {'xrfdisplay': None, 

1359 'xrd1d': None, 

1360 'xrd2d': None} 

1361 self.watch_files = False 

1362 

1363 self.files_in_progress = [] 

1364 

1365 # self.hotcols = False 

1366 self.dtcor = True 

1367 self.showxrd = False 

1368 

1369 self.SetTitle('GSE XRM MapViewer') 

1370 

1371 self.createMainPanel() 

1372 self.SetFont(Font(FONTSIZE)) 

1373 

1374 self.createMenus() 

1375 self.statusbar = self.CreateStatusBar(2, 0) 

1376 self.statusbar.SetStatusWidths([-3, -1]) 

1377 statusbar_fields = ['Initializing....', ' '] 

1378 for i in range(len(statusbar_fields)): 

1379 self.statusbar.SetStatusText(statusbar_fields[i], i) 

1380 

1381 self.htimer = wx.Timer(self) 

1382 self.Bind(wx.EVT_TIMER, self.onTimer, self.htimer) 

1383 self.h5convert_done = True 

1384 self.h5convert_irow = 0 

1385 self.h5convert_nrow = 0 

1386 

1387 read_workdir('gsemap.dat') 

1388 

1389 w0, h0 = self.GetSize() 

1390 w1, h1 = self.GetBestSize() 

1391 self.SetSize((max(w0, w1)+5, max(h0, h1)+5)) 

1392 self.SetMinSize((500, 300)) 

1393 self.Show() 

1394 

1395 self.scandb = None 

1396 self.instdb = None 

1397 self.inst_name = None 

1398 self.move_callback = None 

1399 

1400 if filename is not None: 

1401 wx.CallAfter(self.onRead, filename) 

1402 

1403 if check_version: 

1404 version_thread.join() 

1405 if self.vinfo is not None: 

1406 if self.vinfo.update_available: 

1407 self.onCheckforUpdates() 

1408 self.statusbar.SetStatusText(f'Larch Version {self.vinfo.remote_version} is available!', 0) 

1409 self.statusbar.SetStatusText(f'Larch Version {self.vinfo.local_version}', 1) 

1410 else: 

1411 self.statusbar.SetStatusText(f'Larch Version {self.vinfo.local_version} (latest)', 1) 

1412 

1413 

1414 def CloseFile(self, filename, event=None): 

1415 if filename in self.filemap: 

1416 self.filemap[filename].close() 

1417 self.filemap.pop(filename) 

1418 

1419 def createMainPanel(self): 

1420 splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) 

1421 splitter.SetMinimumPaneSize(250) 

1422 

1423 self.filelist = EditableListBox(splitter, self.ShowFile, 

1424 remove_action=self.CloseFile, 

1425 size=(250, -1)) 

1426 

1427 dpanel = self.detailspanel = wx.Panel(splitter) 

1428 self.createNBPanels(dpanel) 

1429 splitter.SplitVertically(self.filelist, self.detailspanel, 1) 

1430 sizer = wx.BoxSizer(wx.VERTICAL) 

1431 sizer.Add(splitter, 1, wx.GROW|wx.ALL, 5) 

1432 pack(self, sizer) 

1433 fico = os.path.join(icondir, XRF_ICON_FILE) 

1434 try: 

1435 self.SetIcon(wx.Icon(fico, wx.BITMAP_TYPE_ICO)) 

1436 except: 

1437 pass 

1438 

1439 

1440 self.Raise() 

1441 wx.CallAfter(self.init_larch) 

1442 

1443 def createNBPanels(self, parent): 

1444 self.title = SimpleText(parent, 'initializing...', size=(680, -1)) 

1445 

1446 self.SetBackgroundColour('#F0F0E8') 

1447 

1448 nbpanels = {} 

1449 for panel in (MapPanel, MapInfoPanel, MapAreaPanel, MapMathPanel, 

1450 TomographyPanel, XRFAnalysisPanel): 

1451 nbpanels[panel.label] = panel 

1452 self.nb = flatnotebook(parent, nbpanels, panelkws={'owner':self}, 

1453 on_change=self.onNBChanged) 

1454 self.roimap_panel = self.nb.GetPage(0) 

1455 sizer = wx.BoxSizer(wx.VERTICAL) 

1456 sizer.Add(self.title, 0, ALL_CEN) 

1457 sizer.Add(self.nb, 1, wx.ALL|wx.EXPAND) 

1458 parent.SetSize((700, 400)) 

1459 pack(parent, sizer) 

1460 

1461 def onNBChanged(self, event=None): 

1462 cb = getattr(self.nb.GetCurrentPage(), 'update_xrmmap', None) 

1463 if callable(cb): 

1464 cb() 

1465 

1466 def get_mca_area(self, mask, xoff=0, yoff=0, det=None, xrmfile=None): 

1467 if xrmfile is None: 

1468 xrmfile = self.current_file 

1469 

1470 if xrmfile.write_access: 

1471 aname = xrmfile.add_area(mask) 

1472 self.sel_mca = xrmfile.get_mca_area(aname, det=det) 

1473 else: 

1474 dgroup = xrmfile.get_detname(det) 

1475 _ay, _ax = np.where(mask) 

1476 ymin, ymax, xmin, xmax = _ay.min(), _ay.max()+1, _ax.min(), _ax.max()+1 

1477 opts = {'dtcorrect': None, 'det': det} 

1478 counts = xrmfile.get_counts_rect(ymin, ymax, xmin, xmax, det=det) 

1479 ltime, rtime = xrmfile.get_livereal_rect(ymin, ymax, xmin, 

1480 xmax, det=det) 

1481 ltime = ltime[mask[ymin:ymax, xmin:xmax]].sum() 

1482 rtime = rtime[mask[ymin:ymax, xmin:xmax]].sum() 

1483 counts = counts[mask[ymin:ymax, xmin:xmax]] 

1484 while(len(counts.shape) > 1): 

1485 counts = counts.sum(axis=0) 

1486 self.sel_mca = xrmfile._getmca(dgroup, counts, 'selected area', 

1487 npixels=mask.sum(), 

1488 real_time=rtime, live_time=ltime) 

1489 

1490 

1491 def lassoHandler(self, mask=None, xrmfile=None, xoff=0, yoff=0, 

1492 det=None, **kws): 

1493 if xrmfile is None: 

1494 xrmfile = self.current_file 

1495 

1496 ny, nx = xrmfile.get_shape() 

1497 if mask.sum() < 1: 

1498 return 

1499 

1500 if (xoff>0 or yoff>0) or mask.shape != (ny, nx): 

1501 if mask.shape == (nx, ny): ## sinogram 

1502 mask = np.swapaxes(mask,0,1) 

1503 # elif mask.shape == (ny, ny) or mask.shape == (nx, nx): ## tomograph 

1504 # tomo = True 

1505 else: 

1506 ym, xm = mask.shape 

1507 tmask = np.zeros((ny, nx)).astype(bool) 

1508 xmax = min(nx, xm+xoff) 

1509 for iy in range(ym): 

1510 if iy+yoff < ny: 

1511 tmask[iy+yoff, xoff:xmax] = mask[iy] 

1512 mask = tmask 

1513 

1514 kwargs = dict(xrmfile=xrmfile, xoff=xoff, yoff=yoff, det=det) 

1515 mca_thread = Thread(target=self.get_mca_area, 

1516 args=(mask,), kwargs=kwargs) 

1517 mca_thread.start() 

1518 self.show_XRFDisplay() 

1519 mca_thread.join() 

1520 if hasattr(self, 'sel_mca'): 

1521 path, fname = os.path.split(xrmfile.filename) 

1522 aname = self.sel_mca.areaname 

1523 if self.sel_mca.npixels is None: 

1524 try: 

1525 area = xrmfile.xrmmap['areas/%s' % aname] 

1526 npix = area[()].sum() 

1527 self.sel_mca.npixels = npix 

1528 except: 

1529 pass 

1530 

1531 if self.sel_mca.npixels is None: 

1532 self.sel_mca.npixels = 0 

1533 self.sel_mca.filename = fname 

1534 self.sel_mca.title = aname 

1535 self.subframes['xrfdisplay'].add_mca(self.sel_mca, label='%s:%s'% (fname, aname), 

1536 plot=True) 

1537 self.subframes['xrfdisplay'].roi_callback = self.UpdateROI 

1538 update_xrmmap = getattr(self.nb.GetCurrentPage(), 'update_xrmmap', None) 

1539 if callable(update_xrmmap): 

1540 update_xrmmap(xrmfile=self.current_file) 

1541 

1542 if self.showxrd: 

1543 for page in self.nb.pagelist: 

1544 if hasattr(page, 'onXRD'): 

1545 page.onXRD(show=True, xrd1d=True,verbose=False) 

1546 

1547 def show_subframe(self, name, frameclass, **opts): 

1548 shown = False 

1549 if name in self.subframes: 

1550 try: 

1551 self.subframes[name].Raise() 

1552 shown = True 

1553 except: 

1554 del self.subframes[name] 

1555 if not shown: 

1556 self.subframes[name] = frameclass(self, **opts) 

1557 

1558 def show_XRD1D(self, event=None): 

1559 self.show_subframe('xrd1d', XRD1DFrame, _larch=self.larch) 

1560 

1561 def show_XRD2D(self, event=None): 

1562 self.show_subframe('xrd2d', XRD1DFrame, _larch=self.larch) 

1563 

1564 

1565 def show_XRFDisplay(self, do_raise=True, clear=True, xrmfile=None): 

1566 'make sure XRF plot frame is enabled and visible' 

1567 if xrmfile is None: 

1568 xrmfile = self.current_file 

1569 self.show_subframe('xrfdisplay', XRFDisplayFrame, 

1570 parent=self.larch_buffer, 

1571 roi_callback=self.UpdateROI) 

1572 

1573 self.subframes['xrfdisplay'].Show() 

1574 if do_raise: 

1575 self.subframes['xrfdisplay'].Raise() 

1576 if clear: 

1577 self.subframes['xrfdisplay'].panel.clear() 

1578 self.subframes['xrfdisplay'].panel.reset_config() 

1579 

1580 def onMoveToPixel(self, xval, yval): 

1581 if not HAS_EPICS: 

1582 return 

1583 

1584 xrmmap = self.current_file.xrmmap 

1585 pos_addrs = [str(x) for x in xrmmap['config/positioners'].keys()] 

1586 pos_label = [str(x[()]) for x in xrmmap['config/positioners'].values()] 

1587 

1588 pos1 = h5str(xrmmap['config/scan/pos1'][()]) 

1589 pos2 = h5str(xrmmap['config/scan/pos2'][()]) 

1590 i1 = pos_addrs.index(pos1) 

1591 i2 = pos_addrs.index(pos2) 

1592 msg = '%s(%s) = %.4f, %s(%s) = %.4f?' % (pos_label[i1], pos_addrs[i1], xval, 

1593 pos_label[i2], pos_addrs[i2], yval) 

1594 

1595 if (wx.ID_YES == Popup(self, 'Really move stages to\n %s?' % msg, 

1596 'move stages to pixel?', style=wx.YES_NO)): 

1597 caput(pos_addrs[i1], xval) 

1598 caput(pos_addrs[i2], yval) 

1599 

1600 def onSavePixel(self, name, ix, iy, x=None, y=None, title=None, xrmfile=None): 

1601 'save pixel as area, and perhaps to scandb' 

1602 if x is None: 

1603 x = float(xrmfile.get_pos(0, mean=True)[ix]) 

1604 if y is None: 

1605 y = float(xrmfile.get_pos(1, mean=True)[iy]) 

1606 

1607 if len(name) < 1: 

1608 return 

1609 if xrmfile is None: 

1610 xrmfile = self.current_file 

1611 

1612 # first, create 1-pixel mask for area, and save that 

1613 ny, nx = xrmfile.get_shape() 

1614 tmask = np.zeros((ny, nx)).astype(bool) 

1615 tmask[int(iy), int(ix)] = True 

1616 xrmfile.add_area(tmask, name=name) 

1617 # for page in self.nb.pagelist: 

1618 # if hasattr(page, 'update_xrmmap'): 

1619 # page.update_xrmmap(xrmfile=xrmfile) 

1620 update_xrmmap = getattr(self.nb.GetCurrentPage(), 'update_xrmmap', None) 

1621 if callable(update_xrmmap): 

1622 update_xrmmap(xrmfile=xrmfile) 

1623 

1624 # show position on map 

1625 self.im_displays[-1].panel.add_highlight_area(tmask, label=name) 

1626 

1627 # make sure we can save position into database 

1628 if self.scandb is None or self.instdb is None: 

1629 return 

1630 samplestage = self.instdb.get_instrument(self.inst_name) 

1631 if samplestage is None: 

1632 return 

1633 pvmap = dict([(r.id, r.name) for r in self.scandb.get_rows('pv')]) 

1634 

1635 pv_rows = self.scandb.get_rows('instrument_pv', 

1636 where={'instrument_id': samplestage.id}) 

1637 

1638 allpvs = [] 

1639 for row in pv_rows: 

1640 for pvid, pvname in pvmap.items(): 

1641 if pvid == row.pv_id: 

1642 allpvs.append(pvname) 

1643 

1644 pvn = pv_fullname 

1645 conf = xrmfile.xrmmap['config'] 

1646 pos_addrs = [pvn(h5str(tval)) for tval in conf['positioners']] 

1647 env_addrs = [pvn(h5str(tval)) for tval in conf['environ/address']] 

1648 env_vals = [h5str(tval) for tval in conf['environ/value']] 

1649 

1650 position = {} 

1651 for pv in allpvs: 

1652 position[pv] = None 

1653 

1654 for addr, val in zip(env_addrs, env_vals): 

1655 if addr in allpvs: 

1656 position[addr] = float(val) 

1657 

1658 position[pvn(h5str(conf['scan/pos1'][()]))] = x 

1659 position[pvn(h5str(conf['scan/pos2'][()]))] = y 

1660 

1661 notes = {'source': '%s: %s' % (xrmfile.filename, name)} 

1662 self.instdb.save_position(self.inst_name, name, position, 

1663 notes=json.dumps(notes)) 

1664 

1665 

1666 def add_tomodisplay(self, title, det=None, _lassocallback=True): 

1667 

1668 if _lassocallback: 

1669 lasso_cb = partial(self.lassoHandler, det=det) 

1670 else: 

1671 lasso_cb = None 

1672 

1673 imframe = MapImageFrame(output_title=title, 

1674 lasso_callback=lasso_cb) 

1675 

1676 self.tomo_displays.append(imframe) 

1677 

1678 def display_tomo(self, tomo, title='', info='', x=None, y=None, xoff=0, 

1679 yoff=0, det=None, subtitles=None, xrmfile=None, 

1680 _lassocallback=True): 

1681 

1682 displayed = False 

1683 if _lassocallback: 

1684 lasso_cb = partial(self.lassoHandler, det=det, xrmfile=xrmfile) 

1685 else: 

1686 lasso_cb = None 

1687 

1688 while not displayed: 

1689 try: 

1690 tmd = self.tomo_displays.pop() 

1691 clevel = tmd.panel.conf.contrast_level 

1692 if clevel in (0, None): 

1693 clevel = 0.5 

1694 tmd.display(tomo, title=title, subtitles=subtitles, 

1695 contrast_level=clevel) 

1696 tmd.lasso_callback = lasso_cb 

1697 displayed = True 

1698 except IndexError: 

1699 tmd = MapImageFrame(output_title=title, 

1700 lasso_callback=lasso_cb) 

1701 tmd.display(tomo, title=title, subtitles=subtitles, 

1702 contrast_level=0.5) 

1703 displayed = True 

1704 except: 

1705 displayed = False 

1706 self.tomo_displays.append(tmd) 

1707 tmd.SetStatusText(info, 1) 

1708 tmd.Show() 

1709 tmd.Raise() 

1710 

1711 def add_imdisplay(self, title, det=None): 

1712 imd = MapImageFrame(output_title=title, 

1713 lasso_callback=partial(self.lassoHandler, det=det), 

1714 cursor_labels=self.cursor_menulabels, 

1715 save_callback=self.onSavePixel) 

1716 self.im_displays.append(imd) 

1717 return imd 

1718 

1719 def display_map(self, map, title='', info='', x=None, y=None, xoff=0, yoff=0, 

1720 det=None, subtitles=None, xrmfile=None, with_savepos=True): 

1721 """display a map in an available image display""" 

1722 if xrmfile is None: 

1723 hotcols = False 

1724 else: 

1725 hotcols = xrmfile.hotcols 

1726 

1727 if x is not None: 

1728 zigzag = abs(xrmfile.zigzag) 

1729 if zigzag != 0: 

1730 x = x[zigzag:-zigzag] 

1731 elif hotcols and map.shape[1] != x.shape[0]: 

1732 x = x[1:-1] 

1733 

1734 dopts = dict(title=title, x=x, y=y, xoff=xoff, yoff=yoff, 

1735 det=det, subtitles=subtitles, 

1736 xrmfile=xrmfile, with_savepos=with_savepos) 

1737 displayed = False 

1738 while not displayed: 

1739 if 'contrast_level' not in dopts: 

1740 dopts['contrast_level'] = 0.5 

1741 if len(self.im_displays) == 0: 

1742 imd = self.add_imdisplay(title=title, det=det) 

1743 imd.display(map, **dopts) 

1744 else: 

1745 try: 

1746 imd = self.im_displays[-1] 

1747 if imd.panel.conf.contrast_level not in (0, None): 

1748 dopts['contrast_level'] = imd.panel.conf.contrast_level 

1749 imd.display(map, **dopts) 

1750 displayed = True 

1751 except IndexError: 

1752 pass 

1753 except: 

1754 self.im_displays.pop() 

1755 imd.SetStatusText(info, 1) 

1756 imd.Show() 

1757 imd.Raise() 

1758 

1759 def display_2Dxrd(self, map, label='image 0', xrmfile=None, flip=True): 

1760 ''' 

1761 displays 2D XRD pattern in diFFit viewer 

1762 ''' 

1763 xrmfile = self.current_file 

1764 ponifile = bytes2str(xrmfile.xrmmap['xrd1d'].attrs.get('calfile','')) 

1765 if len(ponifile) < 2 or not os.path.exists(ponifile): 

1766 t_ponifile = os.path.join(xrmfile.folder, 'XRD.poni') 

1767 if os.path.exists(t_ponifile): 

1768 ponifile = t_ponifile 

1769 if os.path.exists(ponifile): 

1770 self.current_file.xrmmap['xrd1d'].attrs['calfile'] = ponifile 

1771 

1772 self.show_XRD2D() 

1773 self.show_XRD1D() 

1774 self.subframes['xrd2d'].flip = 'vertical' if flip is True else False 

1775 self.subframes['xrd2d'].calfile = ponifile 

1776 self.subframes['xrd2d'].plot2Dxrd(label, map) 

1777 self.subframes['xrd2d'].Show() 

1778 

1779 def display_xrd1d(self, counts, q, energy, label='dataset 0', xrmfile=None): 

1780 ''' 

1781 displays 1D XRD pattern in diFFit viewer 

1782 ''' 

1783 wavelength = lambda_from_E(energy, E_units='keV') 

1784 xdat = xrd1d(label=label, energy=energy, wavelength=wavelength) 

1785 xdat.set_xy_data(np.array([q, counts]), 'q') 

1786 

1787 xrmfile = self.current_file 

1788 ponidata = json.loads(bytes2str(xrmfile.xrmmap['xrd1d'].attrs.get('caldata','{}'))) 

1789 if 'rot1' not in ponidata: # invalid poni data 

1790 ponifile = bytes2str(xrmfile.xrmmap['xrd1d'].attrs.get('calfile','')) 

1791 if len(ponifile) < 2 or not os.path.exists(ponifile): 

1792 t_ponifile = os.path.join(xrmfile.folder, 'XRD.poni') 

1793 if os.path.exists(t_ponifile): 

1794 ponifile = t_ponifile 

1795 if len(ponifile) > 1: 

1796 ponidata = read_poni(ponifile) 

1797 if 'rot1' in ponidata: 

1798 xrmfile.xrmmap['xrd1d'].attrs['caldata'] = json.dumps(ponidata) 

1799 self.show_XRD1D() 

1800 self.subframes['xrd1d'].set_wavelength(wavelength) 

1801 if 'rot1' in ponidata: 

1802 self.subframes['xrd1d'].set_poni(ponidata) 

1803 

1804 self.subframes['xrd1d'].add_data(xdat, label=label) 

1805 self.subframes['xrd1d'].Show() 

1806 

1807 def init_larch(self): 

1808 self.SetStatusText('ready') 

1809 self.datagroups = self.larch.symtable 

1810 if ESCAN_CRED is not None: 

1811 self.move_callback = self.onMoveToPixel 

1812 try: 

1813 self.scandb = connect_scandb(_larch=self.larch) 

1814 self.instdb = self.larch.symtable._scan._instdb 

1815 self.inst_name = self.scandb.get_info('samplestage_instrument', 

1816 default='SampleStage') 

1817 print(" ScanDB: %s, Instrument=%s" % (self.scandb.engine, self.inst_name)) 

1818 except: 

1819 etype, emsg, tb = sys.exc_info() 

1820 print('Could not connect to ScanDB: %s' % (emsg)) 

1821 self.scandb = self.instdb = None 

1822 wx.CallAfter(self.onFolderSelect) 

1823 

1824 def ShowFile(self, evt=None, filename=None, process_file=True, **kws): 

1825 if filename is None and evt is not None: 

1826 filename = evt.GetString() 

1827 if not self.h5convert_done or filename not in self.filemap: 

1828 return 

1829 self.current_file = self.filemap[filename] 

1830 if (self.check_ownership(filename) and 

1831 self.current_file.folder_has_newdata()): 

1832 if process_file: 

1833 mnew = self.roimap_panel.mapproc_nrows.GetStringSelection() 

1834 try: 

1835 mnew = int(mnew) 

1836 except: 

1837 mnew = None 

1838 self.process_file(filename, max_new_rows=mnew) 

1839 

1840 ny, nx = self.current_file.get_shape() 

1841 self.title.SetLabel('%s: (%i x %i)' % (filename, nx, ny)) 

1842 

1843 fnames = self.filelist.GetItems() 

1844 

1845 cb = getattr(self.nb.GetCurrentPage(), 'update_xrmmap', None) 

1846 if callable(cb): 

1847 cb(xrmfile=self.current_file) 

1848 cb = getattr(self.nb.GetCurrentPage(), 'set_file_choices', None) 

1849 if callable(cb): 

1850 cb(fnames) 

1851 

1852 def createMenus(self): 

1853 self.menubar = wx.MenuBar() 

1854 fmenu = wx.Menu() 

1855 

1856 MenuItem(self, fmenu, '&Open XRM Map File\tCtrl+O', 'Read XRM Map File', self.onReadFile) 

1857 MenuItem(self, fmenu, '&Open XRM Map Folder\tCtrl+F', 'Read XRM Map Folder', self.onReadFolder) 

1858 fmenu.AppendSeparator() 

1859 MenuItem(self, fmenu, 'Change &Working Folder', 'Choose working directory', 

1860 self.onFolderSelect) 

1861 MenuItem(self, fmenu, 'Show Larch Buffer\tCtrl+L', 'Show Larch Programming Buffer', 

1862 self.onShowLarchBuffer) 

1863 

1864 # cmenu = fmenu.Append(-1, '&Watch HDF5 Files\tCtrl+W', 'Watch HDF5 Files', kind=wx.ITEM_CHECK) 

1865 # fmenu.Check(cmenu.Id, self.watch_files) ## False 

1866 # self.Bind(wx.EVT_MENU, self.onWatchFiles, id=cmenu.Id) 

1867 

1868 fmenu.AppendSeparator() 

1869 MenuItem(self, fmenu, '&Quit\tCtrl+Q', 

1870 'Quit program', self.onClose) 

1871 

1872 rmenu = wx.Menu() 

1873 MenuItem(self, rmenu, 'Add / Delete ROIs', 

1874 'Define new ROIs, Remove ROIs', self.manageROIs) 

1875 MenuItem(self, rmenu, 'Load ROI File for 1DXRD', 

1876 'Load ROI File for 1DXRD', self.add1DXRDFile) 

1877 rmenu.AppendSeparator() 

1878 MenuItem(self, rmenu, 'Load XRD calibration file', 

1879 'Load XRD calibration file', self.openPONI) 

1880 MenuItem(self, rmenu, 'Add 1DXRD for HDF5 file', 

1881 'Calculate 1DXRD for HDF5 file', self.add1DXRD) 

1882 

1883 

1884 # cmenu = fmenu.Append(-1, 'Display 1DXRD for areas', 

1885 # 'Display 1DXRD for areas', 

1886 # kind=wx.ITEM_CHECK) 

1887 #fmenu.Check(cmenu.Id, self.showxrd) ## False 

1888 #self.Bind(wx.EVT_MENU, self.onShow1DXRD, id=cmenu.Id) 

1889 

1890 hmenu = wx.Menu() 

1891 MenuItem(self, hmenu, 'About GSE XRM MapViewer', 'About GSE XRM MapViewer', 

1892 self.onAbout) 

1893 MenuItem(self, hmenu, 'Check for Updates', 'Check for Updates', 

1894 self.onCheckforUpdates) 

1895 

1896 self.menubar.Append(fmenu, '&File') 

1897 self.menubar.Append(rmenu, '&ROIs') 

1898 self.menubar.Append(hmenu, '&Help') 

1899 self.SetMenuBar(self.menubar) 

1900 self.Bind(wx.EVT_CLOSE, self.onClose) 

1901 

1902 def onShowLarchBuffer(self, evt=None): 

1903 if self.larch_buffer is None: 

1904 self.larch_buffer = LarchFrame(_larch=self.larch, is_standalone=False) 

1905 

1906 self.larch_buffer.Show() 

1907 self.larch_buffer.Raise() 

1908 

1909 def onFolderSelect(self, evt=None): 

1910 dlg = wx.DirDialog(self, 'Select Working Directory:', 

1911 get_cwd(), 

1912 style=wx.DD_DIR_MUST_EXIST|wx.DD_DEFAULT_STYLE) 

1913 

1914 if dlg.ShowModal() == wx.ID_OK: 

1915 basedir = os.path.abspath(str(dlg.GetPath())) 

1916 try: 

1917 if len(basedir) > 0: 

1918 os.chdir(nativepath(basedir)) 

1919 save_workdir(nativepath(basedir)) 

1920 except OSError: 

1921 print( 'Changed folder failed') 

1922 pass 

1923 save_workdir('gsemap.dat') 

1924 dlg.Destroy() 

1925 

1926 def onAbout(self, event=None): 

1927 info = AboutDialogInfo() 

1928 info.SetName('GSE XRM MapViewer') 

1929 info.SetDescription('X-ray Microprobe Mapping Data Visualization and Analysis') 

1930 info.SetVersion(larch.version.__version__) 

1931 info.AddDeveloper('Matthew Newville: newville at cars.uchicago.edu') 

1932 dlg = AboutBox(info) 

1933 

1934 def onCheckforUpdates(self, event=None): 

1935 dlg = LarchUpdaterDialog(self, caller='GSE MapViewer') 

1936 dlg.Raise() 

1937 dlg.SetWindowStyle(wx.STAY_ON_TOP) 

1938 res = dlg.GetResponse() 

1939 dlg.Destroy() 

1940 if res.ok and res.run_updates: 

1941 from larch.apps import update_larch 

1942 update_larch() 

1943 self.onClose(evt=event, prompt=False) 

1944 

1945 def onClose(self, evt=None, prompt=True): 

1946 if prompt: 

1947 dlg = wx.MessageDialog(None, 'Really Quit?', 'Question', 

1948 wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) 

1949 

1950 ret = dlg.ShowModal() 

1951 if ret != wx.ID_YES: 

1952 return 

1953 

1954 save_workdir('gsemap.dat') 

1955 try: 

1956 self.htimer.Stop() 

1957 except: 

1958 pass 

1959 try: 

1960 self.file_timer.Stop() 

1961 except: 

1962 pass 

1963 

1964 

1965 for xrmfile in self.filemap.values(): 

1966 try: 

1967 xrmfile.close() 

1968 except KeyError: 

1969 pass 

1970 

1971 try: 

1972 self.larch.symtable._plotter.close_all_displays() 

1973 except: 

1974 pass 

1975 

1976 ## Closes maps, 2D XRD image 

1977 for disp in self.im_displays + self.plot_displays + self.tomo_displays: 

1978 try: 

1979 disp.Destroy() 

1980 except: 

1981 pass 

1982 

1983 for key, wid in self.subframes.items(): 

1984 if wid is not None: 

1985 try: 

1986 wid.onClose() 

1987 except: 

1988 pass 

1989 if self.larch_buffer is not None: 

1990 self.larch_buffer.exit_on_close = True 

1991 self.larch_buffer.onExit(force=True, with_sysexit=False) 

1992 self.Destroy() 

1993 

1994 def onReadFile(self, evt=None): 

1995 if not self.h5convert_done: 

1996 print('cannot open file while processing a map folder') 

1997 return 

1998 

1999 dlg = wx.FileDialog(self, message='Read XRM Map File', 

2000 defaultDir=get_cwd(), 

2001 wildcard=FILE_WILDCARDS, 

2002 style=wx.FD_OPEN|wx.FD_MULTIPLE) 

2003 path, read = None, False 

2004 if dlg.ShowModal() == wx.ID_OK: 

2005 read = True 

2006 paths = [p.replace('\\', '/') for p in dlg.GetPaths()] 

2007 dlg.Destroy() 

2008 

2009 if not read: 

2010 return 

2011 

2012 for path in paths: 

2013 parent, fname = os.path.split(path) 

2014 read = True 

2015 if fname in self.filemap: 

2016 read = (wx.ID_YES == Popup(self, "Re-read file '%s'?" % path, 

2017 'Re-read file?', style=wx.YES_NO)) 

2018 if read: 

2019 xrmfile = GSEXRM_MapFile(filename=str(path), scandb=self.scandb) 

2020 self.add_xrmfile(xrmfile) 

2021 

2022 def onRead(self, path): 

2023 "simple Read and install XRM Map File" 

2024 xrmfile = GSEXRM_MapFile(filename=str(path), scandb=self.scandb) 

2025 self.add_xrmfile(xrmfile) 

2026 

2027 def onReadFolder(self, evt=None): 

2028 if not self.h5convert_done: 

2029 print( 'cannot open file while processing a map folder') 

2030 return 

2031 

2032 dlg = wx.DirDialog(self, message='Read XRM Map Folder', 

2033 defaultPath=get_cwd(), 

2034 style=wx.DD_DIR_MUST_EXIST|wx.DD_DEFAULT_STYLE) 

2035 

2036 if dlg.ShowModal() == wx.ID_OK: 

2037 folder = os.path.abspath(dlg.GetPath()) 

2038 dlg.Destroy() 

2039 

2040 xrmfile = GSEXRM_MapFile(folder=folder, scandb=self.scandb) 

2041 self.add_xrmfile(xrmfile) 

2042 

2043 

2044 def add_xrmfile(self, xrmfile): 

2045 parent, fname = os.path.split(xrmfile.filename) 

2046 # print("Add XRM File ", fname) 

2047 # look for group with this name or for next available group 

2048 for i in range(1000): 

2049 gname = 'map%3.3i' % (i+1) 

2050 xgroup = getattr(self.datagroups, gname, None) 

2051 if xgroup is None: 

2052 break 

2053 gpar, gfname = os.path.split(xgroup.filename) 

2054 if gfname == fname: 

2055 break 

2056 

2057 setattr(self.datagroups, gname, xrmfile) 

2058 xrmfile.groupname = gname 

2059 

2060 if fname not in self.filemap: 

2061 self.filemap[fname] = xrmfile 

2062 if fname not in self.filelist.GetItems(): 

2063 self.filelist.Append(fname) 

2064 self.filelist.SetStringSelection(fname) 

2065 

2066 if self.check_ownership(fname): 

2067 mnew = self.roimap_panel.mapproc_nrows.GetStringSelection() 

2068 try: 

2069 mnew = int(mnew) 

2070 except: 

2071 mnew = None 

2072 self.process_file(fname, max_new_rows=mnew) 

2073 

2074 self.ShowFile(filename=fname) 

2075 if parent is not None and len(parent) > 0: 

2076 try: 

2077 os.chdir(nativepath(parent)) 

2078 save_workdir(nativepath(parent)) 

2079 except: 

2080 pass 

2081 

2082 def openPONI(self, evt=None): 

2083 """ 

2084 Read specified poni file. 

2085 mkak 2016.07.21 

2086 """ 

2087 

2088 if len(self.filemap) > 0: 

2089 myDlg = OpenPoniFile() 

2090 read = False 

2091 if myDlg.ShowModal() == wx.ID_OK: 

2092 read = True 

2093 path = myDlg.XRDInfo[1].GetValue() 

2094 flip = False if myDlg.XRDInfo[0].GetSelection() == 1 else True 

2095 myDlg.Destroy() 

2096 

2097 if read: 

2098 self.current_file.add_XRDfiles(xrdcalfile=path,flip=flip) 

2099 update_xrmmap = getattr(self.nb.GetCurrentPage(), 

2100 'update_xrmmap', None) 

2101 if callable(update_xrmmap): 

2102 update_xrmmap(xrmfile=self.current_file) 

2103 

2104 def UpdateROI(self, name, xrange=None, action='add', units='keV', roitype='XRF'): 

2105 "add or remove an ROI with name, range" 

2106 cfile = self.current_file 

2107 if xrange is None: xrange = [1, 2] 

2108 if roitype == 'XRF': 

2109 if action.startswith('del'): 

2110 cfile.del_xrfroi(name) 

2111 else: 

2112 cfile.add_xrfroi(name, xrange, unit=units) 

2113 

2114 if roitype == '1DXRD': 

2115 if action.startswith('del'): 

2116 cfile.del_xrd1droi(name) 

2117 else: 

2118 cfile.add_xrd1droi(name, xrange, unit=units) 

2119 

2120 self.current_file.get_roi_list('mcasum', force=True) 

2121 for page in self.nb.pagelist: 

2122 if hasattr(page, 'update_xrmmap'): 

2123 page.update_xrmmap(xrmfile=self.current_file) 

2124 if hasattr(page, 'set_roi_choices'): 

2125 page.set_roi_choices() 

2126 

2127 def manageROIs(self, event=None): 

2128 if not self.h5convert_done: 

2129 print( 'cannot open file while processing a map folder') 

2130 elif len(self.filemap) > 0: 

2131 ROIDialog(self, roi_callback=self.UpdateROI).Show() 

2132 

2133 def add1DXRDFile(self, event=None): 

2134 if len(self.filemap) > 0: 

2135 read = False 

2136 wildcards = '1D-XRD ROI file (*.dat)|*.dat|All files (*.*)|*.*' 

2137 dlg = wx.FileDialog(self, message='Select 1D-XRD ROI file', 

2138 defaultDir=get_cwd(), 

2139 wildcard=wildcards, 

2140 style=wx.FD_OPEN) 

2141 

2142 if dlg.ShowModal() == wx.ID_OK: 

2143 read = True 

2144 path = dlg.GetPath().replace('\\', '/') 

2145 dlg.Destroy() 

2146 

2147 if read and os.path.exists(path): 

2148 time.sleep(1) ## will hopefully allow time for dialog window to close 

2149 self.current_file.read_xrd1D_ROIFile(path) 

2150 

2151 def add1DXRD(self, event=None): 

2152 

2153 if len(self.filemap) > 0: 

2154 xrd1Dgrp = ensure_subgroup('xrd1d',self.current_file.xrmmap) 

2155 poni_path = bytes2str(xrd1Dgrp.attrs.get('calfile','')) 

2156 

2157 if not os.path.exists(poni_path): 

2158 self.openPONI() 

2159 poni_path = bytes2str(xrd1Dgrp.attrs.get('calfile','')) 

2160 

2161 if os.path.exists(poni_path): 

2162 self.current_file.add_xrd1d() 

2163 

2164 def onShow1DXRD(self, event=None): 

2165 self.showxrd = event.IsChecked() 

2166 if self.showxrd: 

2167 msg = 'Show 1DXRD data for area' 

2168 else: 

2169 msg = 'Not displaying 1DXRD for area' 

2170 self.message(msg) 

2171 ##print(msg) 

2172 

2173# def onCorrectDeadtime(self, event=None): 

2174# self.dtcor = event.IsChecked() 

2175# if self.dtcor: 

2176# msg = 'Using deadtime corrected data...' 

2177# else: 

2178# msg = 'Using raw data...' 

2179# self.message(msg) 

2180# ##print(msg) 

2181# 

2182# def onHotColumns(self, event=None): 

2183# self.hotcols = event.IsChecked() 

2184# if self.hotcols: 

2185# msg = 'Ignoring first/last data columns.' 

2186# else: 

2187# msg = 'Using all data columns' 

2188# self.message(msg) 

2189# ##print(msg) 

2190 

2191 def onWatchFiles(self, event=None): 

2192 self.watch_files = event.IsChecked() 

2193 if not self.watch_files: 

2194 self.file_timer.Stop() 

2195 msg = 'Watching Files/Folders for Changes: Off' 

2196 else: 

2197 self.file_timer.Start(10000) 

2198 msg = 'Watching Files/Folders for Changes: On' 

2199 self.message(msg) 

2200 

2201 def onFileWatchTimer(self, event=None): 

2202 if self.current_file is not None and len(self.files_in_progress) == 0: 

2203 if self.current_file.folder_has_newdata(): 

2204 path, fname = os.path.split(self.current_file.filename) 

2205 self.process_file(fname, max_new_rows=1e6) 

2206 

2207 def process_file(self, filename, max_new_rows=None, on_complete=None): 

2208 """Request processing of map file. 

2209 This can take awhile, so is done in a separate thread, 

2210 with updates displayed in message bar 

2211 """ 

2212 xrmfile = self.filemap[filename] 

2213 if xrmfile.status == GSEXRM_FileStatus.created: 

2214 xrmfile.initialize_xrmmap(callback=self.updateTimer) 

2215 

2216 if xrmfile.dimension is None and isGSEXRM_MapFolder(self.folder): 

2217 xrmfile.read_master() 

2218 

2219 # print("PROCESS_FILE!!", xrmfile.folder_has_newdata(), self.h5convert_done, 

2220 # filename in self.files_in_progress) 

2221 

2222 if (xrmfile.folder_has_newdata() and self.h5convert_done 

2223 and filename not in self.files_in_progress): 

2224 

2225 self.files_in_progress.append(filename) 

2226 self.h5convert_fname = filename 

2227 self.h5convert_done = False 

2228 self.h5convert_oncomplete = on_complete 

2229 self.htimer.Start(500) 

2230 maxrow = None 

2231 if max_new_rows is not None: 

2232 maxrow = max_new_rows + xrmfile.last_row + 1 

2233 

2234 ## this calls process function of xrm_mapfile class 

2235 self.h5convert_thread = Thread(target=xrmfile.process, 

2236 kwargs={'callback':self.updateTimer, 

2237 'maxrow': maxrow}) 

2238 self.h5convert_thread.start() 

2239 elif callable(on_complete): 

2240 on_complete() 

2241 

2242 def updateTimer(self, row=None, maxrow=None, filename=None, status=None): 

2243 # print("== UPDATE TIMER ", row, maxrow, filename, status) 

2244 if row is not None: self.h5convert_irow = row 

2245 if maxrow is not None: self.h5convert_nrow = maxrow 

2246 if filename is not None: self.h5convert_fname = filename 

2247 self.h5convert_done = True if status == 'complete' else False 

2248 msg = 'processing %s: row %i of %i' % (self.h5convert_fname, 

2249 self.h5convert_irow, 

2250 self.h5convert_nrow) 

2251 wx.CallAfter(self.message, msg) 

2252 

2253 def onTimer(self, event=None): 

2254 if self.h5convert_done: 

2255 # print("h5convert done, stopping timer") 

2256 fname = self.h5convert_fname 

2257 irow, nrow = self.h5convert_irow, self.h5convert_nrow 

2258 self.htimer.Stop() 

2259 self.h5convert_thread.join() 

2260 self.files_in_progress = [] 

2261 self.message('MapViewer processing %s: complete!' % fname) 

2262 _path, _fname = os.path.split(fname) 

2263 if _fname in self.filemap: 

2264 cfile = self.current_file = self.filemap[_fname] 

2265 ny, nx = cfile.get_shape() 

2266 self.title.SetLabel('%s: (%i x %i)' % (_fname, nx, ny)) 

2267 update_xrmmap = getattr(self.nb.GetCurrentPage(), 

2268 'update_xrmmap', None) 

2269 if callable(update_xrmmap) and _fname in self.filemap: 

2270 update_xrmmap(xrmfile=cfile) 

2271 if self.h5convert_oncomplete is not None: 

2272 self.h5convert_oncomplete() 

2273 

2274 

2275 def message(self, msg, win=0): 

2276 self.statusbar.SetStatusText(msg, win) 

2277 

2278 def check_ownership(self, fname): 

2279 """ 

2280 check whether we're currently owner of the file. 

2281 this is important!! HDF5 files can be corrupted. 

2282 """ 

2283 if not self.filemap[fname].check_hostid(): 

2284 if (wx.ID_YES == Popup(self, NOT_OWNER_MSG % fname, 

2285 'Not Owner of HDF5 File', 

2286 style=wx.YES_NO)): 

2287 self.filemap[fname].take_ownership() 

2288 return self.filemap[fname].check_hostid() 

2289 

2290class OpenPoniFile(wx.Dialog): 

2291 """""" 

2292 

2293 #---------------------------------------------------------------------- 

2294 def __init__(self): 

2295 

2296 """Constructor""" 

2297 dialog = wx.Dialog.__init__(self, None, title='XRD Calibration File', size=(350, 280)) 

2298 

2299 panel = wx.Panel(self) 

2300 

2301 ################################################################################ 

2302 cal_chc = ['Dioptas calibration file:','pyFAI calibration file:'] 

2303 cal_spn = wx.SP_VERTICAL|wx.SP_ARROW_KEYS|wx.SP_WRAP 

2304 self.PoniInfo = [ Choice(panel, choices=cal_chc ), 

2305 wx.TextCtrl(panel, size=(320, 25)), 

2306 Button(panel, label='Browse...')] 

2307 

2308 self.PoniInfo[2].Bind(wx.EVT_BUTTON, self.onBROWSEponi) 

2309 

2310 ponisizer = wx.BoxSizer(wx.VERTICAL) 

2311 ponisizer.Add(self.PoniInfo[0], flag=wx.TOP, border=15) 

2312 ponisizer.Add(self.PoniInfo[1], flag=wx.TOP, border=5) 

2313 ponisizer.Add(self.PoniInfo[2], flag=wx.TOP|wx.BOTTOM, border=5) 

2314 

2315 ################################################################################ 

2316 hlpBtn = wx.Button(panel, wx.ID_HELP ) 

2317 okBtn = wx.Button(panel, wx.ID_OK ) 

2318 canBtn = wx.Button(panel, wx.ID_CANCEL ) 

2319 

2320 minisizer = wx.BoxSizer(wx.HORIZONTAL) 

2321 minisizer.Add(hlpBtn, flag=wx.RIGHT, border=5) 

2322 minisizer.Add(canBtn, flag=wx.RIGHT, border=5) 

2323 minisizer.Add(okBtn, flag=wx.RIGHT, border=5) 

2324 ################################################################################ 

2325 sizer = wx.BoxSizer(wx.VERTICAL) 

2326 sizer.Add((-1, 10)) 

2327 sizer.Add(ponisizer, flag=wx.TOP|wx.LEFT, border=5) 

2328 sizer.Add((-1, 15)) 

2329 sizer.Add(minisizer, flag=wx.ALIGN_RIGHT, border=5) 

2330 

2331 panel.SetSizer(sizer) 

2332 ################################################################################ 

2333 

2334 ## Set defaults 

2335 self.PoniInfo[0].SetSelection(0) 

2336 

2337 self.FindWindowById(wx.ID_OK).Disable() 

2338 

2339 def checkOK(self,event=None): 

2340 

2341 if os.path.exists(self.PoniInfo[1].GetValue()): 

2342 self.FindWindowById(wx.ID_OK).Enable() 

2343 else: 

2344 self.FindWindowById(wx.ID_OK).Disable() 

2345 

2346 def onBROWSEponi(self,event=None): 

2347 wildcards = 'XRD calibration file (*.poni)|*.poni|All files (*.*)|*.*' 

2348 if os.path.exists(self.PoniInfo[1].GetValue()): 

2349 dfltDIR = self.PoniInfo[1].GetValue() 

2350 else: 

2351 dfltDIR = get_cwd() 

2352 

2353 dlg = wx.FileDialog(self, message='Select XRD calibration file', 

2354 defaultDir=dfltDIR, 

2355 wildcard=wildcards, style=wx.FD_OPEN) 

2356 path, read = None, False 

2357 if dlg.ShowModal() == wx.ID_OK: 

2358 read = True 

2359 path = dlg.GetPath().replace('\\', '/') 

2360 dlg.Destroy() 

2361 

2362 if read: 

2363 self.PoniInfo[1].Clear() 

2364 self.PoniInfo[1].SetValue(str(path)) 

2365 self.checkOK() 

2366 

2367###### 

2368class ROIDialog(wx.Dialog): 

2369 """""" 

2370 #---------------------------------------------------------------------- 

2371 def __init__(self, owner, roi_callback=None, **kws): 

2372 """Constructor""" 

2373 print("ROI Dialog owner ", owner) 

2374 wx.Dialog.__init__(self, owner, wx.ID_ANY, title='Add and Delete ROIs', 

2375 size=(450, 350)) 

2376 

2377 self.owner = owner 

2378 self.roi_callback = roi_callback 

2379 self.Bind(wx.EVT_CLOSE, self.onClose) 

2380 

2381 self.gp = gp = GridPanel(self, nrows=8, ncols=4, itemstyle=LEFT, gap=3, **kws) 

2382 

2383 self.roi_name = wx.TextCtrl(gp, -1, 'ROI_001', size=(120, -1)) 

2384 fopts = dict(minval=-1, precision=3, size=(120, -1)) 

2385 self.roi_type = Choice(gp, size=(120, -1)) 

2386 self.roi_lims = [FloatCtrl(gp, value=0, **fopts), 

2387 FloatCtrl(gp, value=-1, **fopts)] 

2388 self.roi_units = Choice(gp, size=(120, -1)) 

2389 

2390 gp.Add(SimpleText(gp, ' Add new ROI: '), dcol=2, style=LEFT) 

2391 gp.Add(SimpleText(gp, ' Name:'), newrow=True) 

2392 gp.Add(self.roi_name, dcol=2) 

2393 gp.Add(SimpleText(gp, ' Type:'), newrow=True) 

2394 gp.Add(self.roi_type, dcol=2) 

2395 

2396 gp.Add(SimpleText(gp, ' Limits:'), newrow=True) 

2397 gp.AddMany((self.roi_lims[0], self.roi_lims[1], self.roi_units), 

2398 dcol=1, style=LEFT) 

2399 gp.Add(SimpleText(gp, ' '), newrow=True) 

2400 gp.Add(Button(gp, 'Add ROI', size=(120, -1), action=self.onCreateROI), 

2401 dcol=2) 

2402 

2403 ############################################################################### 

2404 

2405 self.rm_roi_name = Choice(gp, size=(120, -1)) 

2406 self.rm_roi_det = Choice(gp, size=(120, -1)) 

2407 fopts = dict(minval=-1, precision=3, size=(100, -1)) 

2408 gp.Add(SimpleText(gp, ''),newrow=True) 

2409 gp.Add(HLine(gp, size=(350, 4)), dcol=4, newrow=True) 

2410 gp.Add(SimpleText(gp, ''),newrow=True) 

2411 gp.Add(SimpleText(gp, 'Delete ROI: '), dcol=2, newrow=True) 

2412 

2413 gp.AddMany((SimpleText(gp, 'Detector:'),self.rm_roi_det), newrow=True) 

2414 gp.AddMany((SimpleText(gp, 'ROI:'),self.rm_roi_name), newrow=True) 

2415 

2416 gp.Add(SimpleText(gp, ''), newrow=True) 

2417 gp.Add(Button(gp, 'Remove This ROI', size=(120, -1), action=self.onRemoveROI), 

2418 dcol=2) 

2419 

2420 self.roi_type.Bind(wx.EVT_CHOICE, self.roiUNITS) 

2421 self.rm_roi_name.Bind(wx.EVT_CHOICE, self.roiSELECT) 

2422 

2423 gp.pack() 

2424 fit_dialog_window(self, gp) 

2425 self.owner.current_file.reset_flags() 

2426 self.roiTYPE() 

2427 

2428 def roiTYPE(self, event=None): 

2429 roitype = [] 

2430 cfile = self.owner.current_file 

2431 det_list = cfile.get_detector_list() 

2432 if cfile.has_xrf: 

2433 roitype += ['XRF'] 

2434 if cfile.has_xrd1d: 

2435 roitype += ['1DXRD'] 

2436 if len(roitype) < 1: 

2437 roitype = [''] 

2438 self.roi_type.SetChoices(roitype) 

2439 self.roiUNITS() 

2440 self.rm_roi_det.SetChoices(det_list) 

2441 self.setROI() 

2442 

2443 def onRemoveROI(self,event=None): 

2444 detname = self.rm_roi_det.GetStringSelection() 

2445 roiname = self.rm_roi_name.GetStringSelection() 

2446 

2447 if self.roi_callback is not None: 

2448 self.roi_callback(roiname, action='del') 

2449 self.setROI() 

2450 self.roiTYPE() 

2451 

2452 def setROI(self): 

2453 detname = self.rm_roi_det.GetStringSelection() 

2454 cfile = self.owner.current_file 

2455 try: 

2456 detgrp = cfile.xrmmap['roimap'][detname] 

2457 except: 

2458 return 

2459 

2460 limits = [] 

2461 names = detgrp.keys() 

2462 for name in names: 

2463 limits += [list(detgrp[name]['limits'][:])] 

2464 if len(limits) > 0: 

2465 self.rm_roi_name.SetChoices([x for (y,x) in sorted(zip(limits,names))]) 

2466 self.roiSELECT() 

2467 

2468 def roiSELECT(self, event=None): 

2469 detname = self.rm_roi_det.GetStringSelection() 

2470 cfile = self.owner.current_file 

2471 roinames = cfile.get_roi_list(detname) 

2472 self.rm_roi_name.SetChoices(roinames) 

2473 

2474 def roiUNITS(self,event=None): 

2475 choice = self.roi_type.GetStringSelection() 

2476 roiunit = [''] 

2477 if choice == 'XRF': 

2478 roiunit = ['keV', 'eV', 'channels'] 

2479 elif choice == '1DXRD': 

2480 roiunit = [u'\u212B\u207B\u00B9 (q)',u'\u00B0 (2\u03B8)',u'\u212B (d)'] 

2481 

2482 self.roi_units.SetChoices(roiunit) 

2483 

2484 def onCreateROI(self,event=None): 

2485 rtype = self.roi_type.GetStringSelection() 

2486 name = self.roi_name.GetValue() 

2487 xrange = [float(lims.GetValue()) for lims in self.roi_lims] 

2488 

2489 units = self.roi_units.GetStringSelection() 

2490 if rtype == '1DXRD': 

2491 units = ['q', '2th', 'd'][self.roi_units.GetSelection()] 

2492 

2493 

2494 self.owner.message(f'Building ROI data for: {name:s}') 

2495 if self.roi_callback is not None: 

2496 self.roi_callback(name, xrange=xrange, action='add', units=units, roitype=rtype) 

2497 

2498 self.owner.message(f'Added ROI: {name:s}') 

2499 self.roiTYPE() 

2500 

2501 def onClose(self, event=None): 

2502 self.Destroy() 

2503 

2504##################a 

2505 

2506 

2507 

2508class OpenMapFolder(wx.Dialog): 

2509 """""" 

2510 

2511 #---------------------------------------------------------------------- 

2512 def __init__(self, folder): 

2513 """Constructor""" 

2514 self.folder = folder 

2515 pref, f = os.path.split(folder) 

2516 title = "Read XRM Map Folder: %s" % f 

2517 wx.Dialog.__init__(self, None, 

2518 title=title, size=(475, 750)) 

2519 

2520 

2521 panel = wx.Panel(self) 

2522 

2523 ChkTtl = SimpleText(panel, label='Build map including data:' ) 

2524 self.ChkBx = [ Check(panel, label='XRF' ), 

2525 Check(panel, label='2DXRD' ), 

2526 Check(panel, label='1DXRD (requires calibration file)' )] 

2527 

2528 for chkbx in self.ChkBx: 

2529 chkbx.Bind(wx.EVT_CHECKBOX, self.checkOK) 

2530 

2531 cbsizer = wx.BoxSizer(wx.HORIZONTAL) 

2532 cbsizer.Add(self.ChkBx[0]) 

2533 cbsizer.Add(self.ChkBx[1]) 

2534 cbsizer.Add(self.ChkBx[2]) 

2535 

2536 ckbxsizer = wx.BoxSizer(wx.VERTICAL) 

2537 ckbxsizer.Add(ChkTtl, flag=wx.BOTTOM|wx.LEFT) 

2538 ckbxsizer.Add(cbsizer) 

2539 ################################################################################ 

2540 infoTtl = [ SimpleText(panel, label='Facility'), 

2541 SimpleText(panel, label='Beamline'), 

2542 SimpleText(panel, label='Run cycle'), 

2543 SimpleText(panel, label='Proposal'), 

2544 SimpleText(panel, label='User group')] 

2545 self.info = [ wx.TextCtrl(panel, size=(100, 25) ), 

2546 wx.TextCtrl(panel, size=(100, 25) ), 

2547 wx.TextCtrl(panel, size=(100, 25) ), 

2548 wx.TextCtrl(panel, size=(100, 25) ), 

2549 wx.TextCtrl(panel, size=(320, 25) )] 

2550 

2551 infosizer0 = wx.BoxSizer(wx.HORIZONTAL) 

2552 infosizer0.Add(infoTtl[0], flag=wx.RIGHT, border=5) 

2553 infosizer0.Add(self.info[0], flag=wx.RIGHT, border=15) 

2554 infosizer0.Add(infoTtl[1], flag=wx.RIGHT, border=5) 

2555 infosizer0.Add(self.info[1], flag=wx.RIGHT, border=15) 

2556 

2557 infosizer1 = wx.BoxSizer(wx.HORIZONTAL) 

2558 infosizer1.Add(infoTtl[2], flag=wx.RIGHT, border=5) 

2559 infosizer1.Add(self.info[2], flag=wx.RIGHT, border=15) 

2560 infosizer1.Add(infoTtl[3], flag=wx.RIGHT, border=5) 

2561 infosizer1.Add(self.info[3], flag=wx.RIGHT, border=15) 

2562 

2563 infosizer2 = wx.BoxSizer(wx.HORIZONTAL) 

2564 infosizer2.Add(infoTtl[4], flag=wx.RIGHT, border=5) 

2565 infosizer2.Add(self.info[4], flag=wx.RIGHT, border=15) 

2566 

2567 infosizer = wx.BoxSizer(wx.VERTICAL) 

2568 infosizer.Add(infosizer0, flag=wx.TOP, border=5) 

2569 infosizer.Add(infosizer1, flag=wx.TOP|wx.BOTTOM, border=5) 

2570 infosizer.Add(infosizer2, flag=wx.BOTTOM, border=15) 

2571 ################################################################################ 

2572 cal_chc = ['Dioptas calibration file:','pyFAI calibration file:'] 

2573 bkgd_chc = ['2DXRD background (optional):','1DXRD background (optional):'] 

2574 cal_spn = wx.SP_VERTICAL|wx.SP_ARROW_KEYS|wx.SP_WRAP 

2575 self.XRDInfo = [ Choice(panel, choices=cal_chc ), 

2576 wx.TextCtrl(panel, size=(320, 25)), 

2577 Button(panel, label='Browse...'), 

2578 SimpleText(panel, label='Steps:'), 

2579 wx.TextCtrl(panel, size=(80, 25)), 

2580 SimpleText(panel, label='Wedges:'), 

2581 wx.SpinCtrl(panel, style=cal_spn, size=(100, -1)), 

2582 Choice(panel, choices=bkgd_chc ), 

2583 wx.TextCtrl(panel, size=(320, 25)), 

2584 Button(panel, label='Browse...'), 

2585 SimpleText(panel, label='Background scale:'), 

2586 wx.TextCtrl(panel, size=(80, 25)), 

2587 SimpleText(panel, label='2DXRD mask file (optional):'), 

2588 wx.TextCtrl(panel, size=(320, 25)), 

2589 Button(panel, label='Browse...'),] 

2590 

2591 for i in [1,8,13]: 

2592 self.XRDInfo[i+1].Bind(wx.EVT_BUTTON, partial(self.onBROWSEfile,i=i)) 

2593 

2594 xrdsizer1 = wx.BoxSizer(wx.HORIZONTAL) 

2595 

2596 xrdsizer1.Add(self.XRDInfo[3], flag=wx.RIGHT, border=5) 

2597 xrdsizer1.Add(self.XRDInfo[4], flag=wx.RIGHT, border=5) 

2598 xrdsizer1.Add(self.XRDInfo[5], flag=wx.RIGHT, border=5) 

2599 xrdsizer1.Add(self.XRDInfo[6], flag=wx.RIGHT, border=5) 

2600 

2601 xrdsizer2 = wx.BoxSizer(wx.HORIZONTAL) 

2602 

2603 xrdsizer2.Add(self.XRDInfo[9], flag=wx.RIGHT, border=30) 

2604 xrdsizer2.Add(self.XRDInfo[10], flag=wx.RIGHT, border=5) 

2605 xrdsizer2.Add(self.XRDInfo[11], flag=wx.RIGHT, border=5) 

2606 

2607 xrdsizer = wx.BoxSizer(wx.VERTICAL) 

2608 xrdsizer.Add(self.XRDInfo[0], flag=wx.TOP, border=5) 

2609 xrdsizer.Add(self.XRDInfo[1], flag=wx.TOP, border=5) 

2610 xrdsizer.Add(self.XRDInfo[2], flag=wx.TOP|wx.BOTTOM, border=5) 

2611 xrdsizer.Add(xrdsizer1, flag=wx.BOTTOM, border=5) 

2612 xrdsizer.Add(self.XRDInfo[7], flag=wx.TOP, border=8) 

2613 xrdsizer.Add(self.XRDInfo[8], flag=wx.TOP, border=5) 

2614# xrdsizer.Add(self.XRDInfo[9], flag=wx.TOP|wx.BOTTOM, border=5) 

2615 xrdsizer.Add(xrdsizer2, flag=wx.TOP|wx.BOTTOM, border=5) 

2616 xrdsizer.Add(self.XRDInfo[12], flag=wx.TOP, border=8) 

2617 xrdsizer.Add(self.XRDInfo[13], flag=wx.TOP, border=5) 

2618 xrdsizer.Add(self.XRDInfo[14], flag=wx.TOP|wx.BOTTOM, border=5) 

2619 

2620 

2621 ################################################################################ 

2622 h5cmpr_chc = ['gzip','lzf'] 

2623 h5cmpr_opt = ['%i' % i for i in np.arange(10)] 

2624 

2625 self.H5cmprInfo = [Choice(panel, choices=h5cmpr_chc), 

2626 Choice(panel, choices=h5cmpr_opt)] 

2627 h5txt = SimpleText(panel, label='H5 File Comppression:') 

2628 

2629 self.H5cmprInfo[0].SetSelection(0) 

2630 self.H5cmprInfo[1].SetSelection(2) 

2631 

2632 self.H5cmprInfo[0].Bind(wx.EVT_CHOICE, self.onH5cmpr) 

2633 

2634 h5cmprsizer = wx.BoxSizer(wx.HORIZONTAL) 

2635 h5cmprsizer.Add(h5txt, flag=wx.RIGHT, border=5) 

2636 h5cmprsizer.Add(self.H5cmprInfo[0], flag=wx.RIGHT, border=5) 

2637 h5cmprsizer.Add(self.H5cmprInfo[1], flag=wx.RIGHT, border=5) 

2638 ################################################################################ 

2639 self.ok_btn = wx.Button(panel, wx.ID_OK) 

2640 self.cancel_btn = wx.Button(panel, wx.ID_CANCEL) 

2641 

2642 minisizer = wx.BoxSizer(wx.HORIZONTAL) 

2643 minisizer.Add(self.cancel_btn, flag=wx.RIGHT, border=5) 

2644 minisizer.Add(self.ok_btn, flag=wx.RIGHT, border=5) 

2645 ################################################################################ 

2646 sizer = wx.BoxSizer(wx.VERTICAL) 

2647 

2648 sizer.Add(ckbxsizer, flag=wx.TOP|wx.LEFT, border=5) 

2649 

2650 sizer.Add(HLine(panel, size=(320, 2)),flag=wx.TOP|wx.LEFT, border=5) 

2651 sizer.Add(infosizer, flag=wx.TOP|wx.LEFT, border=5) 

2652 sizer.Add(HLine(panel, size=(320, 2)),flag=wx.TOP|wx.LEFT, border=5) 

2653 sizer.Add(xrdsizer, flag=wx.TOP|wx.LEFT, border=5) 

2654 sizer.Add(HLine(panel, size=(320, 2)),flag=wx.TOP|wx.LEFT, border=5) 

2655 sizer.Add(h5cmprsizer, flag=wx.TOP|wx.LEFT, border=5) 

2656 sizer.Add(minisizer, flag=wx.ALIGN_RIGHT, border=5) 

2657 

2658 

2659 pack(panel, sizer) 

2660 w, h = panel.GetBestSize() 

2661 w = 25*(2 + int(w*0.04)) 

2662 h = 25*(2 + int(h*0.04)) 

2663 panel.SetSize((w, h)) 

2664 

2665 # HX 

2666 ################################################################################ 

2667 

2668 ## Set defaults 

2669 self.ChkBx[0].SetValue(True) 

2670 self.ChkBx[1].SetValue(False) 

2671 self.ChkBx[2].SetValue(False) 

2672 

2673 self.XRDInfo[0].SetSelection(0) 

2674 self.XRDInfo[7].SetSelection(0) 

2675 

2676 self.XRDInfo[4].SetValue('5001') 

2677 self.XRDInfo[6].SetValue(1) 

2678 self.XRDInfo[6].SetRange(0,36) 

2679 

2680 self.XRDInfo[11].SetValue('1.0') 

2681 

2682 for poniinfo in self.XRDInfo: 

2683 poniinfo.Disable() 

2684 

2685 self.info[0].SetValue(FACILITY) 

2686 self.info[1].SetValue(BEAMLINE) 

2687 for line in open(os.path.join(self.folder, 'Scan.ini'), 'r'): 

2688 if line.split()[0] == 'basedir': 

2689 npath = line.split()[-1].replace('\\', '/').split('/') 

2690 cycle, usr = npath[-2], npath[-1] 

2691 self.info[2].SetValue(cycle) 

2692 self.info[4].SetValue(usr) 

2693 self.checkOK() 

2694 

2695 def checkOK(self, evt=None): 

2696 

2697 if self.ChkBx[2].GetValue(): 

2698 for poniinfo in self.XRDInfo: 

2699 poniinfo.Enable() 

2700 elif self.ChkBx[1].GetValue(): 

2701 for poniinfo in self.XRDInfo[8:]: 

2702 poniinfo.Enable() 

2703 for poniinfo in self.XRDInfo[:8]: 

2704 poniinfo.Disable() 

2705 self.XRDInfo[7].SetSelection(0) 

2706 else: 

2707 for poniinfo in self.XRDInfo: 

2708 poniinfo.Disable() 

2709 

2710 def onH5cmpr(self,event=None): 

2711 

2712 if self.H5cmprInfo[0].GetSelection() == 0: 

2713 self.H5cmprInfo[1].Enable() 

2714 self.H5cmprInfo[1].SetChoices(['%i' % i for i in np.arange(10)]) 

2715 self.H5cmprInfo[1].SetSelection(2) 

2716 else: 

2717 self.H5cmprInfo[1].Disable() 

2718 self.H5cmprInfo[1].SetChoices(['']) 

2719 

2720 def onBROWSEfile(self,event=None,i=1): 

2721 

2722 if i == 8: 

2723 wldcd = '2D XRD background file (*.tiff)|*.tif;*.tiff;*.edf|All files (*.*)|*.*' 

2724 if i == 13: 

2725 wldcd = '1D XRD background file (*.xy)|*.xy|All files (*.*)|*.*' 

2726 else: ## elif i == 1: 

2727 wldcd = 'XRD calibration file (*.poni)|*.poni|All files (*.*)|*.*' 

2728 

2729 if os.path.exists(self.XRDInfo[i].GetValue()): 

2730 dfltDIR = self.XRDInfo[i].GetValue() 

2731 else: 

2732 dfltDIR = get_cwd() 

2733 

2734 dlg = wx.FileDialog(self, message='Select %s' % wldcd.split(' (')[0], 

2735 defaultDir=dfltDIR, 

2736 wildcard=wldcd, style=wx.FD_OPEN) 

2737 path, read = None, False 

2738 if dlg.ShowModal() == wx.ID_OK: 

2739 read = True 

2740 path = dlg.GetPath().replace('\\', '/') 

2741 dlg.Destroy() 

2742 

2743 if read: 

2744 self.XRDInfo[i].Clear() 

2745 self.XRDInfo[i].SetValue(str(path)) 

2746 

2747 

2748class MapViewer(LarchWxApp): 

2749 def __init__(self, use_scandb=False, _larch=None, filename=None, 

2750 check_version=True, with_inspect=False, **kws): 

2751 self.filename = filename 

2752 self.use_scandb = use_scandb 

2753 self.check_version = check_version 

2754 LarchWxApp.__init__(self, _larch=_larch, 

2755 with_inspect=with_inspect, **kws) 

2756 

2757 def createApp(self): 

2758 frame = MapViewerFrame(use_scandb=self.use_scandb, 

2759 filename=self.filename, 

2760 check_version=self.check_version, 

2761 _larch=self._larch) 

2762 self.SetTopWindow(frame) 

2763 return True 

2764 

2765 

2766def mapviewer(use_scandb=False, filename=None, _larch=None, 

2767 with_inspect=False, **kws): 

2768 MapViewer(use_scandb=use_scandb, filename=filename, _larch=_larch, 

2769 with_inspect=with_inspect, **kws)