class ColumnDataFileFrame(wx.Frame) : """Column Data File, select columns""" def __init__(self, parent, filename=None, groupname=None, last_array_sel=None, read_ok_cb=None, edit_groupname=True, _larch=None): self.parent = parent self._larch = _larch self.path = filename self.extra_sums = {} group = self.initgroup = self.read_column_file(self.path) self.subframes = {} self.workgroup = Group(raw=group) for attr in ('path', 'filename', 'groupname', 'datatype', 'array_labels', 'data'): setattr(self.workgroup, attr, getattr(group, attr, None)) arr_labels = [l.lower() for l in self.initgroup.array_labels] self.orig_labels = arr_labels[:] if self.workgroup.datatype is None: self.workgroup.datatype = 'raw' for arrlab in arr_labels[:4]: if 'energ' in arrlab: self.workgroup.datatype = 'xas' self.read_ok_cb = read_ok_cb self.array_sel = {'xpop': '', 'xarr': None, 'ypop': '', 'yop': '/', 'yarr1': None, 'yarr2': None, 'use_deriv': False} if last_array_sel is not None: self.array_sel.update(last_array_sel) if self.array_sel['yarr2'] is None and 'i0' in arr_labels: self.array_sel['yarr2'] = 'i0' if self.array_sel['yarr1'] is None: if 'itrans' in arr_labels: self.array_sel['yarr1'] = 'itrans' elif 'i1' in arr_labels: self.array_sel['yarr1'] = 'i1' message = "Data Columns for %s" % group.filename wx.Frame.__init__(self, None, -1, 'Build Arrays from Data Columns for %s' % group.filename, style=FRAMESTYLE) x0, y0 = parent.GetPosition() self.SetPosition((x0+60, y0+60)) self.SetFont(Font(10)) panel = wx.Panel(self) self.SetMinSize((600, 600)) self.colors = GUIColors() # title row title = SimpleText(panel, message, font=Font(13), colour=self.colors.title, style=LEFT) opts = dict(action=self.onUpdate, size=(120, -1)) yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = self.xarr_labels = arr_labels + ['_index'] self.xarr = Choice(panel, choices=xarr_labels, **opts) self.yarr1 = Choice(panel, choices= arr_labels, **opts) self.yarr2 = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr.Disable() self.datatype = Choice(panel, choices=DATATYPES, **opts) self.datatype.SetStringSelection(self.workgroup.datatype) opts['size'] = (50, -1) self.yop = Choice(panel, choices=ARR_OPS, **opts) opts['size'] = (150, -1) self.use_deriv = Check(panel, label='use derivative', default=self.array_sel['use_deriv'], **opts) self.xpop = Choice(panel, choices=XPRE_OPS, **opts) self.ypop = Choice(panel, choices=YPRE_OPS, **opts) opts['action'] = self.onYerrChoice self.yerr_op = Choice(panel, choices=YERR_OPS, **opts) self.yerr_op.SetSelection(0) self.yerr_const = FloatCtrl(panel, value=1, precision=4, size=(90, -1)) ylab = SimpleText(panel, 'Y = ') xlab = SimpleText(panel, 'X = ') yerr_lab = SimpleText(panel, 'Yerror = ') self.xsuf = SimpleText(panel, '') self.ysuf = SimpleText(panel, '') self.message = SimpleText(panel, '', font=Font(11), colour=self.colors.title, style=LEFT) self.xpop.SetStringSelection(self.array_sel['xpop']) self.ypop.SetStringSelection(self.array_sel['ypop']) self.yop.SetStringSelection(self.array_sel['yop']) if '(' in self.array_sel['ypop']: self.ysuf.SetLabel(')') ixsel, iysel, iy2sel = 0, 1, len(yarr_labels)-1 if self.array_sel['xarr'] in xarr_labels: ixsel = xarr_labels.index(self.array_sel['xarr']) if self.array_sel['yarr1'] in arr_labels: iysel = arr_labels.index(self.array_sel['yarr1']) if self.array_sel['yarr2'] in yarr_labels: iy2sel = yarr_labels.index(self.array_sel['yarr2']) self.xarr.SetSelection(ixsel) self.yarr1.SetSelection(iysel) self.yarr2.SetSelection(iy2sel) bpanel = wx.Panel(panel) bsizer = wx.BoxSizer(wx.HORIZONTAL) _ok = Button(bpanel, 'OK', action=self.onOK) _cancel = Button(bpanel, 'Cancel', action=self.onCancel) _edit = Button(bpanel, 'Edit Array Names', action=self.onEditNames) _add = Button(bpanel, 'Select Columns to Sum', action=self.onAddColumns) bsizer.Add(_ok) bsizer.Add(_cancel) bsizer.Add(_edit) bsizer.Add(_add) _ok.SetDefault() pack(bpanel, bsizer) sizer = wx.GridBagSizer(4, 8) sizer.Add(title, (0, 0), (1, 7), LEFT, 5) ir = 1 sizer.Add(xlab, (ir, 0), (1, 1), LEFT, 0) sizer.Add(self.xpop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.xarr, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.xsuf, (ir, 3), (1, 1), CEN, 0) ir += 1 sizer.Add(ylab, (ir, 0), (1, 1), LEFT, 0) sizer.Add(self.ypop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yarr1, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.yop, (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yarr2, (ir, 4), (1, 1), CEN, 0) sizer.Add(self.ysuf, (ir, 5), (1, 1), CEN, 0) sizer.Add(self.use_deriv, (ir, 6), (1, 1), LEFT, 0) ir += 1 sizer.Add(yerr_lab, (ir, 0), (1, 1), LEFT, 0) sizer.Add(self.yerr_op, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yerr_arr, (ir, 2), (1, 1), CEN, 0) sizer.Add(SimpleText(panel, 'Value:'), (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yerr_const, (ir, 4), (1, 2), CEN, 0) ir += 1 sizer.Add(SimpleText(panel, 'Data Type:'), (ir, 0), (1, 1), LEFT, 0) sizer.Add(self.datatype, (ir, 1), (1, 2), LEFT, 0) self.wid_filename = wx.TextCtrl(panel, value=group.filename, size=(300, -1)) self.wid_groupname = wx.TextCtrl(panel, value=group.groupname, size=(150, -1)) if not edit_groupname: self.wid_groupname.Disable() ir += 1 sizer.Add(SimpleText(panel, 'Displayed Name:'), (ir, 0), (1, 1), LEFT, 0) sizer.Add(self.wid_filename, (ir, 1), (1, 2), LEFT, 0) ir += 1 sizer.Add(SimpleText(panel, 'Group/Code Name:'), (ir, 0), (1, 1), LEFT, 0) sizer.Add(self.wid_groupname, (ir, 1), (1, 2), LEFT, 0) sizer.Add(self.message, (ir, 3), (1, 4), LEFT, 0) ir += 1 sizer.Add(bpanel, (ir, 0), (1, 5), LEFT, 3) pack(panel, sizer) self.nb = fnb.FlatNotebook(self, -1, agwStyle=FNB_STYLE) self.nb.SetTabAreaColour(wx.Colour(248,248,240)) self.nb.SetActiveTabColour(wx.Colour(254,254,195)) self.nb.SetNonActiveTabTextColour(wx.Colour(40,40,180)) self.nb.SetActiveTabTextColour(wx.Colour(80,0,0)) self.plotpanel = PlotPanel(self, messenger=self.plot_messages) self.plotpanel.SetMinSize((200, 200)) textpanel = wx.Panel(self) ftext = wx.TextCtrl(textpanel, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(400, 250)) ftext.SetValue(group.text) ftext.SetFont(Font(10)) textsizer = wx.BoxSizer(wx.VERTICAL) textsizer.Add(ftext, 1, LEFT|wx.GROW, 1) pack(textpanel, textsizer) self.nb.AddPage(textpanel, ' Text of Data File ', True) self.nb.AddPage(self.plotpanel, ' Plot of Selected Arrays ', True) mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 0, wx.GROW|wx.ALL, 2) mainsizer.Add(self.nb, 1, LEFT|wx.GROW, 2) pack(self, mainsizer) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-1, -1]) statusbar_fields = [group.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.Show() self.Raise() self.onUpdate(self) def read_column_file(self, path): """read column file, generally as initial read""" parent, filename = os.path.split(path) with open(path, 'r') as fh: lines = fh.readlines() text = ''.join(lines) line1 = lines[0].lower() reader = 'read_ascii' if 'epics stepscan file' in line1: reader = 'read_gsexdi' elif 'xdi' in line1: reader = 'read_xdi' elif 'epics scan' in line1: reader = 'read_gsescan' tmpname = '_tmp_file_' read_cmd = "%s = %s('%s')" % (tmpname, reader, path) self.reader = reader _larch = self._larch if (not isinstance(_larch, larch.Interpreter) and hasattr(_larch, '_larch')): _larch = _larch._larch try: _larch.eval(read_cmd, add_history=True) except: pass if _larch.error: msg = ["Error trying to read '%s':" % path, ""] for err in _larch.error: exc_name, errmsg = err.get_error() msg.append(errmsg) title = "Cannot read %s" % path r = Popup(self.parent, "\n".join(msg), title) return None group = _larch.symtable.get_symbol(tmpname) _larch.symtable.del_symbol(tmpname) group.text = text group.path = path group.filename = filename group.groupname = file2groupname(filename, symtable=self._larch.symtable) return group def show_subframe(self, name, frameclass, **opts): shown = False if name in self.subframes: try: self.subframes[name].Raise() shown = True except: pass if not shown: self.subframes[name] = frameclass(self, **opts) self.subframes[name].Show() self.subframes[name].Raise() def onAddColumns(self, event=None): self.show_subframe('addcol', AddColumnsFrame, group=self.workgroup, on_ok=self.add_columns) def add_columns(self, label, selection): new_labels = self.workgroup.array_labels self.set_array_labels(new_labels) self.yarr1.SetStringSelection(new_labels[-1]) self.extra_sums[label] = selection self.onUpdate() def onEditNames(self, evt=None): self.show_subframe('editcol', EditColumnFrame, group=self.workgroup, on_ok=self.set_array_labels) def set_array_labels(self, arr_labels): self.workgroup.array_labels = arr_labels yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = self.xarr_labels = arr_labels + ['_index'] def update(wid, choices): curstr = wid.GetStringSelection() curind = wid.GetSelection() wid.SetChoices(choices) if curstr in choices: wid.SetStringSelection(curstr) else: wid.SetSelection(curind) update(self.xarr, xarr_labels) update(self.yarr1, yarr_labels) update(self.yarr2, yarr_labels) update(self.yerr_arr, yarr_labels) self.onUpdate() def onOK(self, event=None): """ build arrays according to selection """ user_filename = self.wid_filename.GetValue() if self.wid_groupname is not None: groupname = fix_varname(self.wid_groupname.GetValue()) yerr_op = self.yerr_op.GetStringSelection().lower() yerr_expr = '1' if yerr_op.startswith('const'): yerr_expr = "%f" % self.yerr_const.GetValue() elif yerr_op.startswith('array'): yerr_expr = '%%s.data[%i, :]' % self.yerr_arr.GetSelection() elif yerr_op.startswith('sqrt'): yerr_expr = 'sqrt(%s.ydat)' self.expressions['yerr'] = yerr_expr # generate script to pass back to calling program: read_cmd = "%s('{path}', labels='%s')" % (self.reader, ', '.join(self.orig_labels)) buff = ["{group} = %s" % read_cmd, "{group}.path = '{path}'", "{group}.is_frozen = False"] for label, selection in self.extra_sums.items(): buff.append("{group}.array_labels.append('%s')" % label) buff.append("_tmparr = {group}.data[%s, :].sum(axis=0)" % repr(selection)) buff.append("_tmpn = len(_tmparr)") buff.append("{group}.data = append({group}.data, _tmparr.reshape(1, _tmpn), axis=0)") buff.append("del _tmparr, _tmpn") for attr in ('datatype', 'plot_xlabel', 'plot_ylabel'): val = getattr(self.workgroup, attr) buff.append("{group}.%s = '%s'" % (attr, val)) for aname in ('xdat', 'ydat', 'yerr'): expr = self.expressions[aname].replace('%s', '{group:s}') buff.append("{group}.%s = %s" % (aname, expr)) if getattr(self.workgroup, 'datatype', 'raw') == 'xas': if self.reader == 'read_gsescan': buff.append("{group}.energy = {group}.x") else: buff.append("{group}.energy = {group}.xdat") buff.append("{group}.mu = {group}.ydat") buff.append("sort_xafs({group}, overwrite=True, fix_repeats=True)") else: buff.append("{group}.scale = 1./({group}.ydat.ptp()+1.e-16)") script = "\n".join(buff) if self.read_ok_cb is not None: self.read_ok_cb(script, self.path, groupname=groupname, filename=user_filename, array_sel=self.array_sel) for f in self.subframes.values(): try: f.Destroy() except: pass self.Destroy() def onCancel(self, event=None): self.workgroup.import_ok = False for f in self.subframes.values(): try: f.Destroy() except: pass self.Destroy() def onYerrChoice(self, evt=None): yerr_choice = evt.GetString() self.yerr_arr.Disable() self.yerr_const.Disable() if 'const' in yerr_choice.lower(): self.yerr_const.Enable() elif 'array' in yerr_choice.lower(): self.yerr_arr.Enable() self.onUpdate() def onUpdate(self, value=None, evt=None): """column selections changed calc xdat and ydat""" # dtcorr = self.dtcorr.IsChecked() dtcorr = False use_deriv = self.use_deriv.IsChecked() rawgroup = self.initgroup workgroup = self.workgroup rdata = self.initgroup.data ix = self.xarr.GetSelection() xname = self.xarr.GetStringSelection() exprs = dict(xdat=None, ydat=None, yerr=None) ncol, npts = rdata.shape workgroup.index = 1.0*np.arange(npts) if xname.startswith('_index') or ix >= ncol: workgroup.xdat = 1.0*np.arange(npts) xname = '_index' exprs['xdat'] = 'arange(%i)' % npts else: workgroup.xdat = rdata[ix, :] exprs['xdat'] = '%%s.data[%i, : ]' % ix workgroup.datatype = self.datatype.GetStringSelection().strip().lower() def pre_op(opwid, arr): opstr = opwid.GetStringSelection().strip() suf = '' if opstr in ('-log(', 'log('): suf = ')' if opstr == 'log(': arr = np.log(arr) elif opstr == '-log(': arr = -np.log(arr) arr[np.where(np.isnan(arr))] = 0 return suf, opstr, arr try: xsuf, xpop, workgroup.xdat = pre_op(self.xpop, workgroup.xdat) self.xsuf.SetLabel(xsuf) exprs['xdat'] = '%s%s%s' % (xpop, exprs['xdat'], xsuf) except: return try: xunits = rawgroup.array_units[ix].strip() xlabel = '%s (%s)' % (xname, xunits) except: xlabel = xname yname1 = self.yarr1.GetStringSelection().strip() yname2 = self.yarr2.GetStringSelection().strip() iy1 = self.yarr1.GetSelection() iy2 = self.yarr2.GetSelection() yop = self.yop.GetStringSelection().strip() ylabel = yname1 if len(yname2) == 0: yname2 = '1.0' else: ylabel = "%s%s%s" % (ylabel, yop, yname2) if yname1 == '0.0': yarr1 = np.zeros(npts)*1.0 yexpr1 = 'zeros(%i)' % npts elif len(yname1) == 0 or yname1 == '1.0' or iy1 >= ncol: yarr1 = np.ones(npts)*1.0 yexpr1 = 'ones(%i)' % npts else: yarr1 = rdata[iy1, :] yexpr1 = '%%s.data[%i, : ]' % iy1 if yname2 == '0.0': yarr2 = np.zeros(npts)*1.0 yexpr2 = '0.0' elif len(yname2) == 0 or yname2 == '1.0' or iy2 >= ncol: yarr2 = np.ones(npts)*1.0 yexpr2 = '1.0' else: yarr2 = rdata[iy2, :] yexpr2 = '%%s.data[%i, : ]' % iy2 workgroup.ydat = yarr1 exprs['ydat'] = yexpr1 if yop in ('+', '-', '*', '/'): exprs['ydat'] = "%s %s %s" % (yexpr1, yop, yexpr2) if yop == '+': workgroup.ydat = yarr1.__add__(yarr2) elif yop == '-': workgroup.ydat = yarr1.__sub__(yarr2) elif yop == '*': workgroup.ydat = yarr1.__mul__(yarr2) elif yop == '/': workgroup.ydat = yarr1.__truediv__(yarr2) ysuf, ypop, workgroup.ydat = pre_op(self.ypop, workgroup.ydat) self.ysuf.SetLabel(ysuf) exprs['ydat'] = '%s%s%s' % (ypop, exprs['ydat'], ysuf) yerr_op = self.yerr_op.GetStringSelection().lower() exprs['yerr'] = '1' if yerr_op.startswith('const'): yerr = self.yerr_const.GetValue() exprs['yerr'] = '%f' % yerr elif yerr_op.startswith('array'): iyerr = self.yerr_arr.GetSelection() yerr = rdata[iyerr, :] exprs['yerr'] = '%%s.data[%i, :]' % iyerr elif yerr_op.startswith('sqrt'): yerr = np.sqrt(workgroup.ydat) exprs['yerr'] = 'sqrt(%s.ydat)' if use_deriv: try: workgroup.ydat = (np.gradient(workgroup.ydat) / np.gradient(workgroup.xdat)) exprs['ydat'] = 'deriv(%s)/deriv(%s)' % (exprs['ydat'], exprs['xdat']) except: pass self.expressions = exprs self.array_sel = {'xpop': xpop, 'xarr': xname, 'ypop': ypop, 'yop': yop, 'yarr1': yname1, 'yarr2': yname2, 'use_deriv': use_deriv} try: npts = min(len(workgroup.xdat), len(workgroup.ydat)) except AttributeError: return except ValueError: return en = workgroup.xdat if ((workgroup.datatype == 'xas') and ((len(en) > 1000 or any(np.diff(en) < 0) or ((max(en)-min(en)) > 350 and (np.diff(en[:100]).mean() < 1.0))))): self.message.SetLabel("Warning: XAS data may need to be rebinned!") else: self.message.SetLabel("") workgroup.filename = rawgroup.filename workgroup.npts = npts workgroup.plot_xlabel = xlabel workgroup.plot_ylabel = ylabel workgroup.xdat = np.array(workgroup.xdat[:npts]) workgroup.ydat = np.array(workgroup.ydat[:npts]) workgroup.y = workgroup.ydat workgroup.yerr = yerr if isinstance(yerr, np.ndarray): workgroup.yerr = np.array(yerr[:npts]) if workgroup.datatype == 'xas': workgroup.energy = workgroup.xdat workgroup.mu = workgroup.ydat path, fname = os.path.split(workgroup.filename) popts = dict(marker='o', markersize=4, linewidth=1.5, title=fname, ylabel=ylabel, xlabel=xlabel, label="%s: %s" % (fname, workgroup.plot_ylabel)) self.plotpanel.plot(workgroup.xdat, workgroup.ydat, **popts) for i in range(self.nb.GetPageCount()): if 'plot' in self.nb.GetPageText(i).lower(): self.nb.SetSelection(i) def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel)