class LarchSession(object): def __init__(self): self._larch = Interpreter() self.input = InputText(prompt='test>', _larch=self._larch) self.symtable = self._larch.symtable self.symtable.set_symbol('_plotter.newplot', nullfunction) self.symtable.set_symbol('_plotter.plot', nullfunction) self.symtable.set_symbol('_plotter.oplot', nullfunction) self.symtable.set_symbol('_plotter.imshow', nullfunction) self.symtable.set_symbol('_plotter.plot_text', nullfunction) self.symtable.set_symbol('_plotter.plot_arrow', nullfunction) self.symtable.set_symbol('_plotter.xrfplot', nullfunction) def run(self, text): self.input.put(text) ret = None while len(self.input) > 0: block, fname, lineno = self.input.get() if len(block) <= 0: continue ret = self._larch.eval(block, fname=fname, lineno=lineno) if self._larch.error: break return ret def get_errors(self): return self._larch.error def get_symbol(self, name): return self.symtable.get_symbol(name, create=False)
class LarchSession(object): def __init__(self): self._larch = Interpreter() self.input = InputText(prompt='test>', _larch=self._larch) self.symtable = self._larch.symtable self.symtable.set_symbol('_plotter.newplot', nullfunction) self.symtable.set_symbol('_plotter.plot', nullfunction) self.symtable.set_symbol('_plotter.oplot', nullfunction) self.symtable.set_symbol('_plotter.imshow', nullfunction) self.symtable.set_symbol('_plotter.plot_text', nullfunction) self.symtable.set_symbol('_plotter.plot_arrow', nullfunction) self.symtable.set_symbol('_plotter.xrfplot', nullfunction) self._larch.writer = sys.stdout = open('_stdout_', 'w') def read_stdout(self): sys.stdout.flush() time.sleep(0.1) with open(sys.stdout.name) as inp: out = inp.read() sys.stdout.close() self._larch.writer = sys.stdout = open('_stdout_', 'w') return out def run(self, text): self.input.put(text) ret = None buff = [] while len(self.input) > 0: block, fname, lineno = self.input.get() buff.append(block) if not self.input.complete: continue ret = self._larch.eval("\n".join(buff), fname=fname, lineno=lineno) if self._larch.error: break return ret def get_errors(self): return self._larch.error def get_symbol(self, name): return self.symtable.get_symbol(name, create=False)
class LarchSession(object): def __init__(self): self._larch = Interpreter() self.input = self._larch.input # InputText(prompt='test>', _larch=self._larch) self.symtable = self._larch.symtable self.symtable.set_symbol('testdir', os.getcwd()) self.symtable.set_symbol('_plotter.newplot', nullfunction) self.symtable.set_symbol('_plotter.plot', nullfunction) self.symtable.set_symbol('_plotter.oplot', nullfunction) self.symtable.set_symbol('_plotter.imshow', nullfunction) self.symtable.set_symbol('_plotter.plot_text', nullfunction) self.symtable.set_symbol('_plotter.plot_arrow', nullfunction) self.symtable.set_symbol('_plotter.xrfplot', nullfunction) self.set_stdout() def set_stdout(self, fname='_stdout_'): self._outfile = os.path.abspath(fname) self._larch.writer = open(self._outfile, 'w') def read_stdout(self): self._larch.writer.flush() t0 = time.time() time.sleep(0.1) while (not os.path.exists(self._outfile) and (time.time() - t0) < 5.0): time.sleep(0.1) with open(self._outfile) as inp: out = inp.read() os.unlink(self._outfile) self._larch.writer = open(self._outfile, 'w') return out def run(self, text): return self._larch.eval(text, fname='test', lineno=0) def get_errors(self): return self._larch.error def get_symbol(self, name): return self.symtable.get_symbol(name, create=False)
class LarchSession(object): def __init__(self): self._larch = Interpreter() self.input = self._larch.input # InputText(prompt='test>', _larch=self._larch) self.symtable = self._larch.symtable self.symtable.set_symbol('testdir', os.getcwd()) self.symtable.set_symbol('_plotter.newplot', nullfunction) self.symtable.set_symbol('_plotter.plot', nullfunction) self.symtable.set_symbol('_plotter.oplot', nullfunction) self.symtable.set_symbol('_plotter.imshow', nullfunction) self.symtable.set_symbol('_plotter.plot_text', nullfunction) self.symtable.set_symbol('_plotter.plot_arrow', nullfunction) self.symtable.set_symbol('_plotter.xrfplot', nullfunction) self.set_stdout() def set_stdout(self, fname='_stdout_'): # self._outfile = os.path.abspath(fname) # self._larch.writer = open(self._outfile, 'w') self._larch.writer = StringIO() def read_stdout(self): self._larch.writer.flush() self._larch.writer.seek(0) t0 = time.time() time.sleep(0.01) out = self._larch.writer.read() self._larch.writer.close() self.set_stdout() return out def run(self, text): return self._larch.eval(text, fname='test', lineno=0) def get_errors(self): return self._larch.error def get_symbol(self, name): return self.symtable.get_symbol(name, create=False)
class LarchSession(object): def __init__(self): self._larch = Interpreter() self.input = self._larch.input # InputText(prompt='test>', _larch=self._larch) self.symtable = self._larch.symtable setsym = self.symtable.set_symbol setsym('testdir', os.getcwd()) setsym('_plotter.no_plotting', True) setsym('_plotter.get_display', nullfunction) self.set_stdout() def set_stdout(self, fname='_stdout_'): # self._outfile = os.path.abspath(fname) # self._larch.writer = open(self._outfile, 'w') self._larch.writer = StringIO() def read_stdout(self): self._larch.writer.flush() self._larch.writer.seek(0) t0 = time.time() time.sleep(0.01) out = self._larch.writer.read() self._larch.writer.close() self.set_stdout() return out def run(self, text): return self._larch.eval(text, fname='test', lineno=0) def get_errors(self): return self._larch.error def get_symbol(self, name): return self.symtable.get_symbol(name, create=False)
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 """ 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 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()
class LarchServer(SimpleXMLRPCServer): def __init__(self, host='localhost', port=4966, logRequests=False, allow_none=True, keepalive_time=3 * 24 * 3600): self.out_buffer = [] self.larch = Interpreter(writer=self) self.input = InputText(prompt='', _larch=self.larch) self.larch.run_init_scripts() self.larch('_sys.client = group(keepalive_time=%f)' % keepalive_time) self.larch('_sys.wx = group(wxapp=None)') _sys = self.larch.symtable._sys _sys.color_exceptions = False _sys.client.last_event = int(time()) _sys.client.pid_server = int(os.getpid()) _sys.client.app = 'unknown' _sys.client.pid = 0 _sys.client.user = '******' _sys.client.machine = 'unknown' self.client = self.larch.symtable._sys.client SimpleXMLRPCServer.__init__(self, (host, port), logRequests=logRequests, allow_none=allow_none) self.register_introspection_functions() self.register_function(self.larch_exec, 'larch') for method in ('ls', 'chdir', 'cd', 'cwd', 'shutdown', 'set_keepalive_time', 'set_client_info', 'get_client_info', 'get_data', 'get_rawdata', 'get_messages', 'len_messages'): self.register_function(getattr(self, method), method) # sys.stdout = self self.finished = False signal.signal(signal.SIGINT, self.signal_handler) self.activity_thread = Thread(target=self.check_activity) def write(self, text, **kws): self.out_buffer.append(text) def flush(self): pass def set_keepalive_time(self, keepalive_time): """set keepalive time the server will self destruct after keepalive_time of inactivity Arguments: keepalive_time (number): time in seconds """ self.larch("_sys.client.keepalive_time = %f" % keepalive_time) def set_client_info(self, key, value): """set client info Arguments: key (str): category value (str): value to use Notes: the key can actually be any string but include by convention: app application name user user name machine machine name pid process id """ self.larch("_sys.client.%s = '%s'" % (key, value)) def get_client_info(self): """get client info: returns json dictionary of client information """ out = {} client = self.larch.symtable._sys.client for attr in dir(client): out[attr] = getattr(client, attr) return encode4js(out) def get_messages(self): """get (and clear) all output messages (say, from "print()") """ out = "".join(self.out_buffer) self.out_buffer = [] return out def len_messages(self): "length of message buffer" return len(self.out_buffer) def ls(self, dir_name): """list contents of a directory: """ return os.listdir(dir_name) def chdir(self, dir_name): """change directory""" return os.chdir(dir_name) def cd(self, dir_name): """change directory""" return os.chdir(dir_name) def cwd(self): """change directory""" ret = os.getcwd() if sys.platform == 'win32': ret = ret.replace('\\', '/') return ret def signal_handler(self, sig=0, frame=None): self.kill() def kill(self): """handle alarm signal, generated by signal.alarm(t)""" sleep(2.0) self.shutdown() self.server_close() def shutdown(self): "shutdown LarchServer" self.finished = True if self.activity_thread.is_alive(): self.activity_thread.join(POLL_TIME) return 1 def check_activity(self): while not self.finished: sleep(POLL_TIME) # print("Tick ", time()- (self.client.keepalive_time + self.client.last_event)) if time() > (self.client.keepalive_time + self.client.last_event): t = Thread(target=self.kill) t.start() break def larch_exec(self, text): "execute larch command" text = text.strip() if text in ('quit', 'exit', 'EOF'): self.shutdown() else: self.input.put(text, lineno=0) if self.input.complete: self.larch('_sys.client.last_event = %i' % time()) self.input.run() self.flush() return 1 def get_rawdata(self, expr): "return non-json encoded data for a larch expression" return self.larch.eval(expr) def get_data(self, expr): "return json encoded data for a larch expression" self.larch('_sys.client.last_event = %i' % time()) return encode4js(self.larch.eval(expr)) def run(self): """run server until times out""" self.activity_thread.start() while not self.finished: try: self.handle_request() except: break
class TestCase(unittest.TestCase): """testing of asteval""" def setUp(self): self.interp = Interpreter() self.symtable = self.interp.symtable self.interp.eval('x = 1') self.outfile = '_stdout_' self.outfile = '_stdout_' self.interp.writer = NamedTemporaryFile('w', delete=False, prefix='larchtest') if not HAS_NUMPY: self.interp("arange = range") def read_stdout(self): time.sleep(0.1) self.interp.writer.flush() out = None with open(self.interp.writer.name) as inp: out = inp.read() return out def tearDown(self): pass # noinspection PyUnresolvedReferences def isvalue(self, sym, val): """assert that a symboltable symbol has a particular value""" tval = self.interp.symtable.get_symbol(sym) if isinstance(val, np.ndarray): return self.assertTrue(np.all(tval == val)) else: return self.assertTrue(tval == val) def isnear(self, expr, val, places=7): """assert that a symboltable symbol is near a particular value""" oval = self.interp(expr) if HAS_NUMPY and isinstance(val, np.ndarray): for x, y in zip(oval, val): self.assertAlmostEqual(x, y, places=places) else: return self.assertAlmostEqual(oval, val, places=places) # noinspection PyUnresolvedReferences def istrue(self, expr): """assert that an expression evaluates to True""" val = self.interp(expr) if HAS_NUMPY and isinstance(val, np.ndarray): val = np.all(val) return self.assertTrue(val) # noinspection PyUnresolvedReferences def isfalse(self, expr): """assert that an expression evaluates to False""" val = self.interp(expr) if HAS_NUMPY and isinstance(val, np.ndarray): val = np.all(val) return self.assertFalse(val) def check_output(self, chk_str, exact=False): self.interp.writer.flush() out = self.read_stdout().split('\n') if out: if exact: return chk_str == out[0] return chk_str in out[0] return False def check_error(self, chk_type, chk_msg=''): #trye if chk_type is None: self.assertEqual(0, len(self.interp.error)) else: errtype, errmsg = self.interp.error[0].get_error() self.assertEqual(errtype, chk_type) if chk_msg: self.assertTrue(chk_msg in errmsg)
class LarchServer(SimpleXMLRPCServer): def __init__(self, host='localhost', port=4966, logRequests=False, allow_none=True, keepalive_time=3*24*3600): self.out_buffer = [] self.larch = Interpreter(writer=self) self.input = InputText(prompt='', _larch=self.larch) self.larch.run_init_scripts() self.larch('_sys.client = group(keepalive_time=%f)' % keepalive_time) self.larch('_sys.wx = group(wxapp=None)') _sys = self.larch.symtable._sys _sys.color_exceptions = False _sys.client.last_event = int(time()) _sys.client.pid_server = int(os.getpid()) _sys.client.app = 'unknown' _sys.client.pid = 0 _sys.client.user = '******' _sys.client.machine = 'unknown' self.client = self.larch.symtable._sys.client SimpleXMLRPCServer.__init__(self, (host, port), logRequests=logRequests, allow_none=allow_none) self.register_introspection_functions() self.register_function(self.larch_exec, 'larch') for method in ('ls', 'chdir', 'cd', 'cwd', 'shutdown', 'set_keepalive_time', 'set_client_info', 'get_client_info', 'get_data', 'get_rawdata', 'get_messages', 'len_messages'): self.register_function(getattr(self, method), method) # sys.stdout = self self.finished = False signal.signal(signal.SIGINT, self.signal_handler) self.activity_thread = Thread(target=self.check_activity) def write(self, text, **kws): if text is None: text = '' self.out_buffer.append(str(text)) def flush(self): pass def set_keepalive_time(self, keepalive_time): """set keepalive time the server will self destruct after keepalive_time of inactivity Arguments: keepalive_time (number): time in seconds """ self.larch("_sys.client.keepalive_time = %f" % keepalive_time) def set_client_info(self, key, value): """set client info Arguments: key (str): category value (str): value to use Notes: the key can actually be any string but include by convention: app application name user user name machine machine name pid process id """ self.larch("_sys.client.%s = '%s'" % (key, value)) def get_client_info(self): """get client info: returns json dictionary of client information """ out = {} client = self.larch.symtable._sys.client for attr in dir(client): out[attr] = getattr(client, attr) return encode4js(out) def get_messages(self): """get (and clear) all output messages (say, from "print()") """ out = "".join(self.out_buffer) self.out_buffer = [] return out def len_messages(self): "length of message buffer" return len(self.out_buffer) def ls(self, dir_name): """list contents of a directory: """ return os.listdir(dir_name) def chdir(self, dir_name): """change directory""" return os.chdir(dir_name) def cd(self, dir_name): """change directory""" return os.chdir(dir_name) def cwd(self): """change directory""" ret = os.getcwd() if sys.platform == 'win32': ret = ret.replace('\\','/') return ret def signal_handler(self, sig=0, frame=None): self.kill() def kill(self): """handle alarm signal, generated by signal.alarm(t)""" sleep(2.0) self.shutdown() self.server_close() def shutdown(self): "shutdown LarchServer" self.finished = True if self.activity_thread.is_alive(): self.activity_thread.join(POLL_TIME) return 1 def check_activity(self): while not self.finished: sleep(POLL_TIME) # print("Tick ", time()- (self.client.keepalive_time + self.client.last_event)) if time() > (self.client.keepalive_time + self.client.last_event): t = Thread(target=self.kill) t.start() break def larch_exec(self, text): "execute larch command" text = text.strip() if text in ('quit', 'exit', 'EOF'): self.shutdown() else: self.input.put(text, lineno=0) if self.input.complete: self.larch('_sys.client.last_event = %i' % time()) self.input.run() self.flush() return 1 def get_rawdata(self, expr): "return non-json encoded data for a larch expression" return self.larch.eval(expr) def get_data(self, expr): "return json encoded data for a larch expression" self.larch('_sys.client.last_event = %i' % time()) return encode4js(self.larch.eval(expr)) def run(self): """run server until times out""" self.activity_thread.start() while not self.finished: try: self.handle_request() except: break
class SpykShell(): ps1 = 'Spyk >' ps2 = ' ... >' def __init__(self, wxparent=None, writer=None, _larch=None, prompt=None, historyfile=None, output=None, input=None): self._larch = _larch self.textstyle = None if _larch is None: self._larch = Interpreter(historyfile=historyfile, writer=self) self._larch.run_init_scripts() self.symtable = self._larch.symtable self.prompt = prompt self.input = input self.output = output self.set_textstyle(mode='text') self._larch("_sys.display.colors['text2'] = {'color': 'blue'}", add_history=False) self._larch.add_plugin('wx', wxparent=wxparent) self.symtable.set_symbol('_builtin.force_wxupdate', False) self.symtable.set_symbol('_sys.wx.force_wxupdate', False) self.symtable.set_symbol('_sys.wx.wxapp', output) self.symtable.set_symbol('_sys.wx.parent', wx.GetApp().GetTopWindow()) if self.output is not None: style = self.output.GetDefaultStyle() bgcol = style.GetBackgroundColour() sfont = style.GetFont() self.textstyle = wx.TextAttr('black', bgcol, sfont) self.SetPrompt(True) self.flush_timer = wx.Timer(wxparent) self.needs_flush = True wxparent.Bind(wx.EVT_TIMER, self.onFlushTimer, self.flush_timer) self.flush_timer.Start(500) def onUpdate(self, event=None): symtable = self.symtable if symtable.get_symbol('_builtin.force_wxupdate', create=True): app = wx.GetApp() evtloop = wx.EventLoop() while evtloop.Pending(): evtloop.Dispatch() app.ProcessIdle() symtable.set_symbol('_builtin.force_wxupdate', False) def SetPrompt(self, complete): if self.prompt is None: return sprompt, scolor = self.ps1, '#000075' if not complete: sprompt, scolor = self.ps2, '#E00075' self.prompt.SetLabel(sprompt) self.prompt.SetForegroundColour(scolor) self.prompt.Refresh() def set_textstyle(self, mode='text'): if self.output is None: return display_colors = self._larch.symtable._sys.display.colors textattrs = display_colors.get(mode, {'color':'black'}) color = textattrs['color'] style = self.output.GetDefaultStyle() bgcol = style.GetBackgroundColour() sfont = style.GetFont() self.textstyle = wx.TextAttr(color, bgcol, sfont) def write(self, text, **kws): if self.output is None: sys.stdout.write(text) sys.stdout.flush() else: pos0 = self.output.GetLastPosition() self.output.WriteText(text) pos1 = self.output.GetLastPosition() self.output.SetStyle(pos0, pos1, self.textstyle) self.needs_flush = True def flush(self, *args): try: self.output.SetInsertionPoint(self.output.GetLastPosition()) except: pass self.output.Refresh() self.output.Update() self.needs_flush = False def clear_input(self): self._larch.input.clear() self.SetPrompt(True) def onFlushTimer(self, event=None): if self.needs_flush: self.flush() def eval(self, text, add_history=True, **kws): if text is None: return if text.startswith('!'): return os.system(text[1:]) else: if add_history: self.input.AddToHistory(text) self.write(">%s\n" % text) ret = self._larch.eval(text, add_history=add_history) if self._larch.error: self._larch.input.clear() self._larch.writer.set_textstyle('error') self._larch.show_errors() self._larch.writer.set_textstyle('text') elif ret is not None: self._larch.writer.write("%s\n" % repr(ret)) self.SetPrompt(self._larch.input.complete)
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): _larch = self.larch 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']) self.wxparent.SetIcon(wx.Icon(self.get_iconfile(), wx.BITMAP_TYPE_ICO)) 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 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 filename2group(self, filename): "convert filename (as displayed) to larch group" return self.get_group(self.file_groups[str(filename)]) 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.yerr = getattr(this, 'd' + yarray, 1.0) if yarray != 'mu': this.mu = this.ydat 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', 'norm_mback', 'norm_vict', 'norm_poly'): 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()