def build_display(self): panel = self.panel self.wids = {} self.plotone_op = Choice(panel, choices=list(PlotOne_Choices.keys()), action=self.onPlotOne, size=(200, -1)) self.plotsel_op = Choice(panel, choices=list(PlotSel_Choices.keys()), action=self.onPlotSel, size=(200, -1)) self.plotone_op.SetSelection(1) self.plotsel_op.SetSelection(1) plot_one = Button(panel, 'Plot Current Group', size=(170, -1), action=self.onPlotOne) plot_sel = Button(panel, 'Plot Selected Groups', size=(170, -1), action=self.onPlotSel) e0panel = wx.Panel(panel) self.wids['auto_e0'] = Check(e0panel, default=True, label='auto?', action=self.onSet_XASE0) self.wids['showe0'] = Check(e0panel, default=True, label='show?', action=self.onSet_XASE0) sx = wx.BoxSizer(wx.HORIZONTAL) sx.Add(self.wids['auto_e0'], 0, LEFT, 4) sx.Add(self.wids['showe0'], 0, LEFT, 4) pack(e0panel, sx) self.wids['auto_step'] = Check(panel, default=True, label='auto?', action=self.onNormMethod) self.wids['nvict'] = Choice(panel, choices=('0', '1', '2', '3'), size=(100, -1), action=self.onNormMethod, default=0) self.wids['nnorm'] = Choice(panel, choices=list(Nnorm_choices.values()), size=(100, -1), action=self.onNormMethod, default=0) opts = { 'size': (100, -1), 'digits': 2, 'increment': 5.0, 'action': self.onSet_Ranges } xas_pre1 = self.add_floatspin('pre1', value=defaults['pre1'], **opts) xas_pre2 = self.add_floatspin('pre2', value=defaults['pre2'], **opts) xas_norm1 = self.add_floatspin('norm1', value=defaults['norm1'], **opts) xas_norm2 = self.add_floatspin('norm2', value=defaults['norm2'], **opts) opts = {'digits': 3, 'increment': 0.1, 'value': 0} plot_voff = self.add_floatspin('plot_voff', with_pin=False, size=(80, -1), action=self.onVoffset, **opts) xas_e0 = self.add_floatspin('e0', action=self.onSet_XASE0Val, **opts) xas_step = self.add_floatspin('step', action=self.onSet_XASStep, with_pin=False, min_val=0.0, **opts) opts['value'] = 1.0 scale = self.add_floatspin('scale', action=self.onSet_Scale, **opts) self.wids['norm_method'] = Choice( panel, choices=('polynomial', 'mback'), # , 'area'), size=(120, -1), action=self.onNormMethod) self.wids['norm_method'].SetSelection(0) atsyms = ['?'] + self.larch.symtable._xray._xraydb.atomic_symbols edges = ('K', 'L3', 'L2', 'L1', 'M5') self.wids['atsym'] = Choice(panel, choices=atsyms, size=(75, -1)) self.wids['edge'] = Choice(panel, choices=edges, size=(60, -1)) self.wids['is_frozen'] = Check(panel, default=False, label='Freeze Group', action=self.onFreezeGroup) saveconf = Button(panel, 'Save as Default Settings', size=(200, -1), action=self.onSaveConfigBtn) use_auto = Button(panel, 'Use Default Settings', size=(200, -1), action=self.onAutoNorm) copy_auto = Button(panel, 'Copy', size=(60, -1), action=self.onCopyAuto) def CopyBtn(name): return Button(panel, 'Copy', size=(60, -1), action=partial(self.onCopyParam, name)) add_text = self.add_text HLINEWID = 575 panel.Add(SimpleText(panel, 'XAS Pre-edge subtraction and Normalization', **self.titleopts), dcol=4) panel.Add(SimpleText(panel, 'Copy to Selected Groups:'), style=RIGHT, dcol=2) panel.Add(plot_sel, newrow=True) panel.Add(self.plotsel_op, dcol=3) panel.Add(SimpleText(panel, 'Y Offset:'), style=RIGHT) panel.Add(plot_voff, style=RIGHT) panel.Add(plot_one, newrow=True) panel.Add(self.plotone_op, dcol=4) panel.Add(CopyBtn('plotone_op'), dcol=1, style=RIGHT) panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=6, newrow=True) add_text('Non-XAS Data Scale:') panel.Add(scale, dcol=2) panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=6, newrow=True) add_text('XAS Data:') panel.Add(use_auto, dcol=4) panel.Add(copy_auto, dcol=1, style=RIGHT) add_text('Element and Edge: ', newrow=True) panel.Add(self.wids['atsym']) panel.Add(self.wids['edge'], dcol=3) panel.Add(CopyBtn('atsym'), dcol=1, style=RIGHT) add_text('E0 : ') panel.Add(xas_e0) panel.Add(e0panel, dcol=3) panel.Add(CopyBtn('xas_e0'), dcol=1, style=RIGHT) add_text('Edge Step: ') panel.Add(xas_step) panel.Add(self.wids['auto_step'], dcol=3) panel.Add(CopyBtn('xas_step'), dcol=1, style=RIGHT) panel.Add((5, 5), newrow=True) panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=6, newrow=True) add_text('Pre-edge range: ') panel.Add(xas_pre1) add_text(' : ', newrow=False) panel.Add(xas_pre2, dcol=2) panel.Add(CopyBtn('xas_pre'), dcol=1, style=RIGHT) panel.Add(SimpleText(panel, 'Victoreen order:'), newrow=True) panel.Add(self.wids['nvict'], dcol=4) panel.Add((5, 5), newrow=True) panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=6, newrow=True) add_text('Normalization method: ') panel.Add(self.wids['norm_method'], dcol=4) panel.Add(CopyBtn('xas_norm'), dcol=1, style=RIGHT) add_text('Normalization range: ') panel.Add(xas_norm1) add_text(' : ', newrow=False) panel.Add(xas_norm2, dcol=2) panel.Add(SimpleText(panel, 'Polynomial Type:'), newrow=True) panel.Add(self.wids['nnorm'], dcol=4) panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=6, newrow=True) panel.Add((5, 5), newrow=True) panel.Add(self.wids['is_frozen'], newrow=True) panel.Add(saveconf, dcol=5) panel.Add((5, 5), newrow=True) panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=6, newrow=True) panel.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((5, 5), 0, LEFT, 3) sizer.Add(panel, 0, LEFT, 3) sizer.Add((5, 5), 0, LEFT, 3) pack(self, sizer)
def build_display(self): self.mod_nb = flat_nb.FlatNotebook(self, -1, agwStyle=FNB_STYLE) self.mod_nb.SetTabAreaColour(wx.Colour(250,250,250)) self.mod_nb.SetActiveTabColour(wx.Colour(254,254,195)) self.mod_nb.SetNonActiveTabTextColour(wx.Colour(10,10,128)) self.mod_nb.SetActiveTabTextColour(wx.Colour(128,0,0)) self.mod_nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNBChanged) pan = self.panel = GridPanel(self, ncols=4, nrows=4, pad=2, itemstyle=LCEN) self.wids = {} def FloatSpinWithPin(name, value, **kws): s = wx.BoxSizer(wx.HORIZONTAL) self.wids[name] = FloatSpin(pan, value=value, **kws) bb = BitmapButton(pan, get_icon('pin'), size=(25, 25), action=partial(self.onSelPoint, opt=name), tooltip='use last point selected from plot') s.Add(self.wids[name]) s.Add(bb) return s opts = dict(digits=2, increment=0.1) ppeak_e0 = FloatSpinWithPin('ppeak_e0', value=0, **opts) ppeak_elo = FloatSpinWithPin('ppeak_elo', value=-15, **opts) ppeak_ehi = FloatSpinWithPin('ppeak_ehi', value=-5, **opts) ppeak_emin = FloatSpinWithPin('ppeak_emin', value=-30, **opts) ppeak_emax = FloatSpinWithPin('ppeak_emax', value=0, **opts) self.fitbline_btn = Button(pan,'Fit Baseline', action=self.onFitBaseline, size=(150, 25)) self.fitmodel_btn = Button(pan, 'Fit Model', action=self.onFitModel, size=(150, 25)) self.fitsel_btn = Button(pan, 'Fit Selected Groups', action=self.onFitSelected, size=(150, 25)) self.fitmodel_btn.Disable() self.fitsel_btn.Disable() self.array_choice = Choice(pan, size=(150, -1), choices=list(Array_Choices.keys())) self.array_choice.SetSelection(1) models_peaks = Choice(pan, size=(150, -1), choices=ModelChoices['peaks'], action=self.addModel) models_other = Choice(pan, size=(150, -1), choices=ModelChoices['other'], action=self.addModel) self.plot_choice = Choice(pan, size=(150, -1), choices=PlotChoices, action=self.onPlot) self.message = SimpleText(pan, 'first fit baseline, then add peaks to fit model.') self.msg_centroid = SimpleText(pan, '----') opts = dict(default=True, size=(75, -1), action=self.onPlot) self.show_centroid = Check(pan, label='show?', **opts) self.show_peakrange = Check(pan, label='show?', **opts) self.show_fitrange = Check(pan, label='show?', **opts) self.show_e0 = Check(pan, label='show?', **opts) opts = dict(default=False, size=(200, -1), action=self.onPlot) self.plot_sub_bline = Check(pan, label='Subtract Baseline?', **opts) def add_text(text, dcol=1, newrow=True): pan.Add(SimpleText(pan, text), dcol=dcol, newrow=newrow) titleopts = dict(font=Font(12), colour='#AA0000') pan.Add(SimpleText(pan, ' Pre-edge Peak Fitting', **titleopts), dcol=5) add_text(' Run Fit:', newrow=False) add_text('Array to fit: ') pan.Add(self.array_choice, dcol=3) pan.Add((10, 10)) pan.Add(self.fitbline_btn) add_text('E0: ') pan.Add(ppeak_e0) pan.Add((10, 10), dcol=2) pan.Add(self.show_e0) pan.Add(self.fitmodel_btn) add_text('Fit Energy Range: ') pan.Add(ppeak_emin) add_text(' : ', newrow=False) pan.Add(ppeak_emax) pan.Add(self.show_fitrange) pan.Add(self.fitsel_btn) t = SimpleText(pan, 'Pre-edge Peak Range: ') t.SetToolTip('Range used as mask for background') pan.Add(t, newrow=True) pan.Add(ppeak_elo) add_text(' : ', newrow=False) pan.Add(ppeak_ehi) pan.Add(self.show_peakrange) add_text( 'Peak Centroid: ') pan.Add(self.msg_centroid, dcol=3) pan.Add(self.show_centroid, dcol=1) # plot buttons ts = wx.BoxSizer(wx.HORIZONTAL) ts.Add(self.plot_choice) ts.Add(self.plot_sub_bline) pan.Add(SimpleText(pan, 'Plot: '), newrow=True) pan.Add(ts, dcol=7) # add model ts = wx.BoxSizer(wx.HORIZONTAL) ts.Add(models_peaks) ts.Add(models_other) pan.Add(SimpleText(pan, 'Add Component: '), newrow=True) pan.Add(ts, dcol=7) pan.Add(SimpleText(pan, 'Messages: '), newrow=True) pan.Add(self.message, dcol=7) pan.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((5,5), 0, LCEN, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LCEN, 3) sizer.Add(pan, 0, LCEN, 3) sizer.Add((5,5), 0, LCEN, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LCEN, 3) sizer.Add((5,5), 0, LCEN, 3) sizer.Add(self.mod_nb, 1, LCEN|wx.GROW, 10) pack(self, sizer)
def addModel(self, event=None, model=None, prefix=None, isbkg=False): if model is None and event is not None: model = event.GetString() if model is None or model.startswith('<'): return if prefix is None: p = model[:5].lower() curmodels = ["%s%i_" % (p, i+1) for i in range(1+len(self.fit_components))] for comp in self.fit_components: if comp in curmodels: curmodels.remove(comp) prefix = curmodels[0] label = "%s(prefix='%s')" % (model, prefix) title = "%s: %s " % (prefix[:-1], model) title = prefix[:-1] mclass_kws = {'prefix': prefix} if 'step' in model.lower(): form = model.lower().replace('step', '').strip() if form.startswith('err'): form = 'erf' label = "Step(form='%s', prefix='%s')" % (form, prefix) title = "%s: Step %s" % (prefix[:-1], form[:3]) mclass = lm_models.StepModel mclass_kws['form'] = form minst = mclass(form=form, prefix=prefix) else: if model in ModelFuncs: mclass = getattr(lm_models, ModelFuncs[model]) else: mclass = getattr(lm_models, model+'Model') minst = mclass(prefix=prefix) panel = GridPanel(self.mod_nb, ncols=2, nrows=5, pad=2, itemstyle=CEN) def SLabel(label, size=(80, -1), **kws): return SimpleText(panel, label, size=size, style=wx.ALIGN_LEFT, **kws) usebox = Check(panel, default=True, label='Use in Fit?', size=(100, -1)) bkgbox = Check(panel, default=False, label='Is Baseline?', size=(125, -1)) if isbkg: bkgbox.SetValue(1) delbtn = Button(panel, 'Delete Component', size=(125, -1), action=partial(self.onDeleteComponent, prefix=prefix)) pick2msg = SimpleText(panel, " ", size=(125, -1)) pick2btn = Button(panel, 'Pick Values from Data', size=(150, -1), action=partial(self.onPick2Points, prefix=prefix)) # SetTip(mname, 'Label for the model component') SetTip(usebox, 'Use this component in fit?') SetTip(bkgbox, 'Label this component as "background" when plotting?') SetTip(delbtn, 'Delete this model component') SetTip(pick2btn, 'Select X range on Plot to Guess Initial Values') panel.Add(SLabel(label, size=(275, -1), colour='#0000AA'), dcol=3, style=wx.ALIGN_LEFT, newrow=True) panel.Add(usebox, dcol=1) panel.Add(bkgbox, dcol=2, style=LCEN) panel.Add(delbtn, dcol=1, style=wx.ALIGN_LEFT) panel.Add(pick2btn, dcol=2, style=wx.ALIGN_LEFT, newrow=True) panel.Add(pick2msg, dcol=2, style=wx.ALIGN_RIGHT) # panel.Add((10, 10), newrow=True) # panel.Add(HLine(panel, size=(150, 3)), dcol=4, style=wx.ALIGN_CENTER) panel.Add(SLabel("Parameter "), style=wx.ALIGN_LEFT, newrow=True) panel.AddMany((SLabel(" Value"), SLabel(" Type"), SLabel(' Bounds'), SLabel(" Min", size=(60, -1)), SLabel(" Max", size=(60, -1)), SLabel(" Expression"))) parwids = OrderedDict() parnames = sorted(minst.param_names) for a in minst._func_allargs: pname = "%s%s" % (prefix, a) if (pname not in parnames and a in minst.param_hints and a not in minst.independent_vars): parnames.append(pname) for pname in parnames: sname = pname[len(prefix):] hints = minst.param_hints.get(sname, {}) par = Parameter(name=pname, value=0, vary=True) if 'min' in hints: par.min = hints['min'] if 'max' in hints: par.max = hints['max'] if 'value' in hints: par.value = hints['value'] if 'expr' in hints: par.expr = hints['expr'] pwids = ParameterWidgets(panel, par, name_size=100, expr_size=125, float_size=80, prefix=prefix, widgets=('name', 'value', 'minval', 'maxval', 'vary', 'expr')) parwids[par.name] = pwids panel.Add(pwids.name, newrow=True) panel.AddMany((pwids.value, pwids.vary, pwids.bounds, pwids.minval, pwids.maxval, pwids.expr)) for sname, hint in minst.param_hints.items(): pname = "%s%s" % (prefix, sname) if 'expr' in hint and pname not in parnames: par = Parameter(name=pname, value=0, expr=hint['expr']) pwids = ParameterWidgets(panel, par, name_size=100, expr_size=225, float_size=80, prefix=prefix, widgets=('name', 'value', 'expr')) parwids[par.name] = pwids panel.Add(pwids.name, newrow=True) panel.Add(pwids.value) panel.Add(pwids.expr, dcol=4, style=wx.ALIGN_RIGHT) pwids.value.Disable() fgroup = Group(prefix=prefix, title=title, mclass=mclass, mclass_kws=mclass_kws, usebox=usebox, panel=panel, parwids=parwids, float_size=65, expr_size=150, pick2_msg=pick2msg, bkgbox=bkgbox) self.fit_components[prefix] = fgroup panel.pack() self.mod_nb.AddPage(panel, title, True) sx,sy = self.GetSize() self.SetSize((sx, sy+1)) self.SetSize((sx, sy))
def build_display(self): titleopts = dict(font=Font(12), colour='#AA0000') xas = self.panel self.wids = {} self.plotone_op = Choice(xas, choices=list(PlotOne_Choices.keys()), action=self.onPlotOne, size=(175, -1)) self.plotsel_op = Choice(xas, choices=list(PlotSel_Choices.keys()), action=self.onPlotSel, size=(175, -1)) self.plotone_op.SetSelection(1) self.plotsel_op.SetSelection(1) plot_one = Button(xas, 'Plot This Group', size=(150, -1), action=self.onPlotOne) plot_sel = Button(xas, 'Plot Selected Groups', size=(150, -1), action=self.onPlotSel) opts = dict(action=self.onReprocess) e0opts_panel = wx.Panel(xas) self.wids['autoe0'] = Check(e0opts_panel, default=True, label='auto?', **opts) self.wids['showe0'] = Check(e0opts_panel, default=True, label='show?', **opts) sx = wx.BoxSizer(wx.HORIZONTAL) sx.Add(self.wids['autoe0'], 0, LCEN, 4) sx.Add(self.wids['showe0'], 0, LCEN, 4) pack(e0opts_panel, sx) self.wids['autostep'] = Check(xas, default=True, label='auto?', **opts) opts['size'] = (50, -1) self.wids['vict'] = Choice(xas, choices=('0', '1', '2', '3'), **opts) self.wids['nnor'] = Choice(xas, choices=('0', '1', '2', '3'), **opts) self.wids['vict'].SetSelection(1) self.wids['nnor'].SetSelection(1) opts.update({'size': (100, -1), 'digits': 2, 'increment': 5.0}) xas_pre1 = self.add_floatspin('pre1', value=-1000, **opts) xas_pre2 = self.add_floatspin('pre2', value=-30, **opts) xas_nor1 = self.add_floatspin('nor1', value=50, **opts) xas_nor2 = self.add_floatspin('nor2', value=5000, **opts) opts = {'digits': 2, 'increment': 0.1, 'value': 0} xas_e0 = self.add_floatspin('e0', action=self.onSet_XASE0, **opts) xas_step = self.add_floatspin('step', action=self.onSet_XASStep, with_pin=False, **opts) saveconf = Button(xas, 'Save as Default Settings', size=(200, -1), action=self.onSaveConfigBtn) def CopyBtn(name): return Button(xas, 'Copy', size=(50, -1), action=partial(self.onCopyParam, name)) add_text = self.add_text xas.Add(SimpleText(xas, ' XAS Pre-edge subtraction and Normalization', **titleopts), dcol=4) xas.Add(SimpleText(xas, 'Copy to Selected Groups?'), style=RCEN, dcol=3) xas.Add(plot_sel, newrow=True) xas.Add(self.plotsel_op, dcol=6) xas.Add(plot_one, newrow=True) xas.Add(self.plotone_op, dcol=4) xas.Add((10, 10)) xas.Add(CopyBtn('plotone_op'), style=RCEN) add_text('E0 : ') xas.Add(xas_e0) xas.Add(e0opts_panel, dcol=3) xas.Add((10, 1)) xas.Add(CopyBtn('xas_e0'), style=RCEN) add_text('Edge Step: ') xas.Add(xas_step) xas.Add(self.wids['autostep'], dcol=3) xas.Add((10, 1)) xas.Add(CopyBtn('xas_step'), style=RCEN) add_text('Pre-edge range: ') xas.Add(xas_pre1) add_text(' : ', newrow=False) xas.Add(xas_pre2) xas.Add(SimpleText(xas, 'Victoreen:')) xas.Add(self.wids['vict']) xas.Add(CopyBtn('xas_pre'), style=RCEN) add_text('Normalization range: ') xas.Add(xas_nor1) add_text(' : ', newrow=False) xas.Add(xas_nor2) xas.Add(SimpleText(xas, 'Poly Order:')) xas.Add(self.wids['nnor']) xas.Add(CopyBtn('xas_norm'), style=RCEN) xas.Add(saveconf, dcol=6, newrow=True) xas.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((5, 5), 0, LCEN, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LCEN, 3) sizer.Add(xas, 0, LCEN, 3) sizer.Add((5, 5), 0, LCEN, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LCEN, 3) pack(self, sizer)
class PrePeakPanel(wx.Panel): def __init__(self, parent=None, controller=None, **kws): wx.Panel.__init__(self, parent, -1, size=(550, 625), **kws) self.parent = parent self.controller = controller self.larch = controller.larch self.fit_components = OrderedDict() self.fit_model = None self.fit_params = None self.user_added_params = None self.summary = None self.sizer = wx.GridBagSizer(10, 6) self.build_display() self.pick2_timer = wx.Timer(self) self.pick2_group = None self.Bind(wx.EVT_TIMER, self.onPick2Timer, self.pick2_timer) self.pick2_t0 = 0. self.pick2_timeout = 15. self.pick2erase_timer = wx.Timer(self) self.pick2erase_panel = None self.Bind(wx.EVT_TIMER, self.onPick2EraseTimer, self.pick2erase_timer) def onPanelExposed(self, **kws): # called when notebook is selected try: fname = self.controller.filelist.GetStringSelection() gname = self.controller.file_groups[fname] dgroup = self.controller.get_group(gname) # print(" Fill prepeak panel from group ", fname, gname, dgroup) self.fill_form(dgroup) except: pass # print(" Cannot Fill prepeak panel from group ") def larch_eval(self, cmd): """eval""" self.controller.larch.eval(cmd) def build_display(self): self.mod_nb = flat_nb.FlatNotebook(self, -1, agwStyle=FNB_STYLE) self.mod_nb.SetTabAreaColour(wx.Colour(250,250,250)) self.mod_nb.SetActiveTabColour(wx.Colour(254,254,195)) self.mod_nb.SetNonActiveTabTextColour(wx.Colour(10,10,128)) self.mod_nb.SetActiveTabTextColour(wx.Colour(128,0,0)) self.mod_nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNBChanged) pan = self.panel = GridPanel(self, ncols=4, nrows=4, pad=2, itemstyle=LCEN) self.wids = {} def FloatSpinWithPin(name, value, **kws): s = wx.BoxSizer(wx.HORIZONTAL) self.wids[name] = FloatSpin(pan, value=value, **kws) bb = BitmapButton(pan, get_icon('pin'), size=(25, 25), action=partial(self.onSelPoint, opt=name), tooltip='use last point selected from plot') s.Add(self.wids[name]) s.Add(bb) return s opts = dict(digits=2, increment=0.1) ppeak_e0 = FloatSpinWithPin('ppeak_e0', value=0, **opts) ppeak_elo = FloatSpinWithPin('ppeak_elo', value=-15, **opts) ppeak_ehi = FloatSpinWithPin('ppeak_ehi', value=-5, **opts) ppeak_emin = FloatSpinWithPin('ppeak_emin', value=-30, **opts) ppeak_emax = FloatSpinWithPin('ppeak_emax', value=0, **opts) self.fitbline_btn = Button(pan,'Fit Baseline', action=self.onFitBaseline, size=(150, 25)) self.fitmodel_btn = Button(pan, 'Fit Model', action=self.onFitModel, size=(150, 25)) self.fitsel_btn = Button(pan, 'Fit Selected Groups', action=self.onFitSelected, size=(150, 25)) self.fitmodel_btn.Disable() self.fitsel_btn.Disable() self.array_choice = Choice(pan, size=(150, -1), choices=list(Array_Choices.keys())) self.array_choice.SetSelection(1) models_peaks = Choice(pan, size=(150, -1), choices=ModelChoices['peaks'], action=self.addModel) models_other = Choice(pan, size=(150, -1), choices=ModelChoices['other'], action=self.addModel) self.plot_choice = Choice(pan, size=(150, -1), choices=PlotChoices, action=self.onPlot) self.message = SimpleText(pan, 'first fit baseline, then add peaks to fit model.') self.msg_centroid = SimpleText(pan, '----') opts = dict(default=True, size=(75, -1), action=self.onPlot) self.show_centroid = Check(pan, label='show?', **opts) self.show_peakrange = Check(pan, label='show?', **opts) self.show_fitrange = Check(pan, label='show?', **opts) self.show_e0 = Check(pan, label='show?', **opts) opts = dict(default=False, size=(200, -1), action=self.onPlot) self.plot_sub_bline = Check(pan, label='Subtract Baseline?', **opts) def add_text(text, dcol=1, newrow=True): pan.Add(SimpleText(pan, text), dcol=dcol, newrow=newrow) titleopts = dict(font=Font(12), colour='#AA0000') pan.Add(SimpleText(pan, ' Pre-edge Peak Fitting', **titleopts), dcol=5) add_text(' Run Fit:', newrow=False) add_text('Array to fit: ') pan.Add(self.array_choice, dcol=3) pan.Add((10, 10)) pan.Add(self.fitbline_btn) add_text('E0: ') pan.Add(ppeak_e0) pan.Add((10, 10), dcol=2) pan.Add(self.show_e0) pan.Add(self.fitmodel_btn) add_text('Fit Energy Range: ') pan.Add(ppeak_emin) add_text(' : ', newrow=False) pan.Add(ppeak_emax) pan.Add(self.show_fitrange) pan.Add(self.fitsel_btn) t = SimpleText(pan, 'Pre-edge Peak Range: ') t.SetToolTip('Range used as mask for background') pan.Add(t, newrow=True) pan.Add(ppeak_elo) add_text(' : ', newrow=False) pan.Add(ppeak_ehi) pan.Add(self.show_peakrange) add_text( 'Peak Centroid: ') pan.Add(self.msg_centroid, dcol=3) pan.Add(self.show_centroid, dcol=1) # plot buttons ts = wx.BoxSizer(wx.HORIZONTAL) ts.Add(self.plot_choice) ts.Add(self.plot_sub_bline) pan.Add(SimpleText(pan, 'Plot: '), newrow=True) pan.Add(ts, dcol=7) # add model ts = wx.BoxSizer(wx.HORIZONTAL) ts.Add(models_peaks) ts.Add(models_other) pan.Add(SimpleText(pan, 'Add Component: '), newrow=True) pan.Add(ts, dcol=7) pan.Add(SimpleText(pan, 'Messages: '), newrow=True) pan.Add(self.message, dcol=7) pan.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((5,5), 0, LCEN, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LCEN, 3) sizer.Add(pan, 0, LCEN, 3) sizer.Add((5,5), 0, LCEN, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LCEN, 3) sizer.Add((5,5), 0, LCEN, 3) sizer.Add(self.mod_nb, 1, LCEN|wx.GROW, 10) pack(self, sizer) def get_config(self, dgroup=None): """get processing configuration for a group""" if dgroup is None: dgroup = self.controller.get_group() conf = getattr(dgroup, 'prepeak_config', {}) if 'e0' not in conf: conf = dict(e0 = dgroup.e0, elo=-10, ehi=-5, emin=-40, emax=0, yarray='norm') dgroup.prepeak_config = conf if not hasattr(dgroup, 'prepeaks'): dgroup.prepeaks = Group() return conf def fill_form(self, dat): if isinstance(dat, Group): self.wids['ppeak_e0'].SetValue(dat.e0) if hasattr(dat, 'prepeaks'): self.wids['ppeak_emin'].SetValue(dat.prepeaks.emin) self.wids['ppeak_emax'].SetValue(dat.prepeaks.emax) self.wids['ppeak_elo'].SetValue(dat.prepeaks.elo) self.wids['ppeak_ehi'].SetValue(dat.prepeaks.ehi) elif instance(dat, dict): self.wids['ppeak_e0'].SetValue(dat['e0']) self.wids['ppeak_emin'].SetValue(dat['emin']) self.wids['ppeak_emax'].SetValue(dat['emax']) self.wids['ppeak_elo'].SetValue(dat['elo']) self.wids['ppeak_ehi'].SetValue(dat['ehi']) self.array_choice.SetStringSelection(dat['array_desc']) self.show_e0.Enable(dat['show_e0']) self.show_centroid.Enable(dat['show_centroid']) self.show_fitrange.Enable(dat['show_fitrange']) self.show_peakrange.Enable(dat['show_peakrange']) self.plot_sub_bline.Enable(dat['plot_sub_bline']) def read_form(self): "read for, returning dict of values" dgroup = self.controller.get_group() array_desc = self.array_choice.GetStringSelection() form_opts = {'gname': dgroup.groupname, 'array_desc': array_desc.lower(), 'array_name': Array_Choices[array_desc], 'baseline_form': 'lorentzian'} form_opts['e0'] = self.wids['ppeak_e0'].GetValue() form_opts['emin'] = self.wids['ppeak_emin'].GetValue() form_opts['emax'] = self.wids['ppeak_emax'].GetValue() form_opts['elo'] = self.wids['ppeak_elo'].GetValue() form_opts['ehi'] = self.wids['ppeak_ehi'].GetValue() form_opts['plot_sub_bline'] = self.plot_sub_bline.IsChecked() form_opts['show_centroid'] = self.show_centroid.IsChecked() form_opts['show_peakrange'] = self.show_peakrange.IsChecked() form_opts['show_fitrange'] = self.show_fitrange.IsChecked() form_opts['show_e0'] = self.show_e0.IsChecked() return form_opts def onFitBaseline(self, evt=None): opts = self.read_form() cmd = """{gname:s}.ydat = 1.0*{gname:s}.{array_name:s} pre_edge_baseline(energy={gname:s}.energy, norm={gname:s}.ydat, group={gname:s}, form='{baseline_form:s}', with_line=True, elo={elo:.3f}, ehi={ehi:.3f}, emin={emin:.3f}, emax={emax:.3f}) """ self.larch_eval(cmd.format(**opts)) dgroup = self.controller.get_group() ppeaks = dgroup.prepeaks dgroup.centroid_msg = "%.4f +/- %.4f eV" % (ppeaks.centroid, ppeaks.delta_centroid) self.msg_centroid.SetLabel(dgroup.centroid_msg) if 'loren_' not in self.fit_components: self.addModel(model='Lorentzian', prefix='loren_', isbkg=True) if 'line_' not in self.fit_components: self.addModel(model='Linear', prefix='line_', isbkg=True) for prefix in ('loren_', 'line_'): cmp = self.fit_components[prefix] # cmp.bkgbox.SetValue(1) self.fill_model_params(prefix, dgroup.prepeaks.fit_details.params) self.fill_form(dgroup) self.fitmodel_btn.Enable() # self.fitallmodel_btn.Enable() i1, i2 = self.get_xranges(dgroup.energy) dgroup.yfit = dgroup.xfit = 0.0*dgroup.energy[i1:i2] self.plot_choice.SetStringSelection(PLOT_BASELINE) self.onPlot() def fill_model_params(self, prefix, params): comp = self.fit_components[prefix] parwids = comp.parwids for pname, par in params.items(): pname = prefix + pname if pname in parwids: wids = parwids[pname] if wids.minval is not None: wids.minval.SetValue(par.min) if wids.maxval is not None: wids.maxval.SetValue(par.max) wids.value.SetValue(par.value) varstr = 'vary' if par.vary else 'fix' if par.expr is not None: varstr = 'constrain' if wids.vary is not None: wids.vary.SetStringSelection(varstr) def onPlot(self, evt=None): plot_choice = self.plot_choice.GetStringSelection() opts = self.read_form() dgroup = self.controller.get_group() ppeaks = getattr(dgroup, 'prepeaks', None) if ppeaks is None: return i1, i2 = self.get_xranges(dgroup.xdat) # i2 = len(ppeaks.baseline) + i1 if len(dgroup.yfit) > len(ppeaks.baseline): i2 = i1 + len(ppeaks.baseline) # print(" Indexes: ", i1, i2, i2-i1, len(dgroup.yfit), len(ppeaks.baseline)) xdat = 1.0*dgroup.energy ydat = 1.0*dgroup.ydat yfit = 1.0*dgroup.ydat baseline = 1.0*dgroup.ydat yfit[i1:i2] = dgroup.yfit[:i2-i1] baseline[i1:i2] = ppeaks.baseline[:i2-i1] if opts['plot_sub_bline']: ydat = ydat - baseline if plot_choice in (PLOT_FIT, PLOT_RESID): yfit = yfit - baseline if plot_choice == PLOT_RESID: resid = ydat - yfit _xs = dgroup.energy[i1:i2] xrange = max(_xs) - min(_xs) pxmin = min(_xs) - 0.05 * xrange pxmax = max(_xs) + 0.05 * xrange jmin = index_of(dgroup.energy, pxmin) jmax = index_of(dgroup.energy, pxmax) + 1 _ys = ydat[jmin:jmax] yrange = max(_ys) - min(_ys) pymin = min(_ys) - 0.05 * yrange pymax = max(_ys) + 0.05 * yrange title = ' pre-edge fit' if plot_choice == PLOT_BASELINE: title = ' pre-edge baseline' if opts['plot_sub_bline']: title = ' pre-edge peaks' array_desc = self.array_choice.GetStringSelection() plotopts = {'xmin': pxmin, 'xmax': pxmax, 'ymin': pymin, 'ymax': pymax, 'title': '%s: %s' % (opts['gname'], title), 'xlabel': 'Energy (eV)', 'ylabel': '%s $\mu$' % opts['array_desc'], 'label': '%s $\mu$' % opts['array_desc'], 'delay_draw': True, 'show_legend': True} plot_extras = [] if opts['show_fitrange']: popts = {'color': '#DDDDCC'} emin = opts['emin'] emax = opts['emax'] imin = index_of(dgroup.energy, emin) imax = index_of(dgroup.energy, emax) plot_extras.append(('vline', emin, None, popts)) plot_extras.append(('vline', emax, None, popts)) if opts['show_peakrange']: popts = {'marker': '+', 'markersize': 6} elo = opts['elo'] ehi = opts['ehi'] ilo = index_of(dgroup.xdat, elo) ihi = index_of(dgroup.xdat, ehi) plot_extras.append(('marker', elo, ydat[ilo], popts)) plot_extras.append(('marker', ehi, ydat[ihi], popts)) if opts['show_centroid']: popts = {'color': '#EECCCC'} ecen = getattr(dgroup.prepeaks, 'centroid', -1) if ecen > min(dgroup.energy): plot_extras.append(('vline', ecen, None, popts)) pframe = self.controller.get_display(win=2, stacked=(plot_choice==PLOT_RESID)) ppanel = pframe.panel axes = ppanel.axes plotopts.update(PLOTOPTS_1) ppanel.plot(xdat, ydat, **plotopts) if plot_choice == PLOT_BASELINE: if not opts['plot_sub_bline']: ppanel.oplot(dgroup.prepeaks.energy, dgroup.prepeaks.baseline, label='baseline', **PLOTOPTS_2) elif plot_choice in (PLOT_FIT, PLOT_RESID): ppanel.oplot(dgroup.energy, yfit, label='fit', **PLOTOPTS_1) if hasattr(dgroup, 'ycomps'): ncomp = len(dgroup.ycomps) icomp = 0 for label, ycomp in dgroup.ycomps.items(): icomp +=1 fcomp = self.fit_components[label] # print("ycomp: ", plot_choice, label, len(ycomp), len(dgroup.xfit), # fcomp.bkgbox.IsChecked(), opts['plot_sub_bline'], icomp, ncomp) if not (fcomp.bkgbox.IsChecked() and opts['plot_sub_bline']): ppanel.oplot(dgroup.xfit, ycomp, label=label, delay_draw=(icomp!=ncomp), style='short dashed') if plot_choice == PLOT_RESID: _ys = resid yrange = max(_ys) - min(_ys) plotopts['ymin'] = min(_ys) - 0.05 * yrange plotopts['ymax'] = max(_ys) + 0.05 * yrange plotopts['delay_draw'] = False plotopts['ylabel'] = 'data-fit' plotopts['label'] = '_nolegend_' pframe.plot(dgroup.energy, resid, panel='bot', **plotopts) pframe.Show() # print(" RESIDUAL PLOT margins: ") # print(" top : ", pframe.panel.conf.margins) # print(" bot : ", pframe.panel_bot.conf.margins) 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', 'label': '_nolegend_'} popts.update(opts) axes.axvline(x, **popts) ppanel.canvas.draw() def onNBChanged(self, event=None): idx = self.mod_nb.GetSelection() def addModel(self, event=None, model=None, prefix=None, isbkg=False): if model is None and event is not None: model = event.GetString() if model is None or model.startswith('<'): return if prefix is None: p = model[:5].lower() curmodels = ["%s%i_" % (p, i+1) for i in range(1+len(self.fit_components))] for comp in self.fit_components: if comp in curmodels: curmodels.remove(comp) prefix = curmodels[0] label = "%s(prefix='%s')" % (model, prefix) title = "%s: %s " % (prefix[:-1], model) title = prefix[:-1] mclass_kws = {'prefix': prefix} if 'step' in model.lower(): form = model.lower().replace('step', '').strip() if form.startswith('err'): form = 'erf' label = "Step(form='%s', prefix='%s')" % (form, prefix) title = "%s: Step %s" % (prefix[:-1], form[:3]) mclass = lm_models.StepModel mclass_kws['form'] = form minst = mclass(form=form, prefix=prefix) else: if model in ModelFuncs: mclass = getattr(lm_models, ModelFuncs[model]) else: mclass = getattr(lm_models, model+'Model') minst = mclass(prefix=prefix) panel = GridPanel(self.mod_nb, ncols=2, nrows=5, pad=2, itemstyle=CEN) def SLabel(label, size=(80, -1), **kws): return SimpleText(panel, label, size=size, style=wx.ALIGN_LEFT, **kws) usebox = Check(panel, default=True, label='Use in Fit?', size=(100, -1)) bkgbox = Check(panel, default=False, label='Is Baseline?', size=(125, -1)) if isbkg: bkgbox.SetValue(1) delbtn = Button(panel, 'Delete Component', size=(125, -1), action=partial(self.onDeleteComponent, prefix=prefix)) pick2msg = SimpleText(panel, " ", size=(125, -1)) pick2btn = Button(panel, 'Pick Values from Data', size=(150, -1), action=partial(self.onPick2Points, prefix=prefix)) # SetTip(mname, 'Label for the model component') SetTip(usebox, 'Use this component in fit?') SetTip(bkgbox, 'Label this component as "background" when plotting?') SetTip(delbtn, 'Delete this model component') SetTip(pick2btn, 'Select X range on Plot to Guess Initial Values') panel.Add(SLabel(label, size=(275, -1), colour='#0000AA'), dcol=3, style=wx.ALIGN_LEFT, newrow=True) panel.Add(usebox, dcol=1) panel.Add(bkgbox, dcol=2, style=LCEN) panel.Add(delbtn, dcol=1, style=wx.ALIGN_LEFT) panel.Add(pick2btn, dcol=2, style=wx.ALIGN_LEFT, newrow=True) panel.Add(pick2msg, dcol=2, style=wx.ALIGN_RIGHT) # panel.Add((10, 10), newrow=True) # panel.Add(HLine(panel, size=(150, 3)), dcol=4, style=wx.ALIGN_CENTER) panel.Add(SLabel("Parameter "), style=wx.ALIGN_LEFT, newrow=True) panel.AddMany((SLabel(" Value"), SLabel(" Type"), SLabel(' Bounds'), SLabel(" Min", size=(60, -1)), SLabel(" Max", size=(60, -1)), SLabel(" Expression"))) parwids = OrderedDict() parnames = sorted(minst.param_names) for a in minst._func_allargs: pname = "%s%s" % (prefix, a) if (pname not in parnames and a in minst.param_hints and a not in minst.independent_vars): parnames.append(pname) for pname in parnames: sname = pname[len(prefix):] hints = minst.param_hints.get(sname, {}) par = Parameter(name=pname, value=0, vary=True) if 'min' in hints: par.min = hints['min'] if 'max' in hints: par.max = hints['max'] if 'value' in hints: par.value = hints['value'] if 'expr' in hints: par.expr = hints['expr'] pwids = ParameterWidgets(panel, par, name_size=100, expr_size=125, float_size=80, prefix=prefix, widgets=('name', 'value', 'minval', 'maxval', 'vary', 'expr')) parwids[par.name] = pwids panel.Add(pwids.name, newrow=True) panel.AddMany((pwids.value, pwids.vary, pwids.bounds, pwids.minval, pwids.maxval, pwids.expr)) for sname, hint in minst.param_hints.items(): pname = "%s%s" % (prefix, sname) if 'expr' in hint and pname not in parnames: par = Parameter(name=pname, value=0, expr=hint['expr']) pwids = ParameterWidgets(panel, par, name_size=100, expr_size=225, float_size=80, prefix=prefix, widgets=('name', 'value', 'expr')) parwids[par.name] = pwids panel.Add(pwids.name, newrow=True) panel.Add(pwids.value) panel.Add(pwids.expr, dcol=4, style=wx.ALIGN_RIGHT) pwids.value.Disable() fgroup = Group(prefix=prefix, title=title, mclass=mclass, mclass_kws=mclass_kws, usebox=usebox, panel=panel, parwids=parwids, float_size=65, expr_size=150, pick2_msg=pick2msg, bkgbox=bkgbox) self.fit_components[prefix] = fgroup panel.pack() self.mod_nb.AddPage(panel, title, True) sx,sy = self.GetSize() self.SetSize((sx, sy+1)) self.SetSize((sx, sy)) def onDeleteComponent(self, evt=None, prefix=None): fgroup = self.fit_components.get(prefix, None) if fgroup is None: return for i in range(self.mod_nb.GetPageCount()): if fgroup.title == self.mod_nb.GetPageText(i): self.mod_nb.DeletePage(i) for attr in dir(fgroup): setattr(fgroup, attr, None) self.fit_components.pop(prefix) # sx,sy = self.GetSize() # self.SetSize((sx, sy+1)) # self.SetSize((sx, sy)) def onPick2EraseTimer(self, evt=None): """erases line trace showing automated 'Pick 2' guess """ self.pick2erase_timer.Stop() panel = self.pick2erase_panel ntrace = panel.conf.ntrace - 1 trace = panel.conf.get_mpl_line(ntrace) panel.conf.get_mpl_line(ntrace).set_data(np.array([]), np.array([])) panel.conf.ntrace = ntrace panel.draw() def onPick2Timer(self, evt=None): """checks for 'Pick 2' events, and initiates 'Pick 2' guess for a model from the selected data range """ try: plotframe = self.controller.get_display() curhist = plotframe.cursor_hist[:] plotframe.Raise() except: return if (time.time() - self.pick2_t0) > self.pick2_timeout: msg = self.pick2_group.pick2_msg.SetLabel(" ") plotframe.cursor_hist = [] self.pick2_timer.Stop() return if len(curhist) < 2: self.pick2_group.pick2_msg.SetLabel("%i/2" % (len(curhist))) return self.pick2_group.pick2_msg.SetLabel("done.") self.pick2_timer.Stop() # guess param values xcur = (curhist[0][0], curhist[1][0]) xmin, xmax = min(xcur), max(xcur) dgroup = getattr(self.larch.symtable, self.controller.groupname) x, y = dgroup.xdat, dgroup.ydat i0 = index_of(dgroup.xdat, xmin) i1 = index_of(dgroup.xdat, xmax) x, y = dgroup.xdat[i0:i1+1], dgroup.ydat[i0:i1+1] mod = self.pick2_group.mclass(prefix=self.pick2_group.prefix) parwids = self.pick2_group.parwids try: guesses = mod.guess(y, x=x) except: return for name, param in guesses.items(): if name in parwids: parwids[name].value.SetValue(param.value) dgroup._tmp = mod.eval(guesses, x=dgroup.xdat) plotframe = self.controller.get_display() plotframe.cursor_hist = [] plotframe.oplot(dgroup.xdat, dgroup._tmp) self.pick2erase_panel = plotframe.panel self.pick2erase_timer.Start(5000) def onPick2Points(self, evt=None, prefix=None): fgroup = self.fit_components.get(prefix, None) if fgroup is None: return plotframe = self.controller.get_display() plotframe.Raise() plotframe.cursor_hist = [] fgroup.npts = 0 self.pick2_group = fgroup if fgroup.pick2_msg is not None: fgroup.pick2_msg.SetLabel("0/2") self.pick2_t0 = time.time() self.pick2_timer.Start(250) def onSaveFitResult(self, event=None): dgroup = self.controller.get_group() deffile = dgroup.filename.replace('.', '_') + '.modl' outfile = FileSave(self, 'Save Fit Result', default_file=deffile, wildcard=ModelWcards) if outfile is not None: try: self.save_fit_result(dgroup.fit_history[-1], outfile) except IOError: print('could not write %s' % outfile) def onLoadFitResult(self, event=None): mfile = FileOpen(self, 'Load Fit Result', default_file='', wildcard=ModelWcards) if mfile is not None: self.load_modelresult(mfile) def save_fit_result(self, fitresult, outfile): """saves a customized ModelResult""" save_modelresult(fitresult, outfile) def load_modelresult(self, inpfile): """read a customized ModelResult""" result = load_modelresult(inpfile) for prefix in list(self.fit_components.keys()): self.onDeleteComponent(self, prefix=prefix) for comp in result.model.components: isbkg = comp.prefix in result.user_options['bkg_components'] self.addModel(model=comp.func.__name__, prefix=comp.prefix, isbkg=isbkg) for comp in result.model.components: parwids = self.fit_components[comp.prefix].parwids for pname, par in result.params.items(): if pname in parwids: wids = parwids[pname] if wids.minval is not None: wids.minval.SetValue(par.min) if wids.maxval is not None: wids.maxval.SetValue(par.max) val = result.init_values.get(pname, par.value) wids.value.SetValue(val) self.fill_form(result.user_options) return result def onExportFitResult(self, event=None): dgroup = self.controller.get_group() deffile = dgroup.filename.replace('.', '_') + '_result.xdi' wcards = 'All files (*.*)|*.*' outfile = FileSave(self, 'Export Fit Result', default_file=deffile, wildcard=wcards) if outfile is not None: i1, i2 = self.get_xranges(dgroup.xdat) x = dgroup.xdat[i1:i2] y = dgroup.ydat[i1:i2] yerr = None if hasattr(dgroup, 'yerr'): yerr = 1.0*dgroup.yerr if not isinstance(yerr, np.ndarray): yerr = yerr * np.ones(len(y)) else: yerr = yerr[i1:i2] export_modelresult(dgroup.fit_history[-1], filename=outfile, datafile=dgroup.filename, ydata=y, yerr=yerr, x=x) def onSelPoint(self, evt=None, opt='__', relative_e0=False, win=None): """ get last selected point from a specified plot window and fill in the value for the widget defined by `opt`. by default it finds the latest cursor position from the cursor history of the first 20 plot windows. """ if opt not in self.wids: return None _x, _y = last_cursor_pos(win=win, _larch=self.larch) if _x is not None: if relative_e0 and 'e0' in self.wids: _x -= self.wids['e0'].GetValue() self.wids[opt].SetValue(_x) def get_xranges(self, x): opts = self.read_form() dgroup = self.controller.get_group() en_eps = min(np.diff(dgroup.energy)) / 5. i1 = index_of(x, opts['emin'] + en_eps) i2 = index_of(x, opts['emax'] + en_eps) + 1 return i1, i2 def build_fitmodel(self): """ use fit components to build model""" dgroup = self.controller.get_group() fullmodel = None params = Parameters() self.summary = {'components': [], 'options': {}} peaks = [] for comp in self.fit_components.values(): _cen, _amp = None, None if comp.usebox is not None and comp.usebox.IsChecked(): for parwids in comp.parwids.values(): params.add(parwids.param) #print(" add param ", parwids.param) if parwids.param.name.endswith('_center'): _cen = parwids.param.name elif parwids.param.name.endswith('_amplitude'): _amp = parwids.param.name self.summary['components'].append((comp.mclass.__name__, comp.mclass_kws)) thismodel = comp.mclass(**comp.mclass_kws) if fullmodel is None: fullmodel = thismodel else: fullmodel += thismodel if not comp.bkgbox.IsChecked() and _cen is not None and _amp is not None: peaks.append((_amp, _cen)) if len(peaks) > 0: denom = '+'.join([p[0] for p in peaks]) numer = '+'.join(["%s*%s "% p for p in peaks]) params.add('fit_centroid', expr="(%s)/(%s)" %(numer, denom)) self.fit_model = fullmodel self.fit_params = params if dgroup is not None: i1, i2 = self.get_xranges(dgroup.xdat) xsel = dgroup.xdat[i1:i2] dgroup.xfit = xsel dgroup.yfit = self.fit_model.eval(self.fit_params, x=xsel) dgroup.ycomps = self.fit_model.eval_components(params=self.fit_params, x=xsel) return dgroup def onFitSelected(self, event=None): dgroup = self.build_fitmodel() opts = self.read_form() print("fitting selected groups in progress") def onFitModel(self, event=None): dgroup = self.build_fitmodel() opts = self.read_form() i1, i2 = self.get_xranges(dgroup.xdat) dgroup.xfit = dgroup.xdat[i1:i2] ysel = dgroup.ydat[i1:i2] # print('onFit Model : xrange ', i1, i2, len(dgroup.xfit), len(dgroup.yfit)) weights = np.ones(len(ysel)) if hasattr(dgroup, 'yerr'): yerr = 1.0*dgroup.yerr if not isinstance(yerr, np.ndarray): yerr = yerr * np.ones(len(ysel)) else: yerr = yerr[i1:i2] yerr_min = 1.e-9*ysel.mean() yerr[np.where(yerr < yerr_min)] = yerr_min weights = 1.0/yerr result = self.fit_model.fit(ysel, params=self.fit_params, x=dgroup.xfit, weights=weights, method='leastsq') self.summary['xmin'] = dgroup.xdat[i1] self.summary['xmax'] = dgroup.xdat[i2] for attr in ('aic', 'bic', 'chisqr', 'redchi', 'ci_out', 'covar', 'flatchain', 'success', 'nan_policy', 'nfev', 'ndata', 'nfree', 'nvarys', 'init_values'): self.summary[attr] = getattr(result, attr) self.summary['params'] = result.params dgroup.yfit = result.best_fit dgroup.ycomps = self.fit_model.eval_components(params=result.params, x=dgroup.xfit) result.model_repr = self.fit_model._reprstring(long=True) ## hacks to save user options result.user_options = opts bkg_comps = [] for label, comp in self.fit_components.items(): if comp.bkgbox.IsChecked(): bkg_comps.append(label) result.user_options['bkg_components'] = bkg_comps self.autosave_modelresult(result) if not hasattr(dgroup, 'fit_history'): dgroup.fit_history = [] dgroup.fit_history.append(result) self.plot_choice.SetStringSelection(PLOT_FIT) self.onPlot() self.parent.show_subframe('prepeak_result_frame', FitResultFrame, datagroup=dgroup, peakframe=self) self.parent.subframes['prepeak_result_frame'].show_fitresult() [m.Enable(True) for m in self.parent.afterfit_menus] def update_start_values(self, params): """fill parameters with best fit values""" allparwids = {} for comp in self.fit_components.values(): if comp.usebox is not None and comp.usebox.IsChecked(): for name, parwids in comp.parwids.items(): allparwids[name] = parwids for pname, par in params.items(): if pname in allparwids: allparwids[pname].value.SetValue(par.value) def autosave_modelresult(self, result, fname=None): """autosave model result to user larch folder""" xasguidir = os.path.join(site_config.usr_larchdir, 'xasgui') if not os.path.exists(xasguidir): try: os.makedirs(xasguidir) except OSError: print("Warning: cannot create XAS GUI user folder") return if not HAS_MODELSAVE: print("Warning: cannot save model results: upgrade lmfit") return if fname is None: fname = 'autosave.fitresult' fname = os.path.join(xasguidir, fname) self.save_fit_result(result, fname)
def build_display(self): panel = self.panel wids = self.wids self.skip_process = True wids['fitspace'] = Choice(panel, choices=FitSpace_Choices, size=(175, -1)) wids['fitspace'].SetStringSelection(norm) wids['plotchoice'] = Choice(panel, choices=Plot_Choices, size=(175, -1), action=self.onPlot) wids['plotchoice'].SetSelection(0) add_text = self.add_text opts = dict(digits=2, increment=1.0) w_xmin = self.add_floatspin('xmin', value=defaults['xmin'], **opts) w_xmax = self.add_floatspin('xmax', value=defaults['xmax'], **opts) w_wmin = self.add_floatspin('weight_min', digits=4, value=defaults['weight_min'], increment=0.001, with_pin=False, min_val=0, max_val=0.5, action=self.onSet_WeightMin) autoset_fs_increment(self.wids['weight_min'], defaults['weight_min']) self.wids['weight_auto'] = Check(panel, default=True, label='auto?') w_mcomps = self.add_floatspin('max_components', digits=0, value=defaults['max_components'], increment=1, with_pin=False, min_val=0) b_build_model = Button(panel, 'Build Model With Selected Groups', size=(275, -1), action=self.onBuildPCAModel) wids['fit_group'] = Button(panel, 'Test Current Group with Model', size=(225, -1), action=self.onFitGroup) wids['save_model'] = Button(panel, 'Save PCA Model', size=(150, -1), action=self.onSavePCAModel) wids['load_model'] = Button(panel, 'Load PCA Model', size=(150, -1), action=self.onLoadPCAModel) wids['fit_group'].Disable() wids['load_model'].Disable() wids['save_model'].Disable() collabels = [ ' Variance ', ' IND value ', ' IND / IND_Best', ' Factor Weight' ] colsizes = [100, 100, 100, 200] coltypes = ['float:12,6', 'float:12,6', 'float:12,5', 'string'] coldefs = [0.0, 0.0, 1.0, '0.0'] wids['table'] = DataTableGrid(panel, nrows=MAX_ROWS, collabels=collabels, datatypes=coltypes, defaults=coldefs, colsizes=colsizes, rowlabelsize=60) wids['table'].SetMinSize((625, 175)) wids['table'].EnableEditing(False) # # sview = self.wids['stats'] = dv.DataViewListCtrl(panel, style=DVSTYLE) # sview.AppendTextColumn(' Component', width=75) # sview.AppendTextColumn(' Weight', width=100) # sview.AppendTextColumn(' Significant?', width=75) # # for col in range(sview.ColumnCount): # this = sview.Columns[col] # align = wx.ALIGN_LEFT if col == 0 else wx.ALIGN_RIGHT # this.Sortable = False # this.Alignment = this.Renderer.Alignment = align # sview.SetMinSize((275, 250)) wids['status'] = SimpleText(panel, ' ') rfont = self.GetFont() rfont.SetPointSize(rfont.GetPointSize() + 1) wids['fit_chi2'] = SimpleText(panel, '0.000', font=rfont) wids['fit_dscale'] = SimpleText(panel, '1.000', font=rfont) panel.Add(SimpleText(panel, ' Principal Component Analysis', **self.titleopts), dcol=4) add_text('Array to Use: ', newrow=True) panel.Add(wids['fitspace'], dcol=2) panel.Add(wids['load_model'], dcol=2) add_text('Plot : ', newrow=True) panel.Add(wids['plotchoice'], dcol=2) panel.Add(wids['save_model'], dcol=2) add_text('Fit Energy Range: ') panel.Add(w_xmin) add_text(' : ', newrow=False) panel.Add(w_xmax) #panel.Add(wids['show_fitrange']) add_text('Min Weight: ') panel.Add(w_wmin) panel.Add(wids['weight_auto']) add_text('Max Components:', dcol=1, newrow=True) panel.Add(w_mcomps) panel.Add(Button(panel, 'Copy To Selected Groups', size=(200, -1), action=partial(self.onCopyParam, 'pca')), dcol=2) add_text('Status: ') panel.Add(wids['status'], dcol=3) panel.Add(HLine(panel, size=(550, 2)), dcol=5, newrow=True) panel.Add(b_build_model, dcol=5, newrow=True) panel.Add(wids['table'], dcol=5, newrow=True) panel.Add(wids['fit_group'], dcol=3, newrow=True) add_text('chi-square: ') panel.Add(wids['fit_chi2']) add_text('scale factor: ') panel.Add(wids['fit_dscale']) # # ## add weights report: slightly tricky layout # ## working with GridBagSizer under gridpanel... # icol = panel.icol - 2 # irow = panel.irow # pstyle, ppad = panel.itemstyle, panel.pad # # panel.sizer.Add(SimpleText(panel, 'data scalefactor = '), # (irow+1, icol), (1, 1), pstyle, ppad) # panel.sizer.Add(wids['fit_dscale'], # (irow+1, icol+1), (1, 1), pstyle, ppad) # irow +=1 # for i in range(1, NWTS+1): # wids['fit_wt%d' % i] = SimpleText(panel, '--', font=rfont) # panel.sizer.Add(SimpleText(panel, 'weight_%d ='%i, font=rfont), # (irow+i, icol), (1, 1), pstyle, ppad) # panel.sizer.Add(wids['fit_wt%d'%i], # (irow+i, icol+1), (1, 1), pstyle, ppad) # panel.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((10, 10), 0, LCEN, 3) sizer.Add(panel, 1, LCEN, 3) pack(self, sizer) self.skip_process = False
def build_display(self): panel = self.panel wids = self.wids self.skip_process = True wids['plotone_op'] = Choice(panel, choices=PlotOne_Choices, action=self.onPlotOne, size=(175, -1)) wids['plotalt_op'] = Choice(panel, choices=PlotAlt_Choices, action=self.onPlotOne, size=(175, -1)) wids['plotsel_op'] = Choice(panel, choices=PlotSel_Choices, action=self.onPlotSel, size=(175, -1)) wids['plotone_op'].SetStringSelection(chik) wids['plotsel_op'].SetStringSelection(chik) wids['plotalt_op'].SetStringSelection(noplot) plot_one = Button(panel, 'Plot This Group', size=(175, -1), action=self.onPlotOne) plot_sel = Button(panel, 'Plot Selected Groups', size=(175, -1), action=self.onPlotSel) saveconf = Button(panel, 'Save as Default Settings', size=(200, -1), action=self.onSaveConfigBtn) def xxxFSWithPinPanel(name, value, **kws): s = wx.BoxSizer(wx.HORIZONTAL) self.wids[name] = FloatSpin(panel, value=value, **kws) bb = BitmapButton(panel, get_icon('pin'), size=(25, 25), action=partial(self.onSelPoint, opt=name), tooltip='use last point selected from plot') s.Add(self.wids[name]) s.Add(bb) return s wids['plot_voffset'] = FloatSpin(panel, value=0, digits=2, increment=0.25, action=self.onProcess) wids['plot_kweight'] = FloatSpin(panel, value=2, digits=1, increment=1, action=self.onProcess, min_val=0, max_val=5) wids['plot_kweight_alt'] = FloatSpin(panel, value=2, digits=1, increment=1, action=self.onProcess, min_val=0, max_val=5) opts = dict(digits=2, increment=0.1, min_val=0, action=self.onProcess) wids['e0'] = FloatSpin(panel, **opts) opts['max_val'] = 5 wids['rbkg'] = FloatSpin(panel, value=1.0, **opts) opts['max_val'] = 125 bkg_kmin = self.add_floatspin('bkg_kmin', value=0, with_pin=True, **opts) bkg_kmax = self.add_floatspin('bkg_kmax', value=20, with_pin=True, **opts) fft_kmin = self.add_floatspin('fft_kmin', value=0, with_pin=True, **opts) fft_kmax = self.add_floatspin('fft_kmax', value=20, with_pin=True, **opts) wids['fft_dk'] = FloatSpin(panel, value=3, **opts) opts.update({'increment': 1, 'digits': 1, 'max_val': 5}) wids['bkg_kweight'] = FloatSpin(panel, value=1, **opts) wids['fft_kweight'] = FloatSpin(panel, value=1, **opts) opts = dict(choices=CLAMPLIST, size=(80, -1), action=self.onProcess) wids['bkg_clamplo'] = Choice(panel, **opts) wids['bkg_clamphi'] = Choice(panel, **opts) wids['fft_kwindow'] = Choice(panel, choices=list(FTWINDOWS), action=self.onProcess, size=(150, -1)) self.wids['is_frozen'] = Check(panel, default=False, label='Freeze Group', action=self.onFreezeGroup) def add_text(text, dcol=1, newrow=True): panel.Add(SimpleText(panel, text), dcol=dcol, newrow=newrow) def CopyBtn(name): return Button(panel, 'Copy', size=(60, -1), action=partial(self.onCopyParam, name)) panel.Add(SimpleText(panel, ' EXAFS Processing', **self.titleopts), dcol=5) panel.Add(plot_sel, newrow=True) panel.Add(self.wids['plotsel_op'], dcol=2) add_text('Vertical offset: ', newrow=False) panel.Add(wids['plot_voffset'], dcol=2) panel.Add(plot_one, newrow=True) panel.Add(self.wids['plotone_op'], dcol=2) add_text('Plot k weight: ', newrow=False) panel.Add(wids['plot_kweight']) add_text('Add Second Plot: ', newrow=True) panel.Add(self.wids['plotalt_op'], dcol=2) add_text('Plot2 k weight: ', newrow=False) panel.Add(wids['plot_kweight_alt']) panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True) panel.Add(SimpleText(panel, ' Background subtraction', size=(180, -1), **self.titleopts), dcol=2, style=LEFT, newrow=True) panel.Add(SimpleText(panel, 'Copy To Selected Groups:'), style=RIGHT, dcol=3) add_text('E0: ') panel.Add(wids['e0']) panel.Add((10, 10), dcol=2) panel.Add(CopyBtn('e0'), style=RIGHT) add_text('R bkg: ') panel.Add(wids['rbkg']) panel.Add((10, 10), dcol=2) panel.Add(CopyBtn('rbkg'), style=RIGHT) add_text('k min: ') panel.Add(bkg_kmin) panel.Add(SimpleText(panel, 'k max:', size=(75, -1)), style=LEFT) panel.Add(bkg_kmax) panel.Add(CopyBtn('bkg_krange'), style=RIGHT) add_text('kweight: ', newrow=True) panel.Add(wids['bkg_kweight']) panel.Add((10, 10), dcol=2) panel.Add(CopyBtn('bkg_kweight'), style=RIGHT) add_text('Clamps Low E: ', newrow=True) panel.Add(wids['bkg_clamplo']) add_text('high E: ', newrow=False) panel.Add(wids['bkg_clamphi']) panel.Add(CopyBtn('bkg_clamp'), style=RIGHT) panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True) panel.Add(SimpleText(panel, ' Fourier transform ', size=(180, -1), **self.titleopts), dcol=2, style=LEFT, newrow=True) panel.Add(SimpleText(panel, 'Copy To Selected Groups:'), style=RIGHT, dcol=3) panel.Add(SimpleText(panel, 'k min: '), newrow=True) panel.Add(fft_kmin) panel.Add(SimpleText(panel, 'k max:', size=(75, -1)), style=LEFT) panel.Add(fft_kmax) panel.Add(CopyBtn('fft_krange'), style=RIGHT) panel.Add(SimpleText(panel, 'k weight : '), newrow=True) panel.Add(wids['fft_kweight']) panel.Add((10, 10), dcol=2) panel.Add(CopyBtn('fft_kweight'), style=RIGHT) panel.Add(SimpleText(panel, 'K window : '), newrow=True) panel.Add(wids['fft_kwindow']) panel.Add(SimpleText(panel, ' dk : ')) panel.Add(wids['fft_dk']) panel.Add(CopyBtn('fft_kwindow'), style=RIGHT) panel.Add((10, 10), newrow=True) panel.Add(self.wids['is_frozen'], dcol=1, newrow=True) panel.Add(saveconf, dcol=4) panel.Add((10, 10), newrow=True) panel.Add(HLine(self, size=(500, 3)), dcol=8, newrow=True) panel.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(panel, 1, LEFT, 3) pack(self, sizer) self.skip_process = False
def build_display(self): panel = self.panel wids = self.wids self.skip_process = True wids['fitspace'] = Choice(panel, choices=FitSpace_Choices, size=(175, -1)) wids['fitspace'].SetStringSelection(norm) add_text = self.add_text opts = dict(digits=2, increment=1.0, relative_e0=False) # True) elo_wids = self.add_floatspin('elo', value=defaults['elo'], **opts) ehi_wids = self.add_floatspin('ehi', value=defaults['ehi'], **opts) wids['fit_group'] = Button(panel, 'Fit this Group', size=(175, -1), action=self.onFitOne) wids['fit_selected'] = Button(panel, 'Fit Selected Groups', size=(175, -1), action=self.onFitAll) wids['add_selected'] = Button(panel, 'Use Selected Groups as Components', size=(300, -1), action=self.onUseSelected) wids['saveconf'] = Button(panel, 'Save as Default Settings', size=(225, -1), action=self.onSaveConfigBtn) opts = dict(default=True, size=(75, -1), action=self.onPlotOne) wids['show_fitrange'] = Check(panel, label='show?', **opts) wids['sum_to_one'] = Check(panel, label='Weights Must Sum to 1?', default=True) wids['all_combos'] = Check(panel, label='Fit All Combinations?', default=True) max_ncomps = self.add_floatspin('max_ncomps', value=10, digits=0, increment=1, min_val=0, max_val=20, size=(60, -1), with_pin=False) panel.Add(SimpleText(panel, ' Linear Combination Analysis', **self.titleopts), dcol=4) add_text('Array to Fit: ', newrow=True) panel.Add(wids['fitspace'], dcol=3) add_text('Fit Energy Range: ') panel.Add(elo_wids) add_text(' : ', newrow=False) panel.Add(ehi_wids) panel.Add(wids['show_fitrange']) panel.Add(HLine(panel, size=(625, 3)), dcol=5, newrow=True) add_text('Run Fit: ') panel.Add(wids['fit_group'], dcol=2) panel.Add(wids['fit_selected'], dcol=3) add_text('Fit Options: ') panel.Add(wids['sum_to_one'], dcol=2) panel.Add((10, 10), dcol=1, newrow=True) panel.Add(wids['all_combos'], dcol=2) add_text('Max # Components: ', newrow=False) panel.Add(max_ncomps, dcol=2) panel.Add(HLine(panel, size=(625, 3)), dcol=5, newrow=True) add_text('Components: ') panel.Add(wids['add_selected'], dcol=4) collabels = [' File /Group Name ', 'weight', 'min', 'max'] colsizes = [300, 80, 80, 80] coltypes = ['str', 'float:12,4', 'float:12,4', 'float:12,4'] coldefs = ['', 1.0 / MAX_COMPONENTS, 0.0, 1.0] wids['table'] = DataTableGrid(panel, nrows=MAX_COMPONENTS, collabels=collabels, datatypes=coltypes, defaults=coldefs, colsizes=colsizes) wids['table'].SetMinSize((625, 250)) panel.Add(wids['table'], newrow=True, dcol=6) panel.Add(HLine(panel, size=(625, 3)), dcol=5, newrow=True) panel.Add(wids['saveconf'], dcol=4, newrow=True) panel.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(panel, 1, LEFT, 3) pack(self, sizer) self.skip_process = False
def build_display(self): panel = self.panel wids = self.wids self.skip_process = True wids['fitspace'] = Choice(panel, choices=FitSpace_Choices, size=(250, -1)) wids['fitspace'].SetStringSelection(norm) # wids['plotchoice'] = Choice(panel, choices=Plot_Choices, # size=(250, -1), action=self.onPlot) wids['method'] = Choice(panel, choices=Regress_Choices, size=(250, -1), action=self.onRegressMethod) add_text = self.add_text opts = dict(digits=2, increment=1.0) w_xmin = self.add_floatspin('xmin', value=defaults['xmin'], **opts) w_xmax = self.add_floatspin('xmax', value=defaults['xmax'], **opts) wids['alpha'] = NumericCombo(panel, make_steps(), fmt='%.6g', default_val=0.01, width=100) wids['auto_scale_pls'] = Check(panel, default=True, label='auto scale?') wids['auto_alpha'] = Check(panel, default=False, label='auto alpha?') wids['fit_intercept'] = Check(panel, default=True, label='fit intercept?') wids['save_csv'] = Button(panel, 'Save CSV File', size=(150, -1), action=self.onSaveCSV) wids['load_csv'] = Button(panel, 'Load CSV File', size=(150, -1), action=self.onLoadCSV) wids['save_model'] = Button(panel, 'Save Model', size=(150, -1), action=self.onSaveModel) wids['save_model'].Disable() wids['load_model'] = Button(panel, 'Load Model', size=(150, -1), action=self.onLoadModel) wids['train_model'] = Button(panel, 'Train Model From These Data', size=(275, -1), action=self.onTrainModel) wids['fit_group'] = Button(panel, 'Predict Variable for Selected Groups', size=(275, -1), action=self.onPredictGroups) wids['fit_group'].Disable() w_cvfolds = self.add_floatspin('cv_folds', digits=0, with_pin=False, value=0, increment=1, min_val=-1) w_cvreps = self.add_floatspin('cv_repeats', digits=0, with_pin=False, value=0, increment=1, min_val=-1) w_ncomps = self.add_floatspin('ncomps', digits=0, with_pin=False, value=3, increment=1, min_val=1) wids['varname'] = wx.TextCtrl(panel, -1, 'valence', size=(150, -1)) wids['stat1'] = SimpleText(panel, ' - - - ') wids['stat2'] = SimpleText(panel, ' - - - ') collabels = [' File /Group Name ', 'External Value', 'Predicted Value'] colsizes = [300, 120, 120] coltypes = ['str', 'float:12,4', 'float:12,4'] coldefs = ['', 0.0, 0.0] wids['table'] = DataTableGrid(panel, nrows=MAX_ROWS, collabels=collabels, datatypes=coltypes, defaults=coldefs, colsizes=colsizes) wids['table'].SetMinSize((625, 175)) wids['use_selected'] = Button(panel, 'Use Selected Groups', size=(150, -1), action=self.onFillTable) panel.Add(SimpleText(panel, 'Feature Regression, Model Selection', **self.titleopts), dcol=4) add_text('Array to Use: ', newrow=True) panel.Add(wids['fitspace'], dcol=4) # add_text('Plot : ', newrow=True) # panel.Add(wids['plotchoice'], dcol=3) add_text('Fit Energy Range: ') panel.Add(w_xmin) add_text(' : ', newrow=False) panel.Add(w_xmax, dcol=3) add_text('Regression Method:') panel.Add(wids['method'], dcol=4) add_text('PLS # components: ') panel.Add(w_ncomps) panel.Add(wids['auto_scale_pls'], dcol=2) add_text('Lasso Alpha: ') panel.Add(wids['alpha']) panel.Add(wids['auto_alpha'], dcol=2) panel.Add(wids['fit_intercept']) wids['alpha'].Disable() wids['auto_alpha'].Disable() wids['fit_intercept'].Disable() add_text('Cross Validation: ') add_text(' # folds, # repeats: ', newrow=False) panel.Add(w_cvfolds, dcol=2) panel.Add(w_cvreps) panel.Add(HLine(panel, size=(600, 2)), dcol=6, newrow=True) add_text('Build Model: ', newrow=True) panel.Add(wids['use_selected'], dcol=2) add_text('Attribute Name: ', newrow=False) panel.Add(wids['varname'], dcol=4) add_text('Read/Save Data: ', newrow=True) panel.Add(wids['load_csv'], dcol=3) panel.Add(wids['save_csv'], dcol=2) panel.Add(wids['table'], newrow=True, dcol=5) # , drow=3) panel.Add(HLine(panel, size=(550, 2)), dcol=5, newrow=True) panel.Add((5, 5), newrow=True) add_text('Train Model : ') panel.Add(wids['train_model'], dcol=3) panel.Add(wids['load_model']) add_text('Use This Model : ') panel.Add(wids['fit_group'], dcol=3) panel.Add(wids['save_model']) add_text('Fit Statistics : ') panel.Add(wids['stat1'], dcol=4) panel.Add((5, 5), newrow=True) panel.Add(wids['stat2'], dcol=4) panel.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(panel, 1, LEFT, 3) pack(self, sizer) self.skip_process = False
def build(self): sizer = wx.GridBagSizer(5, 5) sizer.SetVGap(5) sizer.SetHGap(5) splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) splitter.SetMinimumPaneSize(200) self.datalistbox = EditableListBox(splitter, self.ShowDataSet, size=(250, -1)) panel = scrolled.ScrolledPanel(splitter) self.SetMinSize((650, 600)) self.colors = GUIColors() # title row self.wids = wids = {} title = SimpleText(panel, 'Linear Combination Results', font=Font(FONTSIZE + 2), colour=self.colors.title, style=LEFT) wids['plot_one'] = Button(panel, 'Plot This Fit', size=(125, -1), action=self.onPlotOne) wids['plot_sel'] = Button(panel, 'Plot N Best Fits', size=(125, -1), action=self.onPlotSel) wids['plot_ntitle'] = SimpleText(panel, 'N fits to plot: ') wids['plot_nchoice'] = Choice(panel, size=(60, -1), choices=['%d' % i for i in range(1, 21)]) wids['plot_nchoice'].SetStringSelection('5') wids['data_title'] = SimpleText(panel, '<--> ', font=Font(FONTSIZE + 2), colour=self.colors.title, style=LEFT) wids['nfits_title'] = SimpleText(panel, 'showing 5 best fits') copts = dict(size=(125, 30), default=True, action=self.onPlotOne) # wids['show_e0'] = Check(panel, label='show E0?', **copts) wids['show_fitrange'] = Check(panel, label='show fit range?', **copts) irow = 0 sizer.Add(title, (irow, 0), (1, 1), LEFT) sizer.Add(wids['data_title'], (irow, 1), (1, 2), LEFT) irow += 1 sizer.Add(wids['nfits_title'], (irow, 0), (1, 1), LEFT) irow += 1 self.wids['paramstitle'] = SimpleText(panel, '[[Parameters]]', font=Font(FONTSIZE + 2), colour=self.colors.title, style=LEFT) sizer.Add(self.wids['paramstitle'], (irow, 0), (1, 1), LEFT) pview = self.wids['params'] = dv.DataViewListCtrl(panel, style=DVSTYLE) pview.SetMinSize((475, 200)) pview.AppendTextColumn(' Parameter ', width=230) pview.AppendTextColumn(' Best-Fit Value', width=120) pview.AppendTextColumn(' Standard Error ', width=120) for col in range(3): this = pview.Columns[col] isort, align = True, wx.ALIGN_RIGHT if col == 0: align = wx.ALIGN_LEFT this.Sortable = isort this.Alignment = this.Renderer.Alignment = align irow += 1 sizer.Add(self.wids['params'], (irow, 0), (4, 1), LEFT) sizer.Add(self.wids['plot_one'], (irow, 1), (1, 2), LEFT) sizer.Add(self.wids['plot_sel'], (irow + 1, 1), (1, 2), LEFT) sizer.Add(self.wids['plot_ntitle'], (irow + 2, 1), (1, 1), LEFT) sizer.Add(self.wids['plot_nchoice'], (irow + 2, 2), (1, 1), LEFT) # sizer.Add(self.wids['show_e0'], (irow+3, 1), (1, 2), LEFT) sizer.Add(self.wids['show_fitrange'], (irow + 3, 1), (1, 2), LEFT) irow += 4 sizer.Add(HLine(panel, size=(675, 3)), (irow, 0), (1, 4), LEFT) sview = self.wids['stats'] = dv.DataViewListCtrl(panel, style=DVSTYLE) sview.Bind(dv.EVT_DATAVIEW_SELECTION_CHANGED, self.onSelectFitStat) sview.AppendTextColumn(' Fit #', width=50) sview.AppendTextColumn(' N_vary', width=50) sview.AppendTextColumn(' N_eval', width=60) sview.AppendTextColumn(' \u03c7\u00B2', width=110) sview.AppendTextColumn(' \u03c7\u00B2_reduced', width=110) sview.AppendTextColumn(' Akaike Info', width=110) sview.AppendTextColumn(' Bayesian Info', width=110) for col in range(sview.ColumnCount): this = sview.Columns[col] isort, align = True, wx.ALIGN_RIGHT if col == 0: align = wx.ALIGN_CENTER this.Sortable = isort this.Alignment = this.Renderer.Alignment = align sview.SetMinSize((675, 175)) irow += 1 title = SimpleText(panel, '[[Fit Statistics]]', font=Font(FONTSIZE + 2), colour=self.colors.title, style=LEFT) sizer.Add(title, (irow, 0), (1, 4), LEFT) irow += 1 sizer.Add(sview, (irow, 0), (1, 4), LEFT) irow += 1 sizer.Add(HLine(panel, size=(675, 3)), (irow, 0), (1, 4), LEFT) irow += 1 title = SimpleText(panel, '[[Weights]]', font=Font(FONTSIZE + 2), colour=self.colors.title, style=LEFT) sizer.Add(title, (irow, 0), (1, 4), LEFT) self.wids['weightspanel'] = ppan = wx.Panel(panel) p1 = SimpleText(ppan, ' < Weights > ') os = wx.BoxSizer(wx.VERTICAL) os.Add(p1, 1, 3) pack(ppan, os) ppan.SetMinSize((675, 175)) irow += 1 sizer.Add(ppan, (irow, 0), (1, 4), LEFT) irow += 1 sizer.Add(HLine(panel, size=(675, 3)), (irow, 0), (1, 4), LEFT) pack(panel, sizer) panel.SetupScrolling() splitter.SplitVertically(self.datalistbox, panel, 1) mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(splitter, 1, wx.GROW | wx.ALL, 5) pack(self, mainsizer) # self.SetSize((725, 750)) self.Show() self.Raise()
def build_display(self): titleopts = dict(font=Font(12), colour='#AA0000') panel = self.panel wids = self.wids self.skip_process = True wids['fitspace'] = Choice(panel, choices=FitSpace_Choices, size=(175, -1)) wids['fitspace'].SetStringSelection(norm) wids['plotchoice'] = Choice(panel, choices=Plot_Choices, size=(175, -1), action=self.onPlot) wids['plotchoice'].SetSelection(1) add_text = self.add_text opts = dict(digits=2, increment=1.0, relative_e0=True) e0_wids = self.add_floatspin('e0', value=0, **opts) elo_wids = self.add_floatspin('elo', value=-20, **opts) ehi_wids = self.add_floatspin('ehi', value=30, **opts) wids['fit_group'] = Button(panel, 'Fit this Group', size=(150, -1), action=self.onFitOne) wids['fit_selected'] = Button(panel, 'Fit Selected Groups', size=(150, -1), action=self.onFitAll) wids['add_selected'] = Button(panel, 'Use Selected Groups as Components', size=(250, -1), action=self.onUseSelected) wids['saveconf'] = Button(panel, 'Save as Default Settings', size=(200, -1), action=self.onSaveConfigBtn) opts = dict(default=True, size=(75, -1), action=self.onPlotOne) wids['show_e0'] = Check(panel, label='show?', **opts) wids['show_fitrange'] = Check(panel, label='show?', **opts) wids['sum_to_one'] = Check(panel, label='Weights Must Sum to 1?', default=True) wids['all_combos'] = Check(panel, label='Fit All Combinations?', default=True) panel.Add(SimpleText(panel, ' Linear Combination Analysis', **titleopts), dcol=5) add_text('Run Fit', newrow=False) add_text('Array to Fit: ', newrow=True) panel.Add(wids['fitspace'], dcol=4) panel.Add(wids['fit_group']) add_text('Plot : ', newrow=True) panel.Add(wids['plotchoice'], dcol=4) panel.Add(wids['fit_selected']) add_text('E0: ') panel.Add(e0_wids, dcol=3) panel.Add(wids['show_e0']) add_text('Fit Energy Range: ') panel.Add(elo_wids) add_text(' : ', newrow=False) panel.Add(ehi_wids) panel.Add(wids['show_fitrange']) panel.Add(wids['sum_to_one'], dcol=2, newrow=True) panel.Add(wids['all_combos'], dcol=3) panel.Add(HLine(panel, size=(400, 2)), dcol=5, newrow=True) add_text('Components: ') panel.Add(wids['add_selected'], dcol=4) groupnames = [noname] + list(self.controller.file_groups.keys()) sgrid = GridPanel(panel, nrows=6) sgrid.Add(SimpleText(sgrid, "#")) sgrid.Add(SimpleText(sgrid, "Group")) sgrid.Add(SimpleText(sgrid, "Weight")) sgrid.Add(SimpleText(sgrid, "Min Weight")) sgrid.Add(SimpleText(sgrid, "Max Weight")) fopts = dict(minval=-10, maxval=20, precision=4, size=(60, -1)) for i in range(1, 1 + MAX_COMPONENTS): si = ("comp", "_%2.2d" % i) sgrid.Add(SimpleText(sgrid, "%2i" % i), newrow=True) wids['%schoice%s' % si] = Choice(sgrid, choices=groupnames, size=(200, -1), action=partial(self.onComponent, comp=i)) wids['%sval%s' % si] = FloatCtrl(sgrid, value=0, **fopts) wids['%smin%s' % si] = FloatCtrl(sgrid, value=0, **fopts) wids['%smax%s' % si] = FloatCtrl(sgrid, value=1, **fopts) for cname in ('choice', 'val', 'min', 'max'): sgrid.Add(wids[("%%s%s%%s" % cname) % si]) sgrid.pack() panel.Add(sgrid, dcol=5, newrow=True) panel.Add(HLine(panel, size=(400, 2)), dcol=5, newrow=True) panel.Add(wids['saveconf'], dcol=4, newrow=True) panel.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(panel, 1, LCEN, 3) pack(self, sizer) self.skip_process = False
def build_display(self): self.mod_nb = flatnotebook(self, {}) pan = self.panel = GridPanel(self, ncols=4, nrows=4, pad=2, itemstyle=LEFT) self.wids = {} fsopts = dict(digits=2, increment=0.1, with_pin=True) ppeak_e0 = self.add_floatspin('ppeak_e0', value=0, **fsopts) ppeak_elo = self.add_floatspin('ppeak_elo', value=-15, **fsopts) ppeak_ehi = self.add_floatspin('ppeak_ehi', value=-5, **fsopts) ppeak_emin = self.add_floatspin('ppeak_emin', value=-30, **fsopts) ppeak_emax = self.add_floatspin('ppeak_emax', value=0, **fsopts) self.fitbline_btn = Button(pan,'Fit Baseline', action=self.onFitBaseline, size=(125, -1)) self.plotmodel_btn = Button(pan, 'Plot Model', action=self.onPlotModel, size=(125, -1)) self.fitmodel_btn = Button(pan, 'Fit Model', action=self.onFitModel, size=(125, -1)) self.loadmodel_btn = Button(pan, 'Load Model', action=self.onLoadFitResult, size=(125, -1)) self.fitmodel_btn.Disable() self.array_choice = Choice(pan, size=(175, -1), choices=list(Array_Choices.keys())) self.array_choice.SetSelection(1) models_peaks = Choice(pan, size=(150, -1), choices=ModelChoices['peaks'], action=self.addModel) models_other = Choice(pan, size=(150, -1), choices=ModelChoices['other'], action=self.addModel) self.models_peaks = models_peaks self.models_other = models_other self.message = SimpleText(pan, 'first fit baseline, then add peaks to fit model.') self.msg_centroid = SimpleText(pan, '----') opts = dict(default=True, size=(75, -1), action=self.onPlot) self.show_centroid = Check(pan, label='show?', **opts) self.show_peakrange = Check(pan, label='show?', **opts) self.show_fitrange = Check(pan, label='show?', **opts) self.show_e0 = Check(pan, label='show?', **opts) opts = dict(default=False, size=(200, -1), action=self.onPlot) def add_text(text, dcol=1, newrow=True): pan.Add(SimpleText(pan, text), dcol=dcol, newrow=newrow) pan.Add(SimpleText(pan, ' Pre-edge Peak Fitting', **self.titleopts), dcol=5) add_text(' Run Fit:', newrow=False) add_text('Array to fit: ') pan.Add(self.array_choice, dcol=3) pan.Add((10, 10)) pan.Add(self.fitbline_btn) add_text('E0: ') pan.Add(ppeak_e0) pan.Add((10, 10), dcol=2) pan.Add(self.show_e0) pan.Add(self.plotmodel_btn) add_text('Fit Energy Range: ') pan.Add(ppeak_emin) add_text(' : ', newrow=False) pan.Add(ppeak_emax) pan.Add(self.show_fitrange) pan.Add(self.fitmodel_btn) t = SimpleText(pan, 'Pre-edge Peak Range: ') SetTip(t, 'Range used as mask for background') pan.Add(t, newrow=True) pan.Add(ppeak_elo) add_text(' : ', newrow=False) pan.Add(ppeak_ehi) pan.Add(self.show_peakrange) # pan.Add(self.fitsel_btn) add_text( 'Peak Centroid: ') pan.Add(self.msg_centroid, dcol=3) pan.Add(self.show_centroid, dcol=1) pan.Add(self.loadmodel_btn) # add model ts = wx.BoxSizer(wx.HORIZONTAL) ts.Add(models_peaks) ts.Add(models_other) pan.Add(SimpleText(pan, 'Add Component: '), newrow=True) pan.Add(ts, dcol=7) pan.Add(SimpleText(pan, 'Messages: '), newrow=True) pan.Add(self.message, dcol=7) pan.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(pan, 0, LEFT, 3) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LEFT, 3) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(self.mod_nb, 1, LEFT|wx.GROW, 10) pack(self, sizer)
class PrePeakPanel(TaskPanel): def __init__(self, parent=None, controller=None, **kws): TaskPanel.__init__(self, parent, controller, configname='prepeaks_config', config=defaults, **kws) self.fit_components = OrderedDict() self.user_added_params = None self.pick2_timer = wx.Timer(self) self.pick2_group = None self.Bind(wx.EVT_TIMER, self.onPick2Timer, self.pick2_timer) self.pick2_t0 = 0. self.pick2_timeout = 15. self.pick2erase_timer = wx.Timer(self) self.pick2erase_panel = None self.Bind(wx.EVT_TIMER, self.onPick2EraseTimer, self.pick2erase_timer) def onPanelExposed(self, **kws): # called when notebook is selected try: fname = self.controller.filelist.GetStringSelection() gname = self.controller.file_groups[fname] dgroup = self.controller.get_group(gname) self.fill_form(dgroup) except: pass # print(" Cannot Fill prepeak panel from group ") def build_display(self): self.mod_nb = flatnotebook(self, {}) pan = self.panel = GridPanel(self, ncols=4, nrows=4, pad=2, itemstyle=LEFT) self.wids = {} fsopts = dict(digits=2, increment=0.1, with_pin=True) ppeak_e0 = self.add_floatspin('ppeak_e0', value=0, **fsopts) ppeak_elo = self.add_floatspin('ppeak_elo', value=-15, **fsopts) ppeak_ehi = self.add_floatspin('ppeak_ehi', value=-5, **fsopts) ppeak_emin = self.add_floatspin('ppeak_emin', value=-30, **fsopts) ppeak_emax = self.add_floatspin('ppeak_emax', value=0, **fsopts) self.fitbline_btn = Button(pan,'Fit Baseline', action=self.onFitBaseline, size=(125, -1)) self.plotmodel_btn = Button(pan, 'Plot Model', action=self.onPlotModel, size=(125, -1)) self.fitmodel_btn = Button(pan, 'Fit Model', action=self.onFitModel, size=(125, -1)) self.loadmodel_btn = Button(pan, 'Load Model', action=self.onLoadFitResult, size=(125, -1)) self.fitmodel_btn.Disable() self.array_choice = Choice(pan, size=(175, -1), choices=list(Array_Choices.keys())) self.array_choice.SetSelection(1) models_peaks = Choice(pan, size=(150, -1), choices=ModelChoices['peaks'], action=self.addModel) models_other = Choice(pan, size=(150, -1), choices=ModelChoices['other'], action=self.addModel) self.models_peaks = models_peaks self.models_other = models_other self.message = SimpleText(pan, 'first fit baseline, then add peaks to fit model.') self.msg_centroid = SimpleText(pan, '----') opts = dict(default=True, size=(75, -1), action=self.onPlot) self.show_centroid = Check(pan, label='show?', **opts) self.show_peakrange = Check(pan, label='show?', **opts) self.show_fitrange = Check(pan, label='show?', **opts) self.show_e0 = Check(pan, label='show?', **opts) opts = dict(default=False, size=(200, -1), action=self.onPlot) def add_text(text, dcol=1, newrow=True): pan.Add(SimpleText(pan, text), dcol=dcol, newrow=newrow) pan.Add(SimpleText(pan, ' Pre-edge Peak Fitting', **self.titleopts), dcol=5) add_text(' Run Fit:', newrow=False) add_text('Array to fit: ') pan.Add(self.array_choice, dcol=3) pan.Add((10, 10)) pan.Add(self.fitbline_btn) add_text('E0: ') pan.Add(ppeak_e0) pan.Add((10, 10), dcol=2) pan.Add(self.show_e0) pan.Add(self.plotmodel_btn) add_text('Fit Energy Range: ') pan.Add(ppeak_emin) add_text(' : ', newrow=False) pan.Add(ppeak_emax) pan.Add(self.show_fitrange) pan.Add(self.fitmodel_btn) t = SimpleText(pan, 'Pre-edge Peak Range: ') SetTip(t, 'Range used as mask for background') pan.Add(t, newrow=True) pan.Add(ppeak_elo) add_text(' : ', newrow=False) pan.Add(ppeak_ehi) pan.Add(self.show_peakrange) # pan.Add(self.fitsel_btn) add_text( 'Peak Centroid: ') pan.Add(self.msg_centroid, dcol=3) pan.Add(self.show_centroid, dcol=1) pan.Add(self.loadmodel_btn) # add model ts = wx.BoxSizer(wx.HORIZONTAL) ts.Add(models_peaks) ts.Add(models_other) pan.Add(SimpleText(pan, 'Add Component: '), newrow=True) pan.Add(ts, dcol=7) pan.Add(SimpleText(pan, 'Messages: '), newrow=True) pan.Add(self.message, dcol=7) pan.pack() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(pan, 0, LEFT, 3) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(HLine(self, size=(550, 2)), 0, LEFT, 3) sizer.Add((10, 10), 0, LEFT, 3) sizer.Add(self.mod_nb, 1, LEFT|wx.GROW, 10) pack(self, sizer) def get_config(self, dgroup=None): """get processing configuration for a group""" if dgroup is None: dgroup = self.controller.get_group() conf = getattr(dgroup, 'prepeak_config', {}) if 'e0' not in conf: conf = defaults conf['e0'] = getattr(dgroup, 'e0', -1) dgroup.prepeak_config = conf if not hasattr(dgroup, 'prepeaks'): dgroup.prepeaks = Group() return conf def fill_form(self, dat): if isinstance(dat, Group): self.wids['ppeak_e0'].SetValue(dat.e0) if hasattr(dat, 'prepeaks'): self.wids['ppeak_emin'].SetValue(dat.prepeaks.emin) self.wids['ppeak_emax'].SetValue(dat.prepeaks.emax) self.wids['ppeak_elo'].SetValue(dat.prepeaks.elo) self.wids['ppeak_ehi'].SetValue(dat.prepeaks.ehi) elif isinstance(dat, dict): self.wids['ppeak_e0'].SetValue(dat['e0']) self.wids['ppeak_emin'].SetValue(dat['emin']) self.wids['ppeak_emax'].SetValue(dat['emax']) self.wids['ppeak_elo'].SetValue(dat['elo']) self.wids['ppeak_ehi'].SetValue(dat['ehi']) self.array_choice.SetStringSelection(dat['array_desc']) self.show_e0.Enable(dat['show_e0']) self.show_centroid.Enable(dat['show_centroid']) self.show_fitrange.Enable(dat['show_fitrange']) self.show_peakrange.Enable(dat['show_peakrange']) def read_form(self): "read for, returning dict of values" dgroup = self.controller.get_group() array_desc = self.array_choice.GetStringSelection() form_opts = {'gname': dgroup.groupname, 'filename': dgroup.filename, 'array_desc': array_desc.lower(), 'array_name': Array_Choices[array_desc], 'baseline_form': 'lorentzian', 'bkg_components': []} form_opts['e0'] = self.wids['ppeak_e0'].GetValue() form_opts['emin'] = self.wids['ppeak_emin'].GetValue() form_opts['emax'] = self.wids['ppeak_emax'].GetValue() form_opts['elo'] = self.wids['ppeak_elo'].GetValue() form_opts['ehi'] = self.wids['ppeak_ehi'].GetValue() form_opts['plot_sub_bline'] = False # self.plot_sub_bline.IsChecked() form_opts['show_centroid'] = self.show_centroid.IsChecked() form_opts['show_peakrange'] = self.show_peakrange.IsChecked() form_opts['show_fitrange'] = self.show_fitrange.IsChecked() form_opts['show_e0'] = self.show_e0.IsChecked() return form_opts def onFitBaseline(self, evt=None): opts = self.read_form() cmd = """{gname:s}.ydat = 1.0*{gname:s}.{array_name:s} pre_edge_baseline(energy={gname:s}.energy, norm={gname:s}.ydat, group={gname:s}, form='{baseline_form:s}', with_line=True, elo={elo:.3f}, ehi={ehi:.3f}, emin={emin:.3f}, emax={emax:.3f})""" self.larch_eval(cmd.format(**opts)) dgroup = self.controller.get_group() ppeaks = dgroup.prepeaks dgroup.centroid_msg = "%.4f +/- %.4f eV" % (ppeaks.centroid, ppeaks.delta_centroid) self.msg_centroid.SetLabel(dgroup.centroid_msg) if 'bpeak_' not in self.fit_components: self.addModel(model='Lorentzian', prefix='bpeak_', isbkg=True) if 'bline_' not in self.fit_components: self.addModel(model='Linear', prefix='bline_', isbkg=True) for prefix in ('bpeak_', 'bline_'): cmp = self.fit_components[prefix] # cmp.bkgbox.SetValue(1) self.fill_model_params(prefix, dgroup.prepeaks.fit_details.params) self.fill_form(dgroup) self.fitmodel_btn.Enable() # self.fitallmodel_btn.Enable() i1, i2 = self.get_xranges(dgroup.energy) dgroup.yfit = dgroup.xfit = 0.0*dgroup.energy[i1:i2] # self.plot_choice.SetStringSelection(PLOT_BASELINE) self.onPlot(baseline_only=True) def fill_model_params(self, prefix, params): comp = self.fit_components[prefix] parwids = comp.parwids for pname, par in params.items(): pname = prefix + pname if pname in parwids: wids = parwids[pname] if wids.minval is not None: wids.minval.SetValue(par.min) if wids.maxval is not None: wids.maxval.SetValue(par.max) wids.value.SetValue(par.value) varstr = 'vary' if par.vary else 'fix' if par.expr is not None: varstr = 'constrain' if wids.vary is not None: wids.vary.SetStringSelection(varstr) def onPlotModel(self, evt=None): dgroup = self.controller.get_group() g = self.build_fitmodel(dgroup) self.onPlot(show_init=True) def onPlot(self, evt=None, baseline_only=False, show_init=False): opts = self.read_form() dgroup = self.controller.get_group() opts['group'] = opts['gname'] self.larch_eval(COMMANDS['prepeaks_setup'].format(**opts)) cmd = "plot_prepeaks_fit" args = ['{gname}'] if baseline_only: cmd = "plot_prepeaks_baseline" else: args.append("show_init=%s" % (show_init)) cmd = "%s(%s)" % (cmd, ', '.join(args)) self.larch_eval(cmd.format(**opts)) def addModel(self, event=None, model=None, prefix=None, isbkg=False): if model is None and event is not None: model = event.GetString() if model is None or model.startswith('<'): return self.models_peaks.SetSelection(0) self.models_other.SetSelection(0) if prefix is None: p = model[:5].lower() curmodels = ["%s%i_" % (p, i+1) for i in range(1+len(self.fit_components))] for comp in self.fit_components: if comp in curmodels: curmodels.remove(comp) prefix = curmodels[0] label = "%s(prefix='%s')" % (model, prefix) title = "%s: %s " % (prefix[:-1], model) title = prefix[:-1] mclass_kws = {'prefix': prefix} if 'step' in model.lower(): form = model.lower().replace('step', '').strip() if form.startswith('err'): form = 'erf' label = "Step(form='%s', prefix='%s')" % (form, prefix) title = "%s: Step %s" % (prefix[:-1], form[:3]) mclass = lm_models.StepModel mclass_kws['form'] = form minst = mclass(form=form, prefix=prefix) else: if model in ModelFuncs: mclass = getattr(lm_models, ModelFuncs[model]) else: mclass = getattr(lm_models, model+'Model') minst = mclass(prefix=prefix) panel = GridPanel(self.mod_nb, ncols=2, nrows=5, pad=1, itemstyle=CEN) def SLabel(label, size=(80, -1), **kws): return SimpleText(panel, label, size=size, style=wx.ALIGN_LEFT, **kws) usebox = Check(panel, default=True, label='Use in Fit?', size=(100, -1)) bkgbox = Check(panel, default=False, label='Is Baseline?', size=(125, -1)) if isbkg: bkgbox.SetValue(1) delbtn = Button(panel, 'Delete This Component', size=(200, -1), action=partial(self.onDeleteComponent, prefix=prefix)) pick2msg = SimpleText(panel, " ", size=(125, -1)) pick2btn = Button(panel, 'Pick Values from Plotted Data', size=(200, -1), action=partial(self.onPick2Points, prefix=prefix)) # SetTip(mname, 'Label for the model component') SetTip(usebox, 'Use this component in fit?') SetTip(bkgbox, 'Label this component as "background" when plotting?') SetTip(delbtn, 'Delete this model component') SetTip(pick2btn, 'Select X range on Plot to Guess Initial Values') panel.Add(SLabel(label, size=(275, -1), colour='#0000AA'), dcol=4, style=wx.ALIGN_LEFT, newrow=True) panel.Add(usebox, dcol=2) panel.Add(bkgbox, dcol=1, style=RIGHT) panel.Add(pick2btn, dcol=2, style=wx.ALIGN_LEFT, newrow=True) panel.Add(pick2msg, dcol=3, style=wx.ALIGN_RIGHT) panel.Add(delbtn, dcol=2, style=wx.ALIGN_RIGHT) # panel.Add(HLine(panel, size=(150, 3)), dcol=4, style=wx.ALIGN_CENTER) panel.Add(SLabel("Parameter "), style=wx.ALIGN_LEFT, newrow=True) panel.AddMany((SLabel(" Value"), SLabel(" Type"), SLabel(' Bounds'), SLabel(" Min", size=(60, -1)), SLabel(" Max", size=(60, -1)), SLabel(" Expression"))) parwids = OrderedDict() parnames = sorted(minst.param_names) for a in minst._func_allargs: pname = "%s%s" % (prefix, a) if (pname not in parnames and a in minst.param_hints and a not in minst.independent_vars): parnames.append(pname) for pname in parnames: sname = pname[len(prefix):] hints = minst.param_hints.get(sname, {}) par = Parameter(name=pname, value=0, vary=True) if 'min' in hints: par.min = hints['min'] if 'max' in hints: par.max = hints['max'] if 'value' in hints: par.value = hints['value'] if 'expr' in hints: par.expr = hints['expr'] pwids = ParameterWidgets(panel, par, name_size=100, expr_size=150, float_size=80, prefix=prefix, widgets=('name', 'value', 'minval', 'maxval', 'vary', 'expr')) parwids[par.name] = pwids panel.Add(pwids.name, newrow=True) panel.AddMany((pwids.value, pwids.vary, pwids.bounds, pwids.minval, pwids.maxval, pwids.expr)) for sname, hint in minst.param_hints.items(): pname = "%s%s" % (prefix, sname) if 'expr' in hint and pname not in parnames: par = Parameter(name=pname, value=0, expr=hint['expr']) pwids = ParameterWidgets(panel, par, name_size=100, expr_size=400, float_size=80, prefix=prefix, widgets=('name', 'value', 'expr')) parwids[par.name] = pwids panel.Add(pwids.name, newrow=True) panel.Add(pwids.value) panel.Add(pwids.expr, dcol=5, style=wx.ALIGN_RIGHT) pwids.value.Disable() fgroup = Group(prefix=prefix, title=title, mclass=mclass, mclass_kws=mclass_kws, usebox=usebox, panel=panel, parwids=parwids, float_size=65, expr_size=150, pick2_msg=pick2msg, bkgbox=bkgbox) self.fit_components[prefix] = fgroup panel.pack() self.mod_nb.AddPage(panel, title, True) sx,sy = self.GetSize() self.SetSize((sx, sy+1)) self.SetSize((sx, sy)) self.fitmodel_btn.Enable() def onDeleteComponent(self, evt=None, prefix=None): fgroup = self.fit_components.get(prefix, None) if fgroup is None: return for i in range(self.mod_nb.GetPageCount()): if fgroup.title == self.mod_nb.GetPageText(i): self.mod_nb.DeletePage(i) for attr in dir(fgroup): setattr(fgroup, attr, None) self.fit_components.pop(prefix) if len(self.fit_components) < 1: self.fitmodel_btn.Disable() # sx,sy = self.GetSize() # self.SetSize((sx, sy+1)) # self.SetSize((sx, sy)) def onPick2EraseTimer(self, evt=None): """erases line trace showing automated 'Pick 2' guess """ self.pick2erase_timer.Stop() panel = self.pick2erase_panel ntrace = panel.conf.ntrace - 1 trace = panel.conf.get_mpl_line(ntrace) panel.conf.get_mpl_line(ntrace).set_data(np.array([]), np.array([])) panel.conf.ntrace = ntrace panel.draw() def onPick2Timer(self, evt=None): """checks for 'Pick 2' events, and initiates 'Pick 2' guess for a model from the selected data range """ try: plotframe = self.controller.get_display(win=1) curhist = plotframe.cursor_hist[:] plotframe.Raise() except: return if (time.time() - self.pick2_t0) > self.pick2_timeout: msg = self.pick2_group.pick2_msg.SetLabel(" ") plotframe.cursor_hist = [] self.pick2_timer.Stop() return if len(curhist) < 2: self.pick2_group.pick2_msg.SetLabel("%i/2" % (len(curhist))) return self.pick2_group.pick2_msg.SetLabel("done.") self.pick2_timer.Stop() # guess param values xcur = (curhist[0][0], curhist[1][0]) xmin, xmax = min(xcur), max(xcur) dgroup = getattr(self.larch.symtable, self.controller.groupname) x, y = dgroup.xdat, dgroup.ydat i0 = index_of(dgroup.xdat, xmin) i1 = index_of(dgroup.xdat, xmax) x, y = dgroup.xdat[i0:i1+1], dgroup.ydat[i0:i1+1] mod = self.pick2_group.mclass(prefix=self.pick2_group.prefix) parwids = self.pick2_group.parwids try: guesses = mod.guess(y, x=x) except: return for name, param in guesses.items(): if name in parwids: parwids[name].value.SetValue(param.value) dgroup._tmp = mod.eval(guesses, x=dgroup.xdat) plotframe = self.controller.get_display(win=1) plotframe.cursor_hist = [] plotframe.oplot(dgroup.xdat, dgroup._tmp) self.pick2erase_panel = plotframe.panel self.pick2erase_timer.Start(5000) def onPick2Points(self, evt=None, prefix=None): fgroup = self.fit_components.get(prefix, None) if fgroup is None: return plotframe = self.controller.get_display(win=1) plotframe.Raise() plotframe.cursor_hist = [] fgroup.npts = 0 self.pick2_group = fgroup if fgroup.pick2_msg is not None: fgroup.pick2_msg.SetLabel("0/2") self.pick2_t0 = time.time() self.pick2_timer.Start(250) def onLoadFitResult(self, event=None): dlg = wx.FileDialog(self, message="Load Saved File Model", wildcard=ModelWcards, style=wx.FD_OPEN) rfile = None if dlg.ShowModal() == wx.ID_OK: rfile = dlg.GetPath() dlg.Destroy() if rfile is None: return self.larch_eval("# peakmodel = lm_load_modelresult('%s')" %rfile) result = load_modelresult(str(rfile)) for prefix in list(self.fit_components.keys()): self.onDeleteComponent(self, prefix=prefix) for comp in result.model.components: isbkg = comp.prefix in result.user_options['bkg_components'] self.addModel(model=comp.func.__name__, prefix=comp.prefix, isbkg=isbkg) for comp in result.model.components: parwids = self.fit_components[comp.prefix].parwids for pname, par in result.params.items(): if pname in parwids: wids = parwids[pname] if wids.minval is not None: wids.minval.SetValue(par.min) if wids.maxval is not None: wids.maxval.SetValue(par.max) val = result.init_values.get(pname, par.value) wids.value.SetValue(val) self.fill_form(result.user_options) def onSelPoint(self, evt=None, opt='__', relative_e0=False, win=None): """ get last selected point from a specified plot window and fill in the value for the widget defined by `opt`. by default it finds the latest cursor position from the cursor history of the first 20 plot windows. """ if opt not in self.wids: return None _x, _y = last_cursor_pos(win=win, _larch=self.larch) if _x is not None: if relative_e0 and 'e0' in self.wids: _x -= self.wids['e0'].GetValue() self.wids[opt].SetValue(_x) def get_xranges(self, x): opts = self.read_form() dgroup = self.controller.get_group() en_eps = min(np.diff(dgroup.energy)) / 5. i1 = index_of(x, opts['emin'] + en_eps) i2 = index_of(x, opts['emax'] + en_eps) + 1 return i1, i2 def build_fitmodel(self, dgroup): """ use fit components to build model""" # self.summary = {'components': [], 'options': {}} peaks = [] cmds = ["## set up pre-edge peak parameters", "peakpars = Parameters()"] modcmds = ["## define pre-edge peak model"] modop = " =" opts = self.read_form() opts['group'] = opts['gname'] self.larch_eval(COMMANDS['prepeaks_setup'].format(**opts)) for comp in self.fit_components.values(): _cen, _amp = None, None if comp.usebox is not None and comp.usebox.IsChecked(): for parwids in comp.parwids.values(): this = parwids.param pargs = ["'%s'" % this.name, 'value=%f' % (this.value), 'min=%f' % (this.min), 'max=%f' % (this.max)] if this.expr is not None: pargs.append("expr='%s'" % (this.expr)) elif not this.vary: pargs.pop() pargs.pop() pargs.append("vary=False") cmds.append("peakpars.add(%s)" % (', '.join(pargs))) if this.name.endswith('_center'): _cen = this.name elif parwids.param.name.endswith('_amplitude'): _amp = this.name compargs = ["%s='%s'" % (k,v) for k,v in comp.mclass_kws.items()] modcmds.append("peakmodel %s %s(%s)" % (modop, comp.mclass.__name__, ', '.join(compargs))) modop = "+=" if not comp.bkgbox.IsChecked() and _cen is not None and _amp is not None: peaks.append((_amp, _cen)) if len(peaks) > 0: denom = '+'.join([p[0] for p in peaks]) numer = '+'.join(["%s*%s "% p for p in peaks]) cmds.append("peakpars.add('fit_centroid', expr='(%s)/(%s)')" % (numer, denom)) cmds.extend(modcmds) cmds.append(COMMANDS['prepfit'].format(group=dgroup.groupname, user_opts=repr(opts))) self.larch_eval("\n".join(cmds)) def onFitSelected(self, event=None): dgroup = self.controller.get_group() self.build_fitmodel(dgroup) def onFitModel(self, event=None): dgroup = self.controller.get_group() if dgroup is None: return self.build_fitmodel(dgroup) opts = self.read_form() dgroup = self.controller.get_group() opts['group'] = opts['gname'] self.larch_eval(COMMANDS['prepeaks_setup'].format(**opts)) ppeaks = dgroup.prepeaks # add bkg_component to saved user options bkg_comps = [] for label, comp in self.fit_components.items(): if comp.bkgbox.IsChecked(): bkg_comps.append(label) opts['bkg_components'] = bkg_comps imin, imax = self.get_xranges(dgroup.xdat) cmds = ["## do peak fit: "] yerr_type = 'set_yerr_const' yerr = getattr(dgroup, 'yerr', None) if yerr is None: if hasattr(dgroup, 'norm_std'): cmds.append("{group}.yerr = {group}.norm_std") yerr_type = 'set_yerr_array' elif hasattr(dgroup, 'mu_std'): cmds.append("{group}.yerr = {group}.mu_std/(1.e-15+{group}.edge_step)") yerr_type = 'set_yerr_array' else: cmds.append("{group}.yerr = 1") elif isinstance(dgroup.yerr, np.ndarray): yerr_type = 'set_yerr_array' cmds.extend([COMMANDS[yerr_type], COMMANDS['dofit']]) cmd = '\n'.join(cmds) self.larch_eval(cmd.format(group=dgroup.groupname, imin=imin, imax=imax, user_opts=repr(opts))) self.autosave_modelresult(self.larch_get("peakresult")) self.onPlot() self.show_subframe('prepeak_result_frame', FitResultFrame, datagroup=dgroup, peakframe=self) self.subframes['prepeak_result_frame'].show_results() def update_start_values(self, params): """fill parameters with best fit values""" allparwids = {} for comp in self.fit_components.values(): if comp.usebox is not None and comp.usebox.IsChecked(): for name, parwids in comp.parwids.items(): allparwids[name] = parwids for pname, par in params.items(): if pname in allparwids: allparwids[pname].value.SetValue(par.value) def autosave_modelresult(self, result, fname=None): """autosave model result to user larch folder""" confdir = os.path.join(site_config.usr_larchdir, 'xas_viewer') if not os.path.exists(confdir): try: os.makedirs(confdir) except OSError: print("Warning: cannot create XAS_Viewer user folder") return if not HAS_MODELSAVE: print("Warning: cannot save model results: upgrade lmfit") return if fname is None: fname = 'autosave.fitmodel' save_modelresult(result, os.path.join(confdir, fname))
def build(self): sizer = wx.GridBagSizer(10, 5) sizer.SetVGap(5) sizer.SetHGap(5) panel = scrolled.ScrolledPanel(self) self.SetMinSize((700, 450)) self.colors = GUIColors() # title row self.wids = wids = {} title = SimpleText(panel, 'Fit Results', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) wids['data_title'] = SimpleText(panel, '< > ', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) wids['hist_info'] = SimpleText(panel, ' ___ ', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) wids['hist_hint'] = SimpleText(panel, ' (Fit #01 is most recent)', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) opts = dict(default=False, size=(200, -1), action=self.onPlot) wids['plot_bline'] = Check(panel, label='Plot baseline-subtracted?', **opts) wids['plot_resid'] = Check(panel, label='Plot with residual?', **opts) self.plot_choice = Button(panel, 'Plot Selected Fit', size=(175, -1), action=self.onPlot) self.save_result = Button(panel, 'Save Selected Model', size=(175, -1), action=self.onSaveFitResult) SetTip(self.save_result, 'save model and result to be loaded later') self.export_fit = Button(panel, 'Export Fit', size=(175, -1), action=self.onExportFitResult) SetTip(self.export_fit, 'save arrays and results to text file') irow = 0 sizer.Add(title, (irow, 0), (1, 2), LEFT) sizer.Add(wids['data_title'], (irow, 2), (1, 2), LEFT) irow += 1 sizer.Add(wids['hist_info'], (irow, 0), (1, 2), LEFT) sizer.Add(wids['hist_hint'], (irow, 2), (1, 2), LEFT) irow += 1 wids['model_desc'] = SimpleText(panel, '<Model>', font=Font(FONTSIZE+1), size=(700, 50), style=LEFT) sizer.Add(wids['model_desc'], (irow, 0), (1, 6), LEFT) irow += 1 sizer.Add(self.save_result, (irow, 0), (1, 1), LEFT) sizer.Add(self.export_fit, (irow, 1), (1, 2), LEFT) irow += 1 # sizer.Add(SimpleText(panel, 'Plot: '), (irow, 0), (1, 1), LEFT) sizer.Add(self.plot_choice, (irow, 0), (1, 2), LEFT) sizer.Add(wids['plot_bline'], (irow, 2), (1, 1), LEFT) sizer.Add(wids['plot_resid'], (irow, 3), (1, 1), LEFT) irow += 1 sizer.Add(HLine(panel, size=(650, 3)), (irow, 0), (1, 5), LEFT) irow += 1 title = SimpleText(panel, '[[Fit Statistics]]', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) sizer.Add(title, (irow, 0), (1, 4), LEFT) sview = self.wids['stats'] = dv.DataViewListCtrl(panel, style=DVSTYLE) sview.Bind(dv.EVT_DATAVIEW_SELECTION_CHANGED, self.onSelectFit) sview.AppendTextColumn(' Fit #', width=50) sview.AppendTextColumn(' N_data', width=50) sview.AppendTextColumn(' N_vary', width=50) sview.AppendTextColumn(' N_eval', width=60) sview.AppendTextColumn(' \u03c7\u00B2', width=110) sview.AppendTextColumn(' \u03c7\u00B2_reduced', width=110) sview.AppendTextColumn(' Akaike Info', width=110) sview.AppendTextColumn(' Bayesian Info', width=110) for col in range(sview.ColumnCount): this = sview.Columns[col] isort, align = True, wx.ALIGN_RIGHT if col == 0: align = wx.ALIGN_CENTER this.Sortable = isort this.Alignment = this.Renderer.Alignment = align sview.SetMinSize((700, 125)) irow += 1 sizer.Add(sview, (irow, 0), (1, 5), LEFT) irow += 1 sizer.Add(HLine(panel, size=(650, 3)), (irow, 0), (1, 5), LEFT) irow += 1 title = SimpleText(panel, '[[Variables]]', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) sizer.Add(title, (irow, 0), (1, 1), LEFT) self.wids['copy_params'] = Button(panel, 'Update Model with these values', size=(250, -1), action=self.onCopyParams) sizer.Add(self.wids['copy_params'], (irow, 1), (1, 3), LEFT) pview = self.wids['params'] = dv.DataViewListCtrl(panel, style=DVSTYLE) self.wids['paramsdata'] = [] pview.AppendTextColumn('Parameter', width=150) pview.AppendTextColumn('Best-Fit Value', width=125) pview.AppendTextColumn('Standard Error', width=125) pview.AppendTextColumn('Info ', width=275) for col in range(4): this = pview.Columns[col] align = wx.ALIGN_LEFT if col in (1, 2): align = wx.ALIGN_RIGHT this.Sortable = False this.Alignment = this.Renderer.Alignment = align pview.SetMinSize((700, 200)) pview.Bind(dv.EVT_DATAVIEW_SELECTION_CHANGED, self.onSelectParameter) irow += 1 sizer.Add(pview, (irow, 0), (1, 5), LEFT) irow += 1 sizer.Add(HLine(panel, size=(650, 3)), (irow, 0), (1, 5), LEFT) irow += 1 title = SimpleText(panel, '[[Correlations]]', font=Font(FONTSIZE+2), colour=self.colors.title, style=LEFT) self.wids['all_correl'] = Button(panel, 'Show All', size=(100, -1), action=self.onAllCorrel) self.wids['min_correl'] = FloatSpin(panel, value=MIN_CORREL, min_val=0, size=(100, -1), digits=3, increment=0.1) ctitle = SimpleText(panel, 'minimum correlation: ') sizer.Add(title, (irow, 0), (1, 1), LEFT) sizer.Add(ctitle, (irow, 1), (1, 1), LEFT) sizer.Add(self.wids['min_correl'], (irow, 2), (1, 1), LEFT) sizer.Add(self.wids['all_correl'], (irow, 3), (1, 1), LEFT) irow += 1 cview = self.wids['correl'] = dv.DataViewListCtrl(panel, style=DVSTYLE) cview.AppendTextColumn('Parameter 1', width=150) cview.AppendTextColumn('Parameter 2', width=150) cview.AppendTextColumn('Correlation', width=150) for col in (0, 1, 2): this = cview.Columns[col] this.Sortable = False align = wx.ALIGN_LEFT if col == 2: align = wx.ALIGN_RIGHT this.Alignment = this.Renderer.Alignment = align cview.SetMinSize((475, 200)) irow += 1 sizer.Add(cview, (irow, 0), (1, 5), LEFT) irow += 1 sizer.Add(HLine(panel, size=(400, 3)), (irow, 0), (1, 5), LEFT) pack(panel, sizer) panel.SetupScrolling() mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 1, wx.GROW|wx.ALL, 1) pack(self, mainsizer) self.Show() self.Raise()