class XYFitController(): """ class hollding the Larch session and doing the processing work for Larch XYFit """ config_file = 'xyfit.conf' def __init__(self, wxparent=None, _larch=None): self.wxparent = wxparent self.larch = _larch if self.larch is None: self.larch = Interpreter() self.filelist = None self.file_groups = {} self.proc_opts = {} self.fit_opts = {} self.group = None self.groupname = None self.report_frame = None self.symtable = self.larch.symtable self.symtable.set_symbol('_sys.wx.wxapp', wx.GetApp()) self.symtable.set_symbol('_sys.wx.parent', self) def init_larch(self): fico = self.get_iconfile() _larch = self.larch _larch.eval("import xafs_plots") _larch.symtable._sys.xyfit = Group() config = read_config(self.config_file) if (config is None or 'workdir' not in config or 'data_proc' not in config or 'xas_proc' not in config): config = self.make_default_config() for key, value in config.items(): setattr(_larch.symtable._sys.xyfit, key, value) os.chdir(config['workdir']) def make_default_config(self): """ default config, probably called on first run of program""" config = {'chdir_on_fileopen': True, 'workdir': os.getcwd()} config['data_proc'] = dict(xshift=0, xscale=1, yshift=0, yscale=1, smooth_op='None', smooth_conv='Lorentzian', smooth_c0=2, smooth_c1=1, smooth_sig=1) config['xas_proc'] = dict(e0=0, pre1=-200, pre2=-10, edge_step=0, nnorm=2, norm1=25, norm2=-10, nvict=1, auto_step=True, auto_e0=True, show_e0=True, xas_op='Normalized') return config def get_config(self, key, default=None): "get configuration setting" confgroup = self.larch.symtable._sys.xyfit return getattr(confgroup, key, default) def save_config(self): """save configuration""" conf = group2dict(self.larch.symtable._sys.xyfit) conf.pop('__name__') save_config(self.config_file, conf) def set_workdir(self): self.larch.symtable._sys.xyfit.workdir = os.getcwd() def show_report(self, text, evt=None): shown = False try: self.report_frame.Raise() shown = True except: del self.report_frame if not shown: self.report_frame = ReportFrame(self.wxparent) self.report_frame.SetFont(Font(8)) self.report_frame.set_text(text) self.report_frame.SetFont(Font(8)) self.report_frame.Raise() def get_iconfile(self): larchdir = self.symtable._sys.config.larchdir return os.path.join(larchdir, 'icons', ICON_FILE) def get_display(self, stacked=False): win = 1 wintitle='Larch XYFit Array Plot Window' if stacked: win = 2 wintitle='Larch XYFit Fit Plot Window' opts = dict(wintitle=wintitle, stacked=stacked, win=win) out = self.symtable._plotter.get_display(**opts) return out def get_group(self, groupname): if groupname is None: groupname = self.groupname grp = getattr(self.symtable, groupname, None) if not hasattr(grp, 'proc_opts'): grp.proc_opts = {} return grp def get_proc_opts(self, dgroup): opts = {} opts.update(self.get_config('data_proc', default={})) if dgroup.datatype == 'xas': opts.update(self.get_config('xas_proc', {})) if hasattr(dgroup, 'proc_opts'): opts.update(dgroup.proc_opts) return opts def process(self, dgroup, proc_opts=None): if not hasattr(dgroup, 'proc_opts'): dgroup.proc_opts = {} if 'xscale' not in dgroup.proc_opts: dgroup.proc_opts.update(self.get_proc_opts(dgroup)) if proc_opts is not None: dgroup.proc_opts.update(proc_opts) opts = {'group': dgroup.groupname} opts.update(dgroup.proc_opts) # scaling cmds = [] cmds.append("{group:s}.x = {xscale:f}*({group:s}.xdat + {xshift:f})") cmds.append("{group:s}.y = {yscale:f}*({group:s}.ydat + {yshift:f})") # smoothing smop = opts['smooth_op'].lower() smcmd = None if smop.startswith('box'): opts['smooth_c0'] = int(opts['smooth_c0']) smcmd = "boxcar({group:s}.y, {smooth_c0:d})" elif smop.startswith('savit'): opts['smooth_c0'] = int(opts['smooth_c0']) opts['smooth_c1'] = int(opts['smooth_c1']) smcmd = "savitzky_golay({group:s}.y, {smooth_c0:d}, {smooth_c1:d})" elif smop.startswith('conv'): cform = str(opts['smooth_conv'].lower()) smcmd = "smooth({group:s}.x, {group:s}.y, sigma={smooth_sig:f}, form='{smooth_conv:s}')" if smcmd is not None: cmds.append("{group:s}.y = " + smcmd) for cmd in cmds: self.larch.eval(cmd.format(**opts)) # xas if dgroup.datatype.startswith('xas'): dgroup.energy = dgroup.x*1.0 dgroup.mu = dgroup.y*1.0 copts = [dgroup.groupname] if not opts['auto_e0']: _e0 = opts['e0'] if _e0 < max(dgroup.energy) and _e0 > min(dgroup.energy): copts.append("e0=%.4f" % float(_e0)) if not opts['auto_step']: copts.append("step=%.4f" % opts['edge_step']) for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'): copts.append("%s=%.4f" % (attr, opts[attr])) self.larch.eval("pre_edge(%s)" % (','.join(copts))) opts['e0'] = dgroup.e0 opts['edge_step'] = dgroup.edge_step for attr in ('pre1', 'pre2', 'norm1', 'norm2'): opts[attr] = getattr(dgroup.pre_edge_details, attr) dgroup.proc_opts.update(opts) def get_cursor(self): try: xval = self.symtable._plotter.plot1_x yval = self.symtable._plotter.plot1_y except: xval, yval = None, None return xval, yval def plot_group(self, groupname=None, title=None, new=True, **kws): ppanel = self.get_display(stacked=False).panel newplot = ppanel.plot oplot = ppanel.oplot plotcmd = oplot if new: plotcmd = newplot dgroup = self.get_group(groupname) if not hasattr(dgroup, 'xdat'): print("Cannot plot group ", groupname) if dgroup.datatype == 'xas': if ((getattr(dgroup, 'plot_yarrays', None) is None or getattr(dgroup, 'energy', None) is None or getattr(dgroup, 'mu', None) is None)): # print("-> Mode.process") self.process(dgroup) if not hasattr(dgroup, 'x'): dgroup.x = dgroup.xdat[:] if not hasattr(dgroup, 'y'): dgroup.y = dgroup.ydat[:] if hasattr(dgroup, 'plot_yarrays'): plot_yarrays = dgroup.plot_yarrays else: plot_yarrays = [(dgroup.y, {}, None)] popts = kws path, fname = os.path.split(dgroup.filename) if not 'label' in popts: popts['label'] = dgroup.plot_ylabel popts['xlabel'] = dgroup.plot_xlabel popts['ylabel'] = dgroup.plot_ylabel if getattr(dgroup, 'plot_y2label', None) is not None: popts['y2label'] = dgroup.plot_y2label plot_ymarkers = None if new: if title is None: title = fname plot_ymarkers = getattr(dgroup, 'plot_ymarkers', None) popts['title'] = title for yarr in plot_yarrays: popts.update(yarr[1]) if popts['label'] is None and yarr[2] is not None: popts['label'] = yarr[2] plotcmd(dgroup.x, yarr[0], **popts) plotcmd = oplot if plot_ymarkers is not None: axes = ppanel.axes for x, y, opts in plot_ymarkers: popts = {'marker': 'o', 'markersize': 4, 'markerfacecolor': 'red', 'label': '', 'markeredgecolor': 'black'} popts.update(opts) axes.plot([x], [y], **popts) ppanel.canvas.draw()
class XASController(): """ class hollding the Larch session and doing the processing work for Larch XAS GUI """ config_file = 'xas_viewer.conf' def __init__(self, wxparent=None, _larch=None): self.wxparent = wxparent self.larch = _larch if self.larch is None: self.larch = Interpreter() self.filelist = None self.file_groups = OrderedDict() self.fit_opts = {} self.group = None self.groupname = None self.report_frame = None self.symtable = self.larch.symtable def init_larch(self): fico = self.get_iconfile() _larch = self.larch _larch.eval(XASGUI_STARTUP) old_config = read_config(self.config_file) config = self.make_default_config() for sname in config: if old_config is not None and sname in old_config: val = old_config[sname] if isinstance(val, dict): config[sname].update(val) else: config[sname] = val for key, value in config.items(): setattr(_larch.symtable._sys.xas_viewer, key, value) os.chdir(config['workdir']) def make_default_config(self): """ default config, probably called on first run of program""" config = {'chdir_on_fileopen': True, 'workdir': os.getcwd()} return config def get_config(self, key, default=None): "get configuration setting" confgroup = self.larch.symtable._sys.xas_viewer return getattr(confgroup, key, default) def save_config(self): """save configuration""" conf = group2dict(self.larch.symtable._sys.xas_viewer) conf.pop('__name__') save_config(self.config_file, conf) def set_workdir(self): self.larch.symtable._sys.xas_viewer.workdir = os.getcwd() def show_report(self, fitresult, evt=None): shown = False try: self.report_frame.Raise() shown = True except: del self.report_frame if not shown: self.report_frame = ReportFrame(self.wxparent) model_repr = fitresult.model._reprstring(long=True) report = fit_report(fitresult, show_correl=True, min_correl=0.25, sort_pars=True) self.report_frame.SetFont(Font(FONTSIZE - 1)) self.report_frame.set_text(report) self.report_frame.SetFont(Font(FONTSIZE - 1)) self.report_frame.Raise() def get_iconfile(self): larchdir = self.symtable._sys.config.larchdir return os.path.join(larchdir, 'icons', ICON_FILE) def get_display(self, win=1, stacked=False): wintitle = 'Larch XAS Plot Window %i' % win # if stacked: # win = 2 # wintitle='Larch XAS Plot Window' opts = dict(wintitle=wintitle, stacked=stacked, win=win, size=PLOTWIN_SIZE) out = self.symtable._plotter.get_display(**opts) if win > 1: p1 = getattr(self.symtable._plotter, 'plot1', None) if p1 is not None: try: siz = p1.GetSize() pos = p1.GetPosition() pos[0] += int(siz[0] / 4) pos[1] += int(siz[1] / 4) out.SetSize(pos) if not stacked: out.SetSize(siz) except Exception: pass return out def get_group(self, groupname=None): if groupname is None: groupname = self.groupname if groupname is None: return None dgroup = getattr(self.symtable, groupname, None) if dgroup is None and groupname in self.file_groups: groupname = self.file_groups[groupname] dgroup = getattr(self.symtable, groupname, None) return dgroup def merge_groups(self, grouplist, master=None, yarray='mu', outgroup=None): """merge groups""" cmd = """%s = merge_groups(%s, master=%s, xarray='energy', yarray='%s', kind='cubic', trim=True)""" glist = "[%s]" % (', '.join(grouplist)) outgroup = fix_varname(outgroup.lower()) if outgroup is None: outgroup = 'merged' outgroup = unique_name(outgroup, self.file_groups, max=1000) cmd = cmd % (outgroup, glist, master, yarray) self.larch.eval(cmd) if master is None: master = grouplist[0] this = self.get_group(outgroup) master = self.get_group(master) if not hasattr(this, 'xasnorm_config'): this.xasnorm_config = {} this.xasnorm_config.update(master.xasnorm_config) this.datatype = master.datatype this.xdat = 1.0 * this.energy this.ydat = 1.0 * getattr(this, yarray) this.plot_xlabel = 'energy' this.plot_ylabel = yarray return outgroup def copy_group(self, filename, new_filename=None): """copy XAS group (by filename) to new group""" groupname = self.file_groups[filename] if not hasattr(self.larch.symtable, groupname): return ogroup = self.get_group(groupname) ngroup = Group(datatype=ogroup.datatype, copied_from=groupname) for attr in dir(ogroup): do_copy = True if attr in ('xdat', 'ydat', 'i0', 'data' 'yerr', 'energy', 'mu'): val = getattr(ogroup, attr) * 1.0 elif attr in ('norm', 'flat', 'deriv', 'deconv', 'post_edge', 'pre_edge'): do_copy = False else: try: val = copy.deepcopy(getattr(ogroup, attr)) except ValueError: do_copy = False if do_copy: setattr(ngroup, attr, val) if new_filename is None: new_filename = filename + '_1' ngroup.filename = unique_name(new_filename, self.file_groups.keys()) ngroup.groupname = unique_name(groupname, self.file_groups.values()) setattr(self.larch.symtable, ngroup.groupname, ngroup) return ngroup def get_cursor(self, win=None): """get last cursor from selected window""" return last_cursor_pos(win=win, _larch=self.larch) def plot_group(self, groupname=None, title=None, plot_yarrays=None, new=True, zoom_out=True, **kws): ppanel = self.get_display(stacked=False).panel newplot = ppanel.plot oplot = ppanel.oplot plotcmd = oplot viewlims = ppanel.get_viewlimits() if new: plotcmd = newplot dgroup = self.get_group(groupname) if not hasattr(dgroup, 'xdat'): print("Cannot plot group ", groupname) if ((getattr(dgroup, 'plot_yarrays', None) is None or getattr(dgroup, 'energy', None) is None or getattr(dgroup, 'mu', None) is None)): self.process(dgroup) if plot_yarrays is None and hasattr(dgroup, 'plot_yarrays'): plot_yarrays = dgroup.plot_yarrays popts = kws path, fname = os.path.split(dgroup.filename) if not 'label' in popts: popts['label'] = dgroup.plot_ylabel zoom_out = (zoom_out or min(dgroup.xdat) >= viewlims[1] or max(dgroup.xdat) <= viewlims[0] or min(dgroup.ydat) >= viewlims[3] or max(dgroup.ydat) <= viewlims[2]) if not zoom_out: popts['xmin'] = viewlims[0] popts['xmax'] = viewlims[1] popts['ymin'] = viewlims[2] popts['ymax'] = viewlims[3] popts['xlabel'] = dgroup.plot_xlabel popts['ylabel'] = dgroup.plot_ylabel if getattr(dgroup, 'plot_y2label', None) is not None: popts['y2label'] = dgroup.plot_y2label plot_extras = None if new: if title is None: title = fname plot_extras = getattr(dgroup, 'plot_extras', None) popts['title'] = title if hasattr(dgroup, 'custom_plotopts'): popts.update(dgroup.custom_plotopts) narr = len(plot_yarrays) - 1 for i, pydat in enumerate(plot_yarrays): yaname, yopts, yalabel = pydat popts.update(yopts) if yalabel is not None: popts['label'] = yalabel popts['delay_draw'] = (i != narr) plotcmd(dgroup.xdat, getattr(dgroup, yaname), **popts) plotcmd = oplot if plot_extras is not None: axes = ppanel.axes for etype, x, y, opts in plot_extras: if etype == 'marker': popts = { 'marker': 'o', 'markersize': 4, 'label': '_nolegend_', 'markerfacecolor': 'red', 'markeredgecolor': '#884444' } popts.update(opts) axes.plot([x], [y], **popts) elif etype == 'vline': popts = {'ymin': 0, 'ymax': 1.0, 'color': '#888888'} popts.update(opts) axes.axvline(x, **popts) ppanel.canvas.draw()
class XYFitController(): """ class hollding the Larch session and doing the processing work for Larch XYFit """ def __init__(self, wxparent=None, _larch=None): self.wxparent = wxparent self.larch = _larch if self.larch is None: self.larch = Interpreter() self.filelist = None self.file_groups = {} self.proc_opts = {} self.fit_opts = {} self.group = None self.groupname = None self.report_frame = None self.symtable = self.larch.symtable self.symtable.set_symbol('_sys.wx.wxapp', wx.GetApp()) self.symtable.set_symbol('_sys.wx.parent', self) def show_report(self, text, evt=None): shown = False try: self.report_frame.Raise() shown = True except: del self.report_frame if not shown: self.report_frame = ReportFrame(self.wxparent) self.report_frame.SetFont(Font(8)) self.report_frame.set_text(text) self.report_frame.SetFont(Font(8)) self.report_frame.Raise() def get_iconfile(self): larchdir = self.symtable._sys.config.larchdir return os.path.join(larchdir, 'icons', ICON_FILE) def get_display(self, stacked=False): win = 1 wintitle = 'Larch XYFit Array Plot Window' if stacked: win = 2 wintitle = 'Larch XYFit Fit Plot Window' opts = dict(wintitle=wintitle, stacked=stacked, win=win) out = self.symtable._plotter.get_display(**opts) return out def get_group(self, groupname): if groupname is None: groupname = self.groupname grp = getattr(self.symtable, groupname, None) if not hasattr(grp, 'proc_opts'): grp.proc_opts = {} return grp def get_proc_opts(self, dgroup): opts = dict(xshift=0, xscale=1, yshift=0, yscale=1, smooth_op='None', smooth_conv='Lorentzian', smooth_c0=2, smooth_c1=1, smooth_sig=1) if dgroup.datatype == 'xas': opts.update( dict(e0=0, pre1=-200, pre2=-30, edge_step=0, nnorm=3, norm1=50, norm2=-10, nvict=2, auto_step=True, auto_e0=True, show_e0=True, xas_op='Raw Data')) if hasattr(dgroup, 'proc_opts'): opts.update(dgroup.proc_opts) return opts def process(self, dgroup, proc_opts=None): if not hasattr(dgroup, 'proc_opts'): dgroup.proc_opts = {} if 'xscale' not in dgroup.proc_opts: dgroup.proc_opts.update(self.get_proc_opts(dgroup)) if proc_opts is not None: dgroup.proc_opts.update(proc_opts) opts = {'group': dgroup.groupname} opts.update(dgroup.proc_opts) # scaling cmds = [ "{group:s}.x = {xscale:f}*({group:s}.xdat + {xshift:f})", "{group:s}.y = {yscale:f}*({group:s}.ydat + {yshift:f})" ] # smoothing smop = opts['smooth_op'].lower() smcmd = None if smop.startswith('box'): opts['smooth_c0'] = int(opts['smooth_c0']) smcmd = "boxcar({group:s}.y, {smooth_c0:d})" elif smop.startswith('savit'): opts['smooth_c0'] = int(opts['smooth_c0']) opts['smooth_c1'] = int(opts['smooth_c1']) smcmd = "savitzky_golay({group:s}.y, {smooth_c0:d}, {smooth_c1:d})" elif smop.startswith('conv'): cform = str(opts['smooth_conv'].lower()) smcmd = "smooth({group:s}.x, {group:s}.y, sigma={smooth_sig:f}, form='{smooth_conv:s}')" if smcmd is not None: cmds.append("{group:s}.y = " + smcmd) for cmd in cmds: self.larch.eval(cmd.format(**opts)) # xas if dgroup.datatype.startswith('xas'): dgroup.energy = dgroup.x dgroup.mu = dgroup.y popts = dict(group=dgroup.groupname, e0='None', step='None', make_flat='False') if not opts['auto_e0']: _e0 = opts['e0'] if _e0 < max(dgroup.energy) and _e0 > min(dgroup.energy): popts['e0'] = "%.f" % float(_e0) if not opts['auto_step']: popts['step'] = "%.f" % opts['step'] for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'): popts[attr] = "%.f" % opts[attr] cmd = """pre_edge({group:s}, e0={e0:s}, step={step:s}, pre1={pre1:s}, pre2={pre2:s}, norm1={norm1:s}, norm2={norm2:s}, nnorm={nnorm:s}, nvict={nvict:s})""".format( **popts) self.larch.eval(cmd) for attr in ('e0', 'edge_step'): opts[attr] = getattr(dgroup, attr) for attr in ('pre1', 'pre2', 'norm1', 'norm2'): opts[attr] = getattr(dgroup.pre_edge_details, attr) dgroup.proc_opts.update(opts) def get_cursor(self): try: xval = self.symtable._plotter.plot1_x yval = self.symtable._plotter.plot1_y except: xval, yval = None, None return xval, yval def plot_group(self, groupname=None, title=None, new=True, **kws): ppanel = self.get_display(stacked=False).panel newplot = ppanel.plot oplot = ppanel.oplot plotcmd = oplot if new: plotcmd = newplot dgroup = self.get_group(groupname) if not hasattr(dgroup, 'xdat'): print("Cannot plot group ", groupname) if dgroup.datatype == 'xas': if ((getattr(dgroup, 'plot_yarrays', None) is None or getattr(dgroup, 'energy', None) is None or getattr(dgroup, 'mu', None) is None)): # print("-> Mode.process") self.process(dgroup) if not hasattr(dgroup, 'x'): dgroup.x = dgroup.xdat[:] if not hasattr(dgroup, 'y'): dgroup.y = dgroup.ydat[:] if hasattr(dgroup, 'plot_yarrays'): plot_yarrays = dgroup.plot_yarrays else: plot_yarrays = [(dgroup.y, {}, None)] popts = kws path, fname = os.path.split(dgroup.filename) if not 'label' in popts: popts['label'] = "%s: %s" % (fname, dgroup.plot_ylabel) popts['xlabel'] = dgroup.plot_xlabel popts['ylabel'] = dgroup.plot_ylabel if getattr(dgroup, 'plot_y2label', None) is not None: popts['y2label'] = dgroup.plot_y2label if plotcmd == newplot and title is None: title = fname popts['title'] = title for yarr in plot_yarrays: popts.update(yarr[1]) if yarr[2] is not None: popts['label'] = yarr[2] plotcmd(dgroup.x, yarr[0], **popts) plotcmd = oplot if hasattr(dgroup, 'plot_ymarkers'): axes = ppanel.axes for x, y, opts in dgroup.plot_ymarkers: popts = { 'marker': 'o', 'markersize': 4, 'markerfacecolor': 'red', 'markeredgecolor': 'black' } popts.update(opts) axes.plot([x], [y], **popts) ppanel.canvas.draw()