Coverage for larch/wxxas/xasnorm_panel.py: 0%
833 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
1#!/usr/bin/env python
2"""
3XANES Normalization panel
4"""
5import time
6import wx
7from copy import deepcopy
8import numpy as np
10from functools import partial
11from xraydb import guess_edge, atomic_number
13from larch.utils import gformat, path_split
14from larch.math import index_of
15from larch.xafs.xafsutils import guess_energy_units
16from larch.xafs.pre_edge import find_e0
18from larch.wxlib import (BitmapButton, FloatCtrl, FloatSpin, get_icon,
19 SimpleText, pack, Button, HLine, Choice, Check,
20 GridPanel, CEN, RIGHT, LEFT, plotlabels,
21 get_zoomlimits, set_zoomlimits)
23from larch.utils.strutils import fix_varname, fix_filename, file2groupname
25from larch.utils.physical_constants import ATOM_NAMES
26from larch.wxlib.plotter import last_cursor_pos
27from .xas_dialogs import EnergyUnitsDialog
28from .taskpanel import TaskPanel, autoset_fs_increment, update_confval
29from .config import (make_array_choice, EDGES, ATSYMS,
30 NNORM_CHOICES, NNORM_STRINGS, NORM_METHODS)
32np.seterr(all='ignore')
34PLOTOPTS_1 = dict(style='solid', marker='None')
35PLOTOPTS_2 = dict(style='short dashed', zorder=3, marker='None')
36PLOTOPTS_D = dict(style='solid', zorder=2, side='right', marker='None')
38PlotOne_Choices = make_array_choice(['mu','norm', 'flat', 'prelines',
39 'norm+flat', 'mback_norm', 'mback_poly',
40 'i0', 'norm+i0', 'dmude', 'norm+dmude',
41 'd2mude', 'norm+d2mude'])
44PlotSel_Choices = make_array_choice(['mu', 'norm', 'flat', 'dmude', 'd2mude'])
46Plot_EnergyRanges = {'full E range': None,
47 'E0 -20:+80eV': (-20, 80),
48 'E0 -30:+120eV': (-30, 120),
49 'E0 -50:+250eV': (-50, 250),
50 'E0 -100:+500eV': (-100, 500)}
54FSIZE = 120
55FSIZEBIG = 175
57def get_auto_nnorm(norm1, norm2):
58 "autoamatically set nnorm from range"
59 nrange = abs(norm2 - norm1)
60 nnorm = 2
61 if nrange < 300: nnorm = 1
62 if nrange < 30: nnorm = 0
63 return nnorm
65class XASNormPanel(TaskPanel):
66 """XAS normalization Panel"""
67 def __init__(self, parent, controller=None, **kws):
68 TaskPanel.__init__(self, parent, controller, panel='xasnorm', **kws)
70 def build_display(self):
71 panel = self.panel
72 self.wids = {}
73 self.last_plot_type = 'one'
75 trow = wx.Panel(panel)
76 plot_sel = Button(trow, 'Plot Selected Groups', size=(175, -1),
77 action=self.onPlotSel)
78 plot_one = Button(trow, 'Plot Current Group', size=(175, -1),
79 action=self.onPlotOne)
81 self.plotsel_op = Choice(trow, choices=list(PlotSel_Choices.keys()),
82 action=self.onPlotSel, size=(300, -1))
83 self.plotone_op = Choice(trow, choices=list(PlotOne_Choices.keys()),
84 action=self.onPlotOne, size=(300, -1))
86 self.plot_erange = Choice(trow, choices=list(Plot_EnergyRanges.keys()),
87 action=self.onPlotEither, size=(175, -1))
89 opts = {'digits': 2, 'increment': 0.05, 'value': 0, 'size': (FSIZE, -1)}
90 plot_voff = self.add_floatspin('plot_voff', with_pin=False,
91 parent=trow,
92 action=self.onVoffset,
93 max_val=10000, min_val=-10000,
94 **opts)
96 vysize, vxsize = plot_sel.GetBestSize()
97 voff_lab = wx.StaticText(parent=trow, label=' Y Offset:', size=(80, vxsize),
98 style=wx.RIGHT|wx.ALIGN_CENTRE_HORIZONTAL|wx.ST_NO_AUTORESIZE)
100 self.plot_erange.SetSelection(0)
101 self.plotone_op.SetSelection(1)
102 self.plotsel_op.SetSelection(1)
104 tsizer = wx.GridBagSizer(3, 3)
105 tsizer.Add(plot_sel, (0, 0), (1, 1), LEFT, 2)
106 tsizer.Add(self.plotsel_op, (0, 1), (1, 1), LEFT, 2)
107 tsizer.Add(voff_lab, (0, 2), (1, 1), RIGHT, 2)
108 tsizer.Add(plot_voff, (0, 3), (1, 1), RIGHT, 2)
109 tsizer.Add(plot_one, (1, 0), (1, 1), LEFT, 2)
110 tsizer.Add(self.plotone_op, (1, 1), (1, 1), LEFT, 2)
111 tsizer.Add(self.plot_erange, (1, 2), (1, 2), RIGHT, 2)
113 pack(trow, tsizer)
115 # atom row
116 atpanel = wx.Panel(panel)
117 self.wids['atsym'] = Choice(atpanel, choices=ATSYMS, size=(100, -1))
118 self.wids['edge'] = Choice(atpanel, choices=EDGES, size=(100, -1))
119 sat = wx.BoxSizer(wx.HORIZONTAL)
120 sat.Add(self.wids['atsym'], 0, LEFT, 4)
121 sat.Add(self.wids['edge'], 0, LEFT, 4)
122 pack(atpanel, sat)
124 # e0 row
125 e0_panel = wx.Panel(panel)
126 xas_e0 = self.add_floatspin('e0', action=self.onSet_XASE0Val,
127 min_val=-1000, max_val=1e7, digits=3,
128 increment=0.05, value=0, size=(FSIZEBIG, -1),
129 parent=e0_panel)
131 self.wids['auto_e0'] = Check(e0_panel, default=True, label='auto?',
132 action=self.onAuto_XASE0)
133 self.wids['show_e0'] = Check(e0_panel, default=True, label='show?',
134 action=self.onSet_XASE0)
136 sx = wx.BoxSizer(wx.HORIZONTAL)
137 sx.Add(xas_e0, 0, LEFT, 4)
138 sx.Add(self.wids['auto_e0'], 0, LEFT, 4)
139 sx.Add(self.wids['show_e0'], 0, LEFT, 4)
140 pack(e0_panel, sx)
142 # step row
143 step_panel = wx.Panel(panel)
144 xas_step = self.add_floatspin('step', action=self.onSet_XASStep, with_pin=False,
145 min_val=-1000.0, max_val=1e7, digits=4, increment=0.05,
146 value=0.1, size=(FSIZEBIG, -1), parent=step_panel)
147 self.wids['auto_step'] = Check(step_panel, default=True, label='auto?',
148 action=self.onNormMethod)
149 sx = wx.BoxSizer(wx.HORIZONTAL)
150 sx.Add(xas_step, 0, LEFT, 4)
151 sx.Add(self.wids['auto_step'], 0, LEFT, 4)
152 pack(step_panel, sx)
154 # step rows
155 nnorm_panel = wx.Panel(panel)
156 self.wids['nnorm'] = Choice(nnorm_panel, choices=list(NNORM_CHOICES.keys()),
157 size=(150, -1), action=self.onNNormChoice,
158 default=2)
159 self.wids['auto_nnorm'] = Check(nnorm_panel, default=True, label='auto?',
160 action=self.onAuto_NNORM)
162 sx = wx.BoxSizer(wx.HORIZONTAL)
163 sx.Add(self.wids['nnorm'], 0, LEFT, 4)
164 sx.Add(self.wids['auto_nnorm'], 0, LEFT, 4)
165 pack(nnorm_panel, sx)
167 self.wids['energy_ref'] = Choice(panel, choices=['None'],
168 action=self.onEnergyRef, size=(300, -1))
170 self.wids['nvict'] = Choice(panel, choices=('0', '1', '2', '3'),
171 size=(100, -1), action=self.onNormMethod,
172 default=0)
175 opts = {'size': (FSIZE, -1), 'digits': 2, 'increment': 5.0, 'action': self.onSet_Ranges,
176 'min_val':-99000, 'max_val':99000}
177 defaults = self.get_defaultconfig()
179 pre_panel = wx.Panel(panel)
180 xas_pre1 = self.add_floatspin('pre1', value=defaults['pre1'], parent=pre_panel, **opts)
181 xas_pre2 = self.add_floatspin('pre2', value=defaults['pre2'], parent=pre_panel, **opts)
182 self.wids['show_pre'] = Check(pre_panel, default=False, label='show?',
183 action=self.onSet_XASE0)
185 sx = wx.BoxSizer(wx.HORIZONTAL)
186 sx.Add(xas_pre1, 0, LEFT, 4)
187 sx.Add(SimpleText(pre_panel, ' : '), 0, LEFT, 4)
188 sx.Add(xas_pre2, 0, LEFT, 4)
189 sx.Add(self.wids['show_pre'], 0, LEFT, 4)
190 pack(pre_panel, sx)
192 nor_panel = wx.Panel(panel)
193 xas_norm1 = self.add_floatspin('norm1', value=defaults['norm1'], parent=nor_panel, **opts)
194 xas_norm2 = self.add_floatspin('norm2', value=defaults['norm2'], parent=nor_panel, **opts)
196 self.wids['show_norm'] = Check(nor_panel, default=False, label='show?',
197 action=self.onSet_XASE0)
198 sx = wx.BoxSizer(wx.HORIZONTAL)
199 sx.Add(xas_norm1, 0, LEFT, 4)
200 sx.Add(SimpleText(nor_panel, ' : '), 0, LEFT, 4)
201 sx.Add(xas_norm2, 0, LEFT, 4)
202 sx.Add(self.wids['show_norm'], 0, LEFT, 4)
203 pack(nor_panel, sx)
206 opts = {'digits': 3, 'increment': 0.05, 'value': 0, 'size': (FSIZEBIG, -1)}
208 opts.update({'value': 1.0, 'digits': 3})
210 self.wids['norm_method'] = Choice(panel, choices=NORM_METHODS,
211 size=(150, -1), action=self.onNormMethod)
212 self.wids['norm_method'].SetSelection(0)
213 self.wids['energy_shift'] = FloatSpin(panel, value=0, digits=3, increment=0.05,
214 min_val=-99000, max_val=99000,
215 action=self.onSet_EnergyShift,
216 size=(FSIZEBIG, -1))
219 self.wids['is_frozen'] = Check(panel, default=False, label='Freeze Group',
220 action=self.onFreezeGroup)
222 use_auto = Button(panel, 'Use Default Settings', size=(200, -1),
223 action=self.onResetNorm)
225 def CopyBtn(name):
226 return Button(panel, 'Copy', size=(60, -1),
227 action=partial(self.onCopyParam, name))
229 copy_all = Button(panel, 'Copy All Parameters', size=(200, -1),
230 action=partial(self.onCopyParam, 'all'))
232 add_text = self.add_text
233 HLINEWID = 700
234 panel.Add(SimpleText(panel, 'XAS Pre-edge subtraction and Normalization',
235 size=(650, -1), **self.titleopts), style=LEFT, dcol=4)
236 panel.Add(trow, dcol=4, newrow=True)
238 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True)
239 add_text('XAS Data:')
240 panel.Add(use_auto, dcol=1)
241 panel.Add(SimpleText(panel, 'Copy to Selected Groups:'), style=RIGHT, dcol=2)
243 add_text('Element and Edge: ', newrow=True)
244 panel.Add(atpanel, dcol=2)
245 panel.Add(CopyBtn('atsym'), dcol=1, style=RIGHT)
247 add_text('Energy Reference : ')
248 panel.Add(self.wids['energy_ref'], dcol=2)
249 panel.Add(CopyBtn('energy_ref'), dcol=1, style=RIGHT)
251 add_text('Energy Shift : ')
252 panel.Add(self.wids['energy_shift'], dcol=2)
253 panel.Add(CopyBtn('energy_shift'), dcol=1, style=RIGHT)
255 add_text('E0 : ')
256 panel.Add(e0_panel, dcol=2)
257 panel.Add(CopyBtn('xas_e0'), dcol=1, style=RIGHT)
259 add_text('Edge Step: ')
260 panel.Add(step_panel, dcol=2)
261 panel.Add(CopyBtn('xas_step'), dcol=1, style=RIGHT)
263 panel.Add((5, 5), newrow=True)
264 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True)
266 add_text('Pre-edge range: ')
267 panel.Add(pre_panel, dcol=2)
268 panel.Add(CopyBtn('xas_pre'), dcol=1, style=RIGHT)
270 panel.Add(SimpleText(panel, 'Victoreen order:'), newrow=True)
271 panel.Add(self.wids['nvict'], dcol=2)
273 panel.Add((5, 5), newrow=True)
274 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True)
276 add_text('Normalization : ')
277 panel.Add(self.wids['norm_method'], dcol=2)
278 panel.Add(CopyBtn('xas_norm'), dcol=1, style=RIGHT)
280 add_text('Norm Energy range: ')
281 panel.Add(nor_panel, dcol=2)
282 panel.Add(SimpleText(panel, 'Polynomial Type:'), newrow=True)
283 panel.Add(nnorm_panel, dcol=3)
285 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True)
286 panel.Add(self.wids['is_frozen'], newrow=True)
287 panel.Add(copy_all, dcol=3, style=RIGHT)
289 panel.pack()
291 sizer = wx.BoxSizer(wx.VERTICAL)
292 sizer.Add((5, 5), 0, LEFT, 3)
293 sizer.Add(panel, 0, LEFT, 3)
294 sizer.Add((5, 5), 0, LEFT, 3)
295 pack(self, sizer)
297 def get_config(self, dgroup=None):
298 """custom get_config to possibly inherit from Athena settings"""
299 if dgroup is None:
300 dgroup = self.controller.get_group()
301 if dgroup is None:
302 return self.get_defaultconfig()
303 self.read_form()
306 defconf = self.get_defaultconfig()
307 conf = getattr(dgroup.config, self.configname, defconf)
309 for k, v in defconf.items():
310 if k not in conf:
311 conf[k] = v
312 if conf.get('edge_step', None) is None:
313 conf['edge_step'] = getattr(dgroup, 'edge_step', 1)
315 atsym = '?'
316 if hasattr(dgroup, 'element'):
317 elem = getattr(dgroup, 'element', '?')
318 try:
319 z = int(elem)
320 atsym = ATSYMS[z]
321 except:
322 pass
323 if elem in ATSYMS[1:]:
324 atsym = elem
325 else:
326 try:
327 if elem.lower() in ATOM_NAMES:
328 z = 1 + ATOM_NAMES.index(eleme.lower())
329 atsym = ATSYMS[z]
330 except:
331 pass
333 conf['atsym'] = atsym
334 if atsym == '?':
335 conf['atsym'] = getattr(dgroup, 'atsym', atsym)
336 conf['edge'] = getattr(dgroup,'edge', conf['edge'])
338 xeref = getattr(dgroup, 'energy_ref', '')
339 fname = getattr(dgroup, 'filename', None)
340 if fname is None:
341 fname = getattr(dgroup, 'groupname', None)
342 if fname is None:
343 fname =file2groupname('unknown_group',
344 symtable=self._larch.symtable)
346 conf['energy_ref'] = getattr(dgroup, 'energy_ref', fname)
348 if conf['energy_ref'] in (None, 'None'):
349 conf['energy_ref'] = fname
352 conf['energy_shift'] = getattr(dgroup,'energy_shift', conf['energy_shift'])
354 if hasattr(dgroup, 'e0') and conf['atsym'] == '?':
355 atsym, edge = guess_edge(dgroup.e0)
356 conf['atsym'] = atsym
357 conf['edge'] = edge
360 if hasattr(dgroup, 'mback_params'):
361 conf['atsym'] = getattr(dgroup.mback_params, 'atsym', conf['atsym'])
362 conf['edge'] = getattr(dgroup.mback_params, 'edge', conf['edge'])
364 setattr(dgroup.config, self.configname, conf)
365 return conf
367 def fill_form(self, dgroup):
368 """fill in form from a data group"""
369 opts = self.get_config(dgroup)
370 self.skip_process = True
371 if self.is_xasgroup(dgroup):
372 if self.plotone_op.GetCount() != len(PlotOne_Choices.keys()):
373 self.plotone_op.SetChoices(list(PlotOne_Choices.keys()))
374 self.plotone_op.SetSelection(1)
375 if self.plotsel_op.GetCount() != len(PlotSel_Choices.keys()):
376 self.plotsel_op.SetChoices(list(PlotSel_Choices.keys()))
377 self.plotsel_op.SetSelection(1)
379 groupnames = list(self.controller.file_groups.keys())
380 self.wids['energy_ref'].SetChoices(groupnames)
381 eref = opts.get('energy_ref', 'no_energy_ref')
383 for key, val in self.controller.file_groups.items():
384 if eref in (val, key):
385 self.wids['energy_ref'].SetStringSelection(key)
387 self.wids['e0'].SetValue(opts.get('e0', -1))
388 edge_step = opts.get('edge_step', 1.0)
390 if hasattr(dgroup, 'e0') and opts['atsym'] == '?':
391 atsym, edge = guess_edge(dgroup.e0)
392 opts['atsym'] = atsym
393 opts['edge'] = edge
395 self.wids['step'].SetValue(edge_step)
396 autoset_fs_increment(self.wids['step'], edge_step)
397 for attr in ('pre1', 'pre2', 'norm1', 'norm2'):
398 val = opts.get(attr, None)
399 if val is not None:
400 self.wids[attr].SetValue(val)
401 self.set_nnorm_widget(opts.get('nnorm'))
403 self.wids['energy_shift'].SetValue(opts['energy_shift'])
404 self.wids['nvict'].SetStringSelection("%d" % opts['nvict'])
405 self.wids['show_e0'].SetValue(opts['show_e0'])
406 self.wids['auto_e0'].SetValue(opts['auto_e0'])
407 self.wids['auto_nnorm'].SetValue(opts.get('auto_nnorm', 0))
408 self.wids['auto_step'].SetValue(opts['auto_step'])
410 self.wids['edge'].SetStringSelection(opts['edge'].title())
411 self.wids['atsym'].SetStringSelection(opts['atsym'].title())
412 self.wids['norm_method'].SetStringSelection(opts['norm_method'].lower())
413 for attr in ('pre1', 'pre2', 'norm1', 'norm2', 'nnorm', 'edge',
414 'atsym', 'step', 'norm_method'):
415 self.wids[attr].Enable()
416 self.wids['show_pre'].SetValue(opts['show_pre'])
417 self.wids['show_norm'].SetValue(opts['show_norm'])
420 frozen = opts.get('is_frozen', False)
421 frozen = getattr(dgroup, 'is_frozen', frozen)
423 self.wids['is_frozen'].SetValue(frozen)
424 self._set_frozen(frozen)
425 wx.CallAfter(self.unset_skip_process)
427 def set_nnorm_widget(self, nnorm=None):
428 conf = self.get_config()
429 nnorm_default = get_auto_nnorm(conf['norm1'], conf['norm2'])
430 if nnorm in (None, 'auto'):
431 nnorm = nnorm_default
432 elif nnorm in NNORM_CHOICES:
433 nnorm = int(NNORM_CHOICES[nnorm])
434 nnorm_str = NNORM_STRINGS.get(nnorm, None)
435 if nnorm_str is None:
436 nnorm_str = NNORM_STRINGS.get(nnorm_default, '1')
437 self.wids['nnorm'].SetStringSelection(nnorm_str)
438 self.wids['auto_nnorm'].SetValue(0)
440 def unset_skip_process(self):
441 self.skip_process = False
443 def read_form(self):
444 "read form, return dict of values"
445 form_opts = {}
446 form_opts['e0'] = self.wids['e0'].GetValue()
447 form_opts['edge_step'] = self.wids['step'].GetValue()
448 for attr in ('pre1', 'pre2', 'norm1', 'norm2'):
449 val = self.wids[attr].GetValue()
450 if val == 0: val = None
451 form_opts[attr] = val
453 form_opts['energy_shift'] = self.wids['energy_shift'].GetValue()
455 form_opts['nnorm'] = NNORM_CHOICES.get(self.wids['nnorm'].GetStringSelection(), 1)
456 form_opts['nvict'] = int(self.wids['nvict'].GetStringSelection())
457 form_opts['plotone_op'] = self.plotone_op.GetStringSelection()
458 form_opts['plotsel_op'] = self.plotsel_op.GetStringSelection()
459 form_opts['plot_voff'] = self.wids['plot_voff'].GetValue()
460 for ch in ('show_e0', 'show_pre', 'show_norm', 'auto_e0',
461 'auto_step', 'auto_nnorm'):
462 form_opts[ch] = self.wids[ch].IsChecked()
464 form_opts['norm_method'] = self.wids['norm_method'].GetStringSelection().lower()
465 form_opts['edge'] = self.wids['edge'].GetStringSelection().title()
466 form_opts['atsym'] = self.wids['atsym'].GetStringSelection().title()
467 form_opts['energy_ref'] = self.wids['energy_ref'].GetStringSelection()
468 return form_opts
470 def onNNormChoice(self, evt=None):
471 auto_nnorm = self.wids['auto_nnorm'].SetValue(0)
472 self.onNormMethod()
474 def onNormMethod(self, evt=None):
475 method = self.wids['norm_method'].GetStringSelection().lower()
476 auto_nnorm = self.wids['auto_nnorm'].GetValue()
478 nnorm = NNORM_CHOICES.get(self.wids['nnorm'].GetStringSelection(), 1)
479 if nnorm is None:
480 nnorm = get_auto_nnorm(self.wids['norm1'].GetValue(),
481 self.wids['norm2'].GetValue())
483 nvict = int(self.wids['nvict'].GetStringSelection())
484 self.update_config({'norm_method': method, 'nnorm': nnorm, 'nvict': nvict})
485 if method.startswith('mback'):
486 dgroup = self.controller.get_group()
487 cur_elem = self.wids['atsym'].GetStringSelection()
488 if hasattr(dgroup, 'e0') and cur_elem == 'H':
489 atsym, edge = guess_edge(dgroup.e0)
490 self.wids['edge'].SetStringSelection(edge)
491 self.wids['atsym'].SetStringSelection(atsym)
492 self.update_config({'edge': edge, 'atsym': atsym})
493 time.sleep(0.002)
494 wx.CallAfter(self.onReprocess)
496 def _set_frozen(self, frozen):
497 try:
498 dgroup = self.controller.get_group()
499 dgroup.is_frozen = frozen
500 except:
501 pass
503 for wattr in ('e0', 'step', 'pre1', 'pre2', 'norm1', 'norm2', 'nvict',
504 'nnorm', 'show_e0', 'auto_e0', 'auto_step', 'auto_nnorm',
505 'norm_method', 'edge', 'atsym', 'show_pre', 'show_norm'):
506 self.wids[wattr].Enable(not frozen)
508 def onFreezeGroup(self, evt=None):
509 self._set_frozen(evt.IsChecked())
511 def onEnergyRef(self, evt=None):
512 dgroup = self.controller.get_group()
513 eref = self.wids['energy_ref'].GetStringSelection()
514 gname = self.controller.file_groups[eref]
515 dgroup.config.xasnorm['energy_ref'] = eref
516 dgroup.energy_ref = eref
517 self.update_config({'energy_ref': eref}, dgroup=dgroup)
519 def onPlotEither(self, evt=None):
520 if self.last_plot_type == 'multi':
521 self.onPlotSel(evt=evt)
522 else:
523 self.onPlotOne(evt=evt)
525 def onPlotOne(self, evt=None):
526 self.last_plot_type = 'one'
527 self.plot(self.controller.get_group())
528 wx.CallAfter(self.controller.set_focus)
530 def onVoffset(self, evt=None):
531 time.sleep(0.002)
532 wx.CallAfter(self.onPlotSel)
534 def onPlotSel(self, evt=None):
535 newplot = True
536 self.last_plot_type = 'multi'
537 group_ids = self.controller.filelist.GetCheckedStrings()
538 if len(group_ids) < 1:
539 return
540 last_id = group_ids[-1]
542 groupname = self.controller.file_groups[str(last_id)]
543 dgroup = self.controller.get_group(groupname)
545 plot_choices = PlotSel_Choices
547 erange = Plot_EnergyRanges[self.plot_erange.GetStringSelection()]
548 self.controller.set_plot_erange(erange)
550 ytitle = self.plotsel_op.GetStringSelection()
551 yarray_name = plot_choices.get(ytitle, 'norm')
552 ylabel = getattr(plotlabels, yarray_name, ytitle)
553 xlabel = getattr(dgroup, 'plot_xlabel', getattr(plotlabels, 'energy'))
555 if yarray_name == 'norm':
556 norm_method = self.wids['norm_method'].GetStringSelection().lower()
557 if norm_method.startswith('mback'):
558 yarray_name = 'norm_mback'
559 ylabel = "%s (MBACK)" % ylabel
560 elif norm_method.startswith('area'):
561 yarray_name = 'norm_area'
562 ylabel = "%s (Area)" % ylabel
564 voff = self.wids['plot_voff'].GetValue()
565 plot_traces = []
566 newplot = True
567 plotopts = self.controller.get_plot_conf()
568 popts = {'style': 'solid', 'marker': None}
569 popts['linewidth'] = plotopts.pop('linewidth')
570 popts['marksize'] = plotopts.pop('markersize')
571 popts['grid'] = plotopts.pop('show_grid')
572 popts['fullbox'] = plotopts.pop('show_fullbox')
574 for ix, checked in enumerate(group_ids):
575 groupname = self.controller.file_groups[str(checked)]
576 dgroup = self.controller.get_group(groupname)
577 if dgroup is None:
578 continue
579 self.ensure_xas_processed(dgroup, force_mback =('mback' in yarray_name))
581 if erange is not None and hasattr(dgroup, 'e0') and 'xmin' not in popts:
582 popts['xmin'] = dgroup.e0 + erange[0]
583 popts['xmax'] = dgroup.e0 + erange[1]
585 trace = {'xdata': dgroup.xplot,
586 'ydata': getattr(dgroup, yarray_name) + ix*voff,
587 'label': dgroup.filename, 'new': newplot}
588 trace.update(popts)
589 plot_traces.append(trace)
590 newplot = False
592 ppanel = self.controller.get_display(stacked=False).panel
593 zoom_limits = get_zoomlimits(ppanel, dgroup)
595 nplot_traces = len(ppanel.conf.traces)
596 nplot_request = len(plot_traces)
597 if nplot_request > nplot_traces:
598 linecolors = ppanel.conf.linecolors
599 ncols = len(linecolors)
600 for i in range(nplot_traces, nplot_request+5):
601 ppanel.conf.init_trace(i, linecolors[i%ncols], 'dashed')
603 #
605 ppanel.plot_many(plot_traces, xlabel=plotlabels.energy, ylabel=ylabel,
606 zoom_limits=zoom_limits, show_legend=True)
607 set_zoomlimits(ppanel, zoom_limits) or ppanel.unzoom_all()
608 ppanel.canvas.draw()
610 wx.CallAfter(self.controller.set_focus)
612 def onAuto_NNORM(self, evt=None):
613 if evt.IsChecked():
614 nnorm = get_auto_nnorm(self.wids['norm1'].GetValue(),
615 self.wids['norm2'].GetValue())
616 self.set_nnorm_widget(nnorm)
617 self.wids['auto_nnorm'].SetValue(0)
618 time.sleep(0.001)
619 wx.CallAfter(self.onReprocess)
621 def onResetNorm(self, evt=None):
622 auto_nnorm = self.wids['auto_nnorm'].GetValue()
623 if auto_nnorm:
624 nnorm = get_auto_nnorm(self.wids['norm1'].GetValue(),
625 self.wids['norm2'].GetValue())
626 self.set_nnorm_widget(nnorm)
628 defaults = self.get_defaultconfig()
630 self.wids['auto_step'].SetValue(1)
631 self.wids['auto_e0'].SetValue(1)
632 self.wids['auto_e0'].SetValue(1)
633 self.wids['nvict'].SetSelection(0)
634 for attr in ('pre1', 'pre2', 'norm1', 'norm2'):
635 self.wids[attr].SetValue(defaults[attr])
636 self.onReprocess()
638 def onCopyAuto(self, evt=None):
639 opts = dict(pre1=0, pre2=0, nvict=0, norm1=0, norm2=0,
640 norm_method='polynomial', nnorm=2, auto_e0=1,
641 auto_step=1)
642 for checked in self.controller.filelist.GetCheckedStrings():
643 groupname = self.controller.file_groups[str(checked)]
644 grp = self.controller.get_group(groupname)
645 if grp != self.controller.group and not getattr(grp, 'is_frozen', False):
646 self.update_config(opts, dgroup=grp)
647 self.fill_form(grp)
648 self.process(grp, force=True)
651 def onSaveConfigBtn(self, evt=None):
652 conf = self.get_config()
653 conf.update(self.read_form())
654 # self.set_defaultconfig(conf)
656 def onCopyParam(self, name=None, evt=None):
657 conf = self.get_config()
658 form = self.read_form()
659 conf.update(form)
660 dgroup = self.controller.get_group()
661 self.update_config(conf)
662 self.fill_form(dgroup)
663 opts = {}
664 name = str(name)
665 def copy_attrs(*args):
666 for a in args:
667 opts[a] = conf[a]
668 if name == 'all':
669 copy_attrs('e0', 'show_e0', 'auto_e0', 'edge_step',
670 'auto_step', 'energy_shift', 'pre1', 'pre2',
671 'nvict', 'atsym', 'edge', 'norm_method', 'nnorm',
672 'norm1', 'norm2', 'energy_ref')
673 elif name == 'xas_e0':
674 copy_attrs('e0', 'show_e0', 'auto_e0')
675 elif name == 'xas_step':
676 copy_attrs('edge_step', 'auto_step')
677 elif name == 'energy_shift':
678 copy_attrs('energy_shift')
679 elif name == 'xas_pre':
680 copy_attrs('pre1', 'pre2', 'nvict', 'show_pre')
681 elif name == 'atsym':
682 copy_attrs('atsym', 'edge')
683 elif name == 'xas_norm':
684 copy_attrs('norm_method', 'nnorm', 'norm1', 'norm2', 'show_norm')
685 elif name == 'energy_ref':
686 copy_attrs('energy_ref')
687 for checked in self.controller.filelist.GetCheckedStrings():
688 groupname = self.controller.file_groups[str(checked)]
689 grp = self.controller.get_group(groupname)
690 if grp != self.controller.group and not getattr(grp, 'is_frozen', False):
691 self.update_config(opts, dgroup=grp)
692 for key, val in opts.items():
693 if hasattr(grp, key):
694 setattr(grp, key, val)
695 self.fill_form(grp)
696 self.process(grp, force=True)
698 def onAuto_XASE0(self, evt=None):
699 if evt.IsChecked():
700 dgroup = self.controller.get_group()
701 find_e0(dgroup)
702 self.update_config({'e0': dgroup.e0})
703 time.sleep(0.002)
704 wx.CallAfter(self.onReprocess)
706 def onSet_XASE0(self, evt=None, value=None):
707 "handle setting auto e0 / show e0"
708 auto_e0 = self.wids['auto_e0'].GetValue()
709 self.update_config({'e0': self.wids['e0'].GetValue(),
710 'auto_e0':self.wids['auto_e0'].GetValue()})
711 time.sleep(0.002)
712 wx.CallAfter(self.onReprocess)
714 def onSet_XASE0Val(self, evt=None, value=None):
715 "handle setting e0"
716 self.wids['auto_e0'].SetValue(0)
717 self.update_config({'e0': self.wids['e0'].GetValue(),
718 'auto_e0':self.wids['auto_e0'].GetValue()})
719 time.sleep(0.002)
720 wx.CallAfter(self.onReprocess)
722 def onSet_EnergyShift(self, evt=None, value=None):
723 conf = self.get_config()
724 if conf['auto_energy_shift']:
725 eshift = self.wids['energy_shift'].GetValue()
726 dgroup = self.controller.get_group()
727 _eref = getattr(dgroup, 'energy_ref', '<;no eref;>')
728 _gname = dgroup.groupname
729 self.stale_groups = []
730 for fname, gname in self.controller.file_groups.items():
731 this = self.controller.get_group(gname)
732 if _gname != gname and _eref == getattr(this, 'energy_ref', None):
733 this.energy_shift = this.config.xasnorm['energy_shift'] = eshift
734 self.stale_groups.append(this)
736 wx.CallAfter(self.onReprocess)
738 def onSet_XASStep(self, evt=None, value=None):
739 "handle setting edge step"
740 edge_step = self.wids['step'].GetValue()
741 if edge_step < 0:
742 self.wids['step'].SetValue(abs(edge_step))
743 self.wids['auto_step'].SetValue(0)
744 self.update_config({'edge_step': abs(edge_step), 'auto_step': False})
745 autoset_fs_increment(self.wids['step'], abs(edge_step))
746 time.sleep(0.01)
747 wx.CallAfter(self.onReprocess)
750 def onSet_Ranges(self, evt=None, **kws):
751 conf = {}
752 for attr in ('pre1', 'pre2', 'norm1', 'norm2'):
753 conf[attr] = self.wids[attr].GetValue()
754 self.update_config(conf)
755 time.sleep(0.01)
756 wx.CallAfter(self.onReprocess)
758 def pin_callback(self, opt='__', xsel=None, relative_e0=True, **kws):
759 """
760 get last selected point from a specified plot window
761 and fill in the value for the widget defined by `opt`.
763 by default it finds the latest cursor position from the
764 cursor history of the first 20 plot windows.
765 """
766 if xsel is None or opt not in self.wids:
767 return
769 e0 = self.wids['e0'].GetValue()
770 if opt == 'e0':
771 self.wids['e0'].SetValue(xsel)
772 self.wids['auto_e0'].SetValue(0)
773 elif opt in ('pre1', 'pre2', 'norm1', 'norm2'):
774 self.wids[opt].SetValue(xsel-e0)
775 time.sleep(0.01)
776 wx.CallAfter(self.onReprocess)
778 def onReprocess(self, evt=None, value=None, **kws):
779 "handle request reprocess"
780 if self.skip_process:
781 return
782 try:
783 dgroup = self.controller.get_group()
784 except TypeError:
785 return
786 if not hasattr(dgroup.config, self.configname):
787 return
788 form = self.read_form()
789 self.process(dgroup=dgroup)
790 if self.stale_groups is not None:
791 for g in self.stale_groups:
792 self.process(dgroup=g, force=True)
793 self.stale_groups = None
794 self.onPlotEither()
797 def process(self, dgroup=None, force_mback=False, force=False, use_form=True, **kws):
798 """ handle process (pre-edge/normalize) of XAS data from XAS form
799 """
800 if self.skip_process and not force:
801 return
802 if dgroup is None:
803 dgroup = self.controller.get_group()
804 if dgroup is None:
805 return
807 self.skip_process = True
808 conf = self.get_config(dgroup)
809 form = self.read_form()
810 if not use_form:
811 form.update(self.get_defaultconfig())
813 form['group'] = dgroup.groupname
814 groupnames = list(self.controller.file_groups.keys())
815 self.wids['energy_ref'].SetChoices(groupnames)
816 eref_sel = self.wids['energy_ref'].GetStringSelection()
817 for key, val in self.controller.file_groups.items():
818 if eref_sel in (val, key):
819 self.wids['energy_ref'].SetStringSelection(key)
822 en_units = getattr(dgroup, 'energy_units', None)
823 if en_units is None:
824 en_units = guess_energy_units(dgroup.energy)
826 if en_units != 'eV':
827 mono_dspace = getattr(dgroup, 'mono_dspace', 1)
828 dlg = EnergyUnitsDialog(self.parent, dgroup.energy,
829 unitname=en_units,
830 dspace=mono_dspace)
831 res = dlg.GetResponse()
832 dlg.Destroy()
833 if res.ok:
834 en_units = res.units
835 dgroup.mono_dspace = res.dspace
836 dgroup.xplot = dgroup.energy = res.energy
837 dgroup.energy_units = en_units
839 if not hasattr(dgroup, 'e0'):
840 e0 = find_e0(dgroup)
841 if form['atsym'] == '?' and conf.get('atsym', '?') != '?':
842 form['atsym'] = conf['atsym']
843 form['edge'] = conf.get('edge', 'K')
845 if form['atsym'] == '?':
846 form['atsym'], form['edge'] = guess_edge(dgroup.e0)
847 dgroup.atsym = form['atsym']
848 dgroup.edge = form['edge']
851 cmds = []
852 # test whether the energy shift is 0 or is different from the current energy shift:
853 ediff = 8.42e14 # just a huge energy step/shift
854 eshift_current = getattr(dgroup, 'energy_shift', ediff)
855 eshift = form.get('energy_shift', ediff)
856 e1 = getattr(dgroup, 'energy', [ediff])
857 e2 = getattr(dgroup, 'energy_orig', None)
859 if (not isinstance(e2, np.ndarray) or (len(e1) != len(e2))):
860 cmds.append("{group:s}.energy_orig = {group:s}.energy[:]")
862 if (isinstance(e1, np.ndarray) and isinstance(e2, np.ndarray) and
863 len(e1) == len(e2)):
864 ediff = (e1-e2).min()
866 if abs(eshift-ediff) > 1.e-5 or abs(eshift-eshift_current) > 1.e-5:
867 if abs(eshift) > 1e15: eshift = 0.0
868 cmds.extend(["{group:s}.energy_shift = {eshift:.4f}",
869 "{group:s}.energy = {group:s}.xplot = {group:s}.energy_orig + {group:s}.energy_shift"])
871 if len(cmds) > 0:
872 self.larch_eval(('\n'.join(cmds)).format(group=dgroup.groupname, eshift=eshift))
874 e0 = form['e0']
875 edge_step = form['edge_step']
877 copts = [dgroup.groupname]
878 if not form['auto_e0']:
879 if e0 < max(dgroup.energy) and e0 > min(dgroup.energy):
880 copts.append("e0=%.4f" % float(e0))
882 if not form['auto_step']:
883 copts.append("step=%s" % gformat(float(edge_step)))
885 for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'):
886 val = form[attr]
887 if val is None or val == 'auto':
888 val = 'None'
889 elif attr in ('nvict', 'nnorm'):
890 if val in NNORM_CHOICES:
891 val = NNORM_CHOICES[val]
892 val = int(val)
893 else:
894 val = f"{float(val):.2f}"
895 copts.append(f"{attr}={val}")
896 # print("process PreEdge ", copts)
897 self.larch_eval("pre_edge(%s)" % (', '.join(copts)))
898 self.larch_eval("{group:s}.norm_poly = 1.0*{group:s}.norm".format(**form))
899 if not hasattr(dgroup, 'e0'):
900 self.skip_process = False
901 dgroup.mu = dgroup.yplot * 1.0
902 opts = {'group': dgroup.groupname}
903 return
905 norm_method = form['norm_method'].lower()
906 form['normmeth'] = 'poly'
908 dgroup.journal.add_ifnew('normalization_method', norm_method)
910 if force_mback or norm_method.startswith('mback'):
911 form['normmeth'] = 'mback'
912 copts = [dgroup.groupname]
913 copts.append("z=%d" % atomic_number(form['atsym']))
914 copts.append("edge='%s'" % form['edge'])
915 for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'):
916 val = form[attr]
917 if val is None or val == 'auto':
918 val = 'None'
919 elif attr in ('nvict', 'nnorm'):
920 if val in NNORM_CHOICES:
921 val = NNORM_CHOICES[val]
922 val = int(val)
923 else:
924 val = f"{float(val):.2f}"
925 copts.append(f"{attr}={val}")
926 self.larch_eval("mback_norm(%s)" % (', '.join(copts)))
928 if form['auto_step']:
929 norm_expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s}
930{group:s}.edge_step = 1.0*{group:s}.edge_step_{normmeth:s}"""
931 self.larch_eval(norm_expr.format(**form))
932 else:
933 norm_expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s}
934{group:s}.norm *= {group:s}.edge_step_{normmeth:s}/{edge_step:.8f}"""
935 self.larch_eval(norm_expr.format(**form))
937 if norm_method.startswith('area'):
938 form['normmeth'] = 'area'
939 expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s}
940{group:s}.edge_step = 1.0*{group:s}.edge_step_{normmeth:s}"""
941 self.larch_eval(expr.format(**form))
944 if form['auto_e0'] and hasattr(dgroup, 'e0'):
945 self.wids['e0'].SetValue(dgroup.e0)
946 if form['auto_step'] and hasattr(dgroup, 'edge_step'):
947 self.wids['step'].SetValue(dgroup.edge_step)
948 autoset_fs_increment(self.wids['step'], dgroup.edge_step)
950 if hasattr(dgroup, 'e0') and (conf.get('atsym', '?') == '?'):
951 atsym, edge = guess_edge(dgroup.e0)
952 conf['atsym'] = dgroup.atsym = atsym
953 conf['edge'] = dgroup.edge = edge
954 self.wids['atsym'].SetStringSelection(dgroup.atsym)
955 self.wids['edge'].SetStringSelection(dgroup.edge)
957 self.set_nnorm_widget(dgroup.pre_edge_details.nnorm)
958 for attr in ('e0', 'edge_step'):
959 conf[attr] = getattr(dgroup, attr)
960 for attr in ('pre1', 'pre2', 'norm1', 'norm2'):
961 conf[attr] = val = getattr(dgroup.pre_edge_details, attr, None)
962 if val is not None:
963 self.wids[attr].SetValue(val)
965 if hasattr(dgroup, 'mback_params'): # from mback
966 conf['atsym'] = getattr(dgroup.mback_params, 'atsym')
967 conf['edge'] = getattr(dgroup.mback_params, 'edge')
968 self.update_config(conf, dgroup=dgroup)
969 # print("process updated conf ", dgroup, conf)
970 wx.CallAfter(self.unset_skip_process)
973 def get_plot_arrays(self, dgroup):
974 lab = plotlabels.norm
975 if dgroup is None:
976 return
978 dgroup.plot_y2label = None
979 dgroup.plot_xlabel = plotlabels.energy
980 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab)]
982 req_attrs = ['e0', 'norm', 'dmude', 'd2mude', 'pre_edge']
984 pchoice = PlotOne_Choices.get(self.plotone_op.GetStringSelection(), 'norm')
986 if pchoice in ('mu', 'norm', 'i0', 'flat', 'dmude', 'd2mude'):
987 lab = getattr(plotlabels, pchoice)
988 dgroup.plot_yarrays = [(pchoice, PLOTOPTS_1, lab)]
990 elif pchoice == 'prelines':
991 lab = plotlabels.mu
992 dgroup.plot_yarrays = [('mu', PLOTOPTS_1, plotlabels.mu),
993 ('pre_edge', PLOTOPTS_2, 'pre edge'),
994 ('post_edge', PLOTOPTS_2, 'post edge')]
996 elif pchoice == 'norm+d2mude':
997 lab = plotlabels.norm
998 dgroup.plot_y2label = lab2 = plotlabels.d2mude
999 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab),
1000 ('d2mude', PLOTOPTS_D, lab2)]
1002 elif pchoice == 'norm+dmude':
1003 lab = plotlabels.norm
1004 dgroup.plot_y2label = lab2 = plotlabels.dmude
1005 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab),
1006 ('dmude', PLOTOPTS_D, lab2)]
1007 elif pchoice == 'norm+i0':
1008 lab = plotlabels.norm
1009 dgroup.plot_y2label = lab2 = plotlabels.i0
1010 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab),
1011 ('i0', PLOTOPTS_D, lab2)]
1012 elif pchoice == 'norm+flat':
1013 lab = plotlabels.norm
1014 dgroup.plot_y2label = lab2 = plotlabels.flat
1015 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab),
1016 ('flat', PLOTOPTS_D, lab2)]
1017 elif pchoice == 'mback_norm':
1018 req_attrs.append('mback_norm')
1019 lab = plotlabels.mu
1020 if not hasattr(dgroup, 'mback_mu'):
1021 self.process(dgroup=dgroup, force_mback=True)
1022 dgroup.plot_yarrays = [('mu', PLOTOPTS_1, lab),
1023 ('mback_mu', PLOTOPTS_2, r'tabulated $\mu(E)$')]
1025 elif pchoice == 'mback_poly':
1026 req_attrs.append('mback_norm')
1027 lab = plotlabels.norm
1028 if not hasattr(dgroup, 'mback_mu'):
1029 self.process(dgroup=dgroup, force_mback=True)
1030 dgroup.plot_yarrays = [('norm_mback', PLOTOPTS_1, 'mback'),
1031 ('norm_poly', PLOTOPTS_2, 'polynomial')]
1033 elif pchoice == 'area_norm':
1034 dgroup.plot_yarrays = [('norm_area', PLOTOPTS_1, 'area'),
1035 ('norm_poly', PLOTOPTS_2, 'polynomial')]
1037 dgroup.plot_ylabel = lab
1038 needs_proc = False
1039 for attr in req_attrs:
1040 needs_proc = needs_proc or (not hasattr(dgroup, attr))
1042 if needs_proc:
1043 self.process(dgroup=dgroup, force=True)
1045 y4e0 = dgroup.yplot = getattr(dgroup, dgroup.plot_yarrays[0][0], dgroup.mu)
1046 dgroup.plot_extras = []
1048 popts = {'marker': 'o', 'markersize': 5,
1049 'label': '_nolegend_',
1050 'markerfacecolor': '#888',
1051 'markeredgecolor': '#A00'}
1053 if self.wids['show_e0'].IsChecked():
1054 ie0 = index_of(dgroup.energy, dgroup.e0)
1055 dgroup.plot_extras.append(('marker', dgroup.e0, y4e0[ie0], popts))
1057 if self.wids['show_pre'].IsChecked() or self.wids['show_norm'].IsChecked():
1058 popts['markersize'] = 4
1059 wids = []
1060 if self.wids['show_pre'].IsChecked(): wids.extend(['pre1', 'pre2'])
1061 if self.wids['show_norm'].IsChecked(): wids.extend(['norm1', 'norm2'])
1062 for wid in wids:
1063 val = self.wids[wid].GetValue()
1064 ival = min(len(y4e0)-1, index_of(dgroup.energy, dgroup.e0 + val))
1065 dgroup.plot_extras.append(('marker', dgroup.e0+val, y4e0[ival], popts))
1067 def plot(self, dgroup, title=None, plot_yarrays=None, yoff=0,
1068 delay_draw=True, multi=False, new=True, with_extras=True, **kws):
1070 if self.skip_plotting:
1071 return
1072 ppanel = self.controller.get_display(stacked=False).panel
1074 plotcmd = ppanel.oplot
1075 if new:
1076 plotcmd = ppanel.plot
1078 erange = Plot_EnergyRanges[self.plot_erange.GetStringSelection()]
1079 self.controller.set_plot_erange(erange)
1081 groupname = getattr(dgroup, 'groupname', None)
1082 if groupname is None:
1083 return
1085 self.ensure_xas_processed(dgroup, force_mback=True)
1086 self.get_plot_arrays(dgroup)
1088 if plot_yarrays is None and hasattr(dgroup, 'plot_yarrays'):
1089 plot_yarrays = dgroup.plot_yarrays
1091 popts = self.controller.get_plot_conf()
1092 popts.update(kws)
1093 popts['grid'] = popts.pop('show_grid')
1094 popts['fullbox'] = popts.pop('show_fullbox')
1096 path, fname = path_split(dgroup.filename)
1097 if 'label' not in popts:
1098 popts['label'] = dgroup.plot_ylabel
1100 zoom_limits = get_zoomlimits(ppanel, dgroup)
1102 if erange is not None and hasattr(dgroup, 'e0'):
1103 popts['xmin'] = dgroup.e0 + erange[0]
1104 popts['xmax'] = dgroup.e0 + erange[1]
1106 popts['xlabel'] = dgroup.plot_xlabel
1107 popts['ylabel'] = dgroup.plot_ylabel
1108 if getattr(dgroup, 'plot_y2label', None) is not None:
1109 popts['y2label'] = dgroup.plot_y2label
1111 plot_choices = PlotSel_Choices
1112 if multi:
1113 ylabel = self.plotsel_op.GetStringSelection()
1114 yarray_name = plot_choices.get(ylabel, 'norm')
1116 if self.is_xasgroup(dgroup):
1117 ylabel = getattr(plotlabels, yarray_name, ylabel)
1118 popts['ylabel'] = ylabel
1120 plot_extras = None
1121 if new:
1122 if title is None:
1123 title = fname
1124 plot_extras = getattr(dgroup, 'plot_extras', None)
1126 popts['title'] = title
1127 popts['show_legend'] = len(plot_yarrays) > 1
1128 narr = len(plot_yarrays) - 1
1130 _linewidth = popts['linewidth']
1131 for i, pydat in enumerate(plot_yarrays):
1132 yaname, yopts, yalabel = pydat
1133 popts.update(yopts)
1134 if yalabel is not None:
1135 popts['label'] = yalabel
1136 linewidht = _linewidth
1137 if 'linewidth' in popts:
1138 linewidth = popts.pop('linewidth')
1139 popts['delay_draw'] = delay_draw
1140 if yaname == 'norm_mback' and not hasattr(dgroup, yaname):
1141 self.process(dgroup=dgroup, force=True, force_mback=True)
1142 if yaname == 'i0' and not hasattr(dgroup, yaname):
1143 dgroup.i0 = np.ones(len(dgroup.xplot))
1144 plotcmd(dgroup.xplot, getattr(dgroup, yaname)+yoff, linewidth=linewidth, **popts)
1145 plotcmd = ppanel.oplot
1147 if with_extras and plot_extras is not None:
1148 axes = ppanel.axes
1149 for etype, x, y, opts in plot_extras:
1150 if etype == 'marker':
1151 xpopts = {'marker': 'o', 'markersize': 5,
1152 'label': '_nolegend_',
1153 'markerfacecolor': 'red',
1154 'markeredgecolor': '#884444'}
1155 xpopts.update(opts)
1156 axes.plot([x], [y], **xpopts)
1157 elif etype == 'vline':
1158 xpopts = {'ymin': 0, 'ymax': 1.0,
1159 'label': '_nolegend_',
1160 'color': '#888888'}
1161 xpopts.update(opts)
1162 axes.axvline(x, **xpopts)
1164 # set_zoomlimits(ppanel, zoom_limits)
1165 ppanel.reset_formats()
1166 set_zoomlimits(ppanel, zoom_limits)
1167 ppanel.conf.unzoom(full=True, delay_draw=False)