示例#1
0
    def createMainPanel(self):

        display0 = wx.Display(0)
        client_area = display0.ClientArea
        xmin, ymin, xmax, ymax = client_area
        xpos = int((xmax-xmin)*0.02) + xmin
        ypos = int((ymax-ymin)*0.04) + ymin
        self.SetPosition((xpos, ypos))


        splitter  = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
        splitter.SetMinimumPaneSize(250)

        leftpanel = wx.Panel(splitter)
        ltop = wx.Panel(leftpanel)

        def Btn(msg, x, act):
            b = Button(ltop, msg, size=(x, 30),  action=act)
            b.SetFont(Font(FONTSIZE))
            return b

        sel_none = Btn('Select None',   120, self.onSelNone)
        sel_all  = Btn('Select All',    120, self.onSelAll)

        self.controller.filelist = FileCheckList(leftpanel,
                                                 # main=self,
                                                 select_action=self.ShowFile,
                                                 remove_action=self.RemoveFile)

        tsizer = wx.BoxSizer(wx.HORIZONTAL)
        tsizer.Add(sel_all, 1, LCEN|wx.GROW, 1)
        tsizer.Add(sel_none, 1, LCEN|wx.GROW, 1)
        pack(ltop, tsizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(ltop, 0, LCEN|wx.GROW, 1)
        sizer.Add(self.controller.filelist, 1, LCEN|wx.GROW|wx.ALL, 1)

        pack(leftpanel, sizer)

        # right hand side
        panel = wx.Panel(splitter)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self.title = SimpleText(panel, 'initializing...', size=(300, -1))
        self.title.SetFont(Font(FONTSIZE+2))

        ir = 0
        sizer.Add(self.title, 0, LCEN|wx.GROW|wx.ALL, 1)
        self.nb = flatnotebook(panel, NB_PANELS,
                               panelkws=dict(controller=self.controller),
                               on_change=self.onNBChanged)
        sizer.Add(self.nb, 1, LCEN|wx.EXPAND, 2)
        pack(panel, sizer)

        splitter.SplitVertically(leftpanel, panel, 1)
        wx.CallAfter(self.init_larch)
示例#2
0
    def build_display(self):
        """build display"""

        self.panel.Add(SimpleText(self.panel, self.title, **titleopts),
                       dcol=7)
        self.panel.Add(SimpleText(self.panel, ' coming soon....'),
                       dcol=7, newrow=True)
        self.panel.pack()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel, 1, wx.LEFT|wx.CENTER, 3)
        pack(self, sizer)
示例#3
0
 def add_text(text, dcol=1, newrow=True):
     pan.Add(SimpleText(pan, text), dcol=dcol, newrow=newrow)
示例#4
0
    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)
示例#5
0
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)
示例#6
0
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))
示例#7
0
class XASFrame(wx.Frame):
    _about = """Larch XAS GUI: XAS Visualization and Analysis

    Matt Newville <newville @ cars.uchicago.edu>
    """

    def __init__(self, parent=None, _larch=None, **kws):
        wx.Frame.__init__(self,
                          parent,
                          -1,
                          size=XASVIEW_SIZE,
                          style=FRAMESTYLE)

        self.last_array_sel = {}
        self.paths2read = []

        title = "Larch XAS GUI: XAS Visualization and Analysis"

        self.larch_buffer = parent
        if not isinstance(parent, LarchFrame):
            self.larch_buffer = LarchFrame(_larch=_larch)

        self.larch_buffer.Show()
        self.larch_buffer.Raise()
        self.larch = self.larch_buffer.larchshell
        self.larch.symtable._sys.xas_viewer = Group()

        self.controller = XASController(wxparent=self, _larch=self.larch)
        self.current_filename = None
        self.subframes = {}
        self.plotframe = None
        self.SetTitle(title)
        self.SetSize(XASVIEW_SIZE)

        self.SetFont(Font(FONTSIZE))
        self.larch_buffer.Hide()
        self.createMainPanel()
        self.createMenus()
        self.statusbar = self.CreateStatusBar(2, 0)
        self.statusbar.SetStatusWidths([-3, -1])
        statusbar_fields = ["Initializing....", " "]
        for i in range(len(statusbar_fields)):
            self.statusbar.SetStatusText(statusbar_fields[i], i)

    def createMainPanel(self):

        display0 = wx.Display(0)
        client_area = display0.ClientArea
        xmin, ymin, xmax, ymax = client_area
        xpos = int((xmax - xmin) * 0.02) + xmin
        ypos = int((ymax - ymin) * 0.04) + ymin
        self.SetPosition((xpos, ypos))

        splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
        splitter.SetMinimumPaneSize(250)

        leftpanel = wx.Panel(splitter)
        ltop = wx.Panel(leftpanel)

        def Btn(msg, x, act):
            b = Button(ltop, msg, size=(x, 30), action=act)
            b.SetFont(Font(FONTSIZE))
            return b

        sel_none = Btn('Select None', 120, self.onSelNone)
        sel_all = Btn('Select All', 120, self.onSelAll)
        self.controller.filelist = FileCheckList(
            leftpanel,
            # main=self,
            select_action=self.ShowFile,
            remove_action=self.RemoveFile)

        tsizer = wx.BoxSizer(wx.HORIZONTAL)
        tsizer.Add(sel_all, 1, LCEN | wx.GROW, 1)
        tsizer.Add(sel_none, 1, LCEN | wx.GROW, 1)
        pack(ltop, tsizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(ltop, 0, LCEN | wx.GROW, 1)
        sizer.Add(self.controller.filelist, 1, LCEN | wx.GROW | wx.ALL, 1)

        pack(leftpanel, sizer)

        # right hand side
        panel = wx.Panel(splitter)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self.title = SimpleText(panel, 'initializing...', size=(300, -1))
        self.title.SetFont(Font(FONTSIZE + 1))

        ir = 0
        sizer.Add(self.title, 0, LCEN | wx.GROW | wx.ALL, 1)

        self.nb = flat_nb.FlatNotebook(panel, -1, agwStyle=FNB_STYLE)

        self.nb.SetTabAreaColour(wx.Colour(250, 250, 250))
        self.nb.SetActiveTabColour(wx.Colour(254, 254, 195))

        self.nb.SetNonActiveTabTextColour(wx.Colour(10, 10, 128))
        self.nb.SetActiveTabTextColour(wx.Colour(128, 0, 0))

        self.nb_panels = []
        for name, creator in NB_PANELS:
            _panel = creator(parent=self, controller=self.controller)
            self.nb.AddPage(_panel, " %s " % name, True)
            self.nb_panels.append(_panel)

        sizer.Add(self.nb, 1, LCEN | wx.EXPAND, 2)
        self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNBChanged)
        self.nb.SetSelection(0)

        pack(panel, sizer)

        splitter.SplitVertically(leftpanel, panel, 1)
        wx.CallAfter(self.init_larch)

    def onNBChanged(self, event=None):
        idx = self.nb.GetSelection()
        pan = self.nb_panels[idx]

        callback = getattr(pan, 'onPanelExposed', None)
        if callable(callback):
            callback()

    def onSelAll(self, event=None):
        self.controller.filelist.SetCheckedStrings(
            self.controller.file_groups.keys())

    def onSelNone(self, event=None):
        self.controller.filelist.SetCheckedStrings([])

    def init_larch(self):
        self.SetStatusText('initializing Larch')
        self.title.SetLabel('')

        self.controller.init_larch()

        plotframe = self.controller.get_display(stacked=False)
        xpos, ypos = self.GetPosition()
        xsiz, ysiz = self.GetSize()
        plotframe.SetPosition((xpos + xsiz + 5, ypos))
        plotframe.SetSize((ysiz, ysiz))

        self.SetStatusText('ready')
        self.Raise()

    def write_message(self, s, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(s, panel)

    def RemoveFile(self, fname=None, **kws):
        if fname is not None:
            s = str(fname)
            if s in self.controller.file_groups:
                group = self.controller.file_groups.pop(s)

    def ShowFile(self,
                 evt=None,
                 groupname=None,
                 process=True,
                 plot=True,
                 **kws):
        filename = None
        if evt is not None:
            filename = str(evt.GetString())

        if groupname is None and filename is not None:
            groupname = self.controller.file_groups[filename]

        if not hasattr(self.larch.symtable, groupname):
            return

        dgroup = self.controller.get_group(groupname)
        if filename is None:
            filename = dgroup.filename
        self.title.SetLabel(filename)
        self.current_filename = filename

        self.controller.group = dgroup
        self.controller.groupname = groupname
        cur_panel = self.nb_panels[self.nb.GetSelection()]
        if process:
            cur_panel.fill_form(dgroup=dgroup)
            cur_panel.process(dgroup=dgroup)
            if plot and hasattr(cur_panel, 'plot'):
                cur_panel.plot(dgroup=dgroup)

    def createMenus(self):
        # ppnl = self.plotpanel
        self.menubar = wx.MenuBar()
        #
        fmenu = wx.Menu()
        group_menu = wx.Menu()
        data_menu = wx.Menu()
        ppeak_menu = wx.Menu()
        m = {}

        MenuItem(self, fmenu, "&Open Data File\tCtrl+O", "Open Data File",
                 self.onReadDialog)

        MenuItem(self, fmenu, "&Save Project\tCtrl+S",
                 "Save Session to Project File", self.onSaveProject)

        MenuItem(self, fmenu, "Export Selected Groups to Athena Project",
                 "Export Selected Groups to Athena Project",
                 self.onExportAthena)

        MenuItem(self, fmenu, "Export Selected Groups to CSV",
                 "Export Selected Groups to CSV", self.onExportCSV)

        fmenu.AppendSeparator()

        MenuItem(self, fmenu, 'Show Larch Buffer\tCtrl+L',
                 'Show Larch Programming Buffer', self.onShowLarchBuffer)

        MenuItem(self, fmenu, 'Save Larch Script of History\tCtrl+H',
                 'Save Session History as Larch Script',
                 self.onSaveLarchHistory)

        if WX_DEBUG:
            MenuItem(self, fmenu, "&Inspect \tCtrl+J", " wx inspection tool ",
                     self.showInspectionTool)

        MenuItem(self, fmenu, "&Quit\tCtrl+Q", "Quit program", self.onClose)

        MenuItem(self, group_menu, "Copy This Group", "Copy This Group",
                 self.onCopyGroup)

        MenuItem(self, group_menu, "Rename This Group", "Rename This Group",
                 self.onRenameGroup)

        MenuItem(self, group_menu, "Remove Selected Groups",
                 "Remove Selected Group", self.onRemoveGroups)

        MenuItem(self, group_menu, "Merge Selected Groups",
                 "Merge Selected Groups", self.onMergeData)

        MenuItem(self, data_menu, "Deglitch Data", "Deglitch Data",
                 self.onDeglitchData)

        MenuItem(self, data_menu, "Recalibrate Energy", "Recalibrate Energy",
                 self.onEnergyCalibrateData)

        MenuItem(self, data_menu, "Smooth Data", "Smooth Data",
                 self.onSmoothData)

        MenuItem(self, data_menu, "Rebin Data", "Rebin Data", self.onRebinData)

        MenuItem(self, data_menu, "Deconvolve Data", "Deconvolution of Data",
                 self.onDeconvolveData)

        MenuItem(self, data_menu, "Correct Over-absorption",
                 "Correct Over-absorption", self.onCorrectOverAbsorptionData)

        MenuItem(self, ppeak_menu, "&Read Fit Model\tCtrl+R",
                 "Read Fit Model from File", self.onLoadFitResult)

        fsave = MenuItem(self, ppeak_menu, "Save Fit Model",
                         "Save Fit Model to File", self.onSaveFitResult)

        fexport = MenuItem(self, ppeak_menu, "Export Data and Fit",
                           "Export Data and Fit", self.onExportFitResult)

        self.afterfit_menus = (fsave, fexport)

        for m in self.afterfit_menus:
            m.Enable(False)

        self.menubar.Append(fmenu, "&File")
        self.menubar.Append(group_menu, "Groups")
        self.menubar.Append(data_menu, "Data")

        self.menubar.Append(ppeak_menu, "PreEdgePeaks")
        self.SetMenuBar(self.menubar)
        self.Bind(wx.EVT_CLOSE, self.onClose)

    def onShowLarchBuffer(self, evt=None):
        if self.larch_buffer is None:
            self.larch_buffer = LarchFrame(_larch=self.larch)
        self.larch_buffer.Show()
        self.larch_buffer.Raise()

    def onSaveLarchHistory(self, evt=None):
        wildcard = 'Larch file (*.lar)|*.lar|All files (*.*)|*.*'
        path = FileSave(self,
                        message='Save Session History as Larch Script',
                        wildcard=wildcard,
                        default_file='xas_viewer_history.lar')
        if path is not None:
            self.larch._larch.input.history.save(path, session_only=True)
            self.SetStatusText("Wrote %s" % path, 0)

    def onExportCSV(self, evt=None):
        group_ids = self.controller.filelist.GetCheckedStrings()
        savegroups = []
        groupnames = []
        for checked in group_ids:
            groupname = self.controller.file_groups[str(checked)]
            dgroup = self.controller.get_group(groupname)
            savegroups.append(dgroup)
            groupnames.append(groupname)
        if len(savegroups) < 1:
            Popup(self, "No files selected to export to CSV",
                  "No files selected")
            return

        deffile = "%s_%i.csv" % (groupname, len(groupnames))
        wcards = 'CSV Files (*.csv)|*.cvs|All files (*.*)|*.*'

        outfile = FileSave(self,
                           'Export Selected Groups to CSV File',
                           default_file=deffile,
                           wildcard=wcards)

        if outfile is None:
            return

        groups2csv(savegroups,
                   outfile,
                   x='energy',
                   y='norm',
                   _larch=self.larch)

    def onExportAthena(self, evt=None):
        groups = []
        for checked in self.controller.filelist.GetCheckedStrings():
            groups.append(self.controller.file_groups[str(checked)])

        if len(groups) < 1:
            Popup(self, "No files selected to export to Athena",
                  "No files selected")
            return
        self.save_athena_project(groups[0], groups, prompt=True)

    def onSaveProject(self, evt=None):
        groups = [gname for gname in self.controller.file_groups]
        if len(groups) < 1:
            Popup(self, "No files selected to export to Athena",
                  "No files selected")
            return
        self.save_athena_project(groups[0], groups, prompt=True)

    def save_athena_project(self, filename, grouplist, prompt=True):
        if len(grouplist) < 1:
            return
        savegroups = [self.controller.get_group(gname) for gname in grouplist]

        deffile = "%s_%i.prj" % (filename, len(grouplist))
        wcards = 'Athena Projects (*.prj)|*.prj|All files (*.*)|*.*'

        outfile = FileSave(self,
                           'Save Groups to Athena Project File',
                           default_file=deffile,
                           wildcard=wcards)

        if outfile is None:
            return

        aprj = AthenaProject(filename=outfile, _larch=self.larch)
        for label, grp in zip(grouplist, savegroups):
            aprj.add_group(grp, label=label)

        aprj.save(use_gzip=True)

    def onConfigDataProcessing(self, event=None):
        pass

    def onNewGroup(self, datagroup):
        """
        install and display a new group, as from 'copy / modify'
        Note: this is a group object, not the groupname or filename
        """
        dgroup = datagroup
        self.install_group(dgroup.groupname, dgroup.filename, overwrite=False)
        self.ShowFile(groupname=dgroup.groupname)

    def onCopyGroup(self, event=None):
        fname = self.current_filename
        if fname is None:
            fname = self.controller.filelist.GetStringSelection()
        ngroup = self.controller.copy_group(fname)
        self.onNewGroup(ngroup)

    def onRenameGroup(self, event=None):
        fname = self.current_filename = self.controller.filelist.GetStringSelection(
        )
        if fname is None:
            return
        dlg = RenameDialog(self, fname)
        res = dlg.GetResponse()
        dlg.Destroy()

        if res.ok:
            selected = []
            for checked in self.controller.filelist.GetCheckedStrings():
                selected.append(str(checked))
            if self.current_filename in selected:
                selected.remove(self.current_filename)
                selected.append(res.newname)

            groupname = self.controller.file_groups.pop(fname)
            self.controller.file_groups[res.newname] = groupname
            self.controller.filelist.rename_item(self.current_filename,
                                                 res.newname)
            dgroup = self.controller.get_group(groupname)
            dgroup.filename = self.current_filename = res.newname

            self.controller.filelist.SetCheckedStrings(selected)
            self.controller.filelist.SetStringSelection(res.newname)

    def onRemoveGroups(self, event=None):
        groups = []
        for checked in self.controller.filelist.GetCheckedStrings():
            groups.append(str(checked))
        if len(groups) < 1:
            return

        dlg = RemoveDialog(self, groups)
        res = dlg.GetResponse()
        dlg.Destroy()

        if res.ok:
            filelist = self.controller.filelist
            all_fnames = filelist.GetItems()
            for fname in groups:
                gname = self.controller.file_groups.pop(fname)
                delattr(self.controller.symtable, gname)
                all_fnames.remove(fname)

            filelist.Clear()
            for name in all_fnames:
                filelist.Append(name)

    def onMergeData(self, event=None):
        groups = []
        for checked in self.controller.filelist.GetCheckedStrings():
            groups.append(self.controller.file_groups[str(checked)])
        if len(groups) < 1:
            return

        outgroup = unique_name('merge', self.controller.file_groups)
        dlg = MergeDialog(self, groups, outgroup=outgroup)
        res = dlg.GetResponse()
        dlg.Destroy()
        if res.ok:
            fname = res.group
            gname = fix_varname(res.group.lower())
            yname = 'norm' if res.ynorm else 'mu'
            self.controller.merge_groups(groups,
                                         master=res.master,
                                         yarray=yname,
                                         outgroup=gname)
            self.install_group(gname, fname, overwrite=False)
            self.controller.filelist.SetStringSelection(fname)

    def onDeglitchData(self, event=None):
        DeglitchDialog(self, self.controller).Show()

    def onSmoothData(self, event=None):
        SmoothDataDialog(self, self.controller).Show()

    def onRebinData(self, event=None):
        RebinDataDialog(self, self.controller).Show()

    def onCorrectOverAbsorptionData(self, event=None):
        OverAbsorptionDialog(self, self.controller).Show()

    def onEnergyCalibrateData(self, event=None):
        EnergyCalibrateDialog(self, self.controller).Show()

    def onDeconvolveData(self, event=None):
        DeconvolutionDialog(self, self.controller).Show()

    def onConfigDataFitting(self, event=None):
        pass

    def showInspectionTool(self, event=None):
        app = wx.GetApp()
        app.ShowInspectionTool()

    def onAbout(self, evt):
        dlg = wx.MessageDialog(self, self._about, "About Larch XAS GUI",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def onClose(self, event):
        dlg = QuitDialog(self)
        res = dlg.GetResponse()
        dlg.Destroy()

        if not res.ok:
            return

        if res.save:
            groups = [gname for gname in self.controller.file_groups]
            if len(groups) > 0:
                self.save_athena_project(groups[0], groups, prompt=True)

        self.controller.save_config()
        self.controller.get_display().Destroy()

        if self.larch_buffer is not None:
            try:
                self.larch_buffer.Destroy()
            except:
                pass
            time.sleep(0.05)

        for nam in dir(self.larch.symtable._plotter):
            obj = getattr(self.larch.symtable._plotter, nam)
            time.sleep(0.05)
            try:
                obj.Destroy()
            except:
                pass

        for name, wid in self.subframes.items():
            if wid is not None:
                try:
                    wid.Destroy()
                except:
                    pass

        for nam in dir(self.larch.symtable._sys.wx):
            obj = getattr(self.larch.symtable._sys.wx, nam)

        self.Destroy()

    def show_subframe(self, name, frameclass, **opts):
        shown = False
        if name in self.subframes:
            try:
                self.subframes[name].Raise()
                shown = True
            except:
                del self.subframes[name]
        if not shown:
            self.subframes[name] = frameclass(self, **opts)

    def onSelectColumns(self, event=None):
        dgroup = self.controller.get_group()
        self.show_subframe('readfile',
                           ColumnDataFileFrame,
                           group=dgroup.raw,
                           last_array_sel=self.last_array_sel,
                           _larch=self.larch,
                           read_ok_cb=partial(self.onRead_OK, overwrite=True))

    def onLoadFitResult(self, event=None):
        self.nb.SetSelection(1)
        self.nb_panels[1].onLoadFitResult(event=event)

    def onSaveFitResult(self, event=None):
        self.nb_panels[1].onSaveFitResult(event=event)

    def onExportFitResult(self, event=None):
        self.nb_panels[1].onExportFitResult(event=event)

    def onReadDialog(self, event=None):
        dlg = wx.FileDialog(self,
                            message="Read Data File",
                            defaultDir=os.getcwd(),
                            wildcard=FILE_WILDCARDS,
                            style=wx.FD_OPEN | wx.FD_MULTIPLE)
        self.paths2read = []
        if dlg.ShowModal() == wx.ID_OK:
            self.paths2read = dlg.GetPaths()
        dlg.Destroy()

        if len(self.paths2read) < 1:
            return

        path = self.paths2read.pop(0)
        path = path.replace('\\', '/')
        do_read = True
        if path in self.controller.file_groups:
            do_read = (wx.ID_YES == Popup(self, "Re-read file '%s'?" % path,
                                          'Re-read file?'))
        if do_read:
            self.onRead(path)

    def onRead(self, path):
        filedir, filename = os.path.split(path)
        if self.controller.get_config('chdir_on_fileopen'):
            os.chdir(filedir)
            self.controller.set_workdir()

        # check for athena projects
        if is_athena_project(path):
            kwargs = dict(filename=path,
                          _larch=self.controller.larch,
                          read_ok_cb=self.onReadAthenaProject_OK)
            self.show_subframe('athena_import', AthenaImporter, **kwargs)
        else:
            kwargs = dict(filename=path,
                          _larch=self.larch_buffer.larchshell,
                          last_array_sel=self.last_array_sel,
                          read_ok_cb=self.onRead_OK)

            self.show_subframe('readfile', ColumnDataFileFrame, **kwargs)

    def onReadAthenaProject_OK(self, path, namelist):
        """read groups from a list of groups from an athena project file"""
        self.larch.eval(
            "_prj = read_athena('{path:s}', do_fft=False, do_bkg=False)".
            format(path=path))
        dgroup = None
        script = "{group:s} = extract_athenagroup(_prj.{prjgroup:s})"
        for gname in namelist:
            this = getattr(self.larch.symtable._prj, gname)
            gid = str(getattr(this, 'athena_id', gname))
            self.larch.eval(script.format(group=gid, prjgroup=gname))
            dgroup = self.install_group(gid, gname, process=True, plot=False)
        self.larch.eval("del _prj")

    def onRead_OK(self,
                  script,
                  path,
                  groupname=None,
                  array_sel=None,
                  overwrite=False):
        """ called when column data has been selected and is ready to be used
        overwrite: whether to overwrite the current datagroup, as when
        editing a datagroup
        """
        abort_read = False
        filedir, filename = os.path.split(path)
        if not overwrite and hasattr(self.larch.symtable, groupname):
            newname = file2groupname(filename, symtable=self.larch.symtable)
            msg = """Warning: groupname '%s' already used.
            Will use groupname '%s' instead """ % (groupname, newname)
            dlg = wx.MessageDialog(self, msg, 'Warning', wx.OK | wx.CANCEL)

            abort_read = (wx.ID_OK != dlg.ShowModal())
            dlg.Destroy()
            groupname = newname

        if abort_read:
            return
        self.larch.eval(script.format(group=groupname, path=path))
        if array_sel is not None:
            self.last_array_sel = array_sel
        self.install_group(groupname, filename, overwrite=overwrite)

        for path in self.paths2read:
            path = path.replace('\\', '/')
            filedir, filename = os.path.split(path)
            gname = file2groupname(filename, symtable=self.larch.symtable)
            self.larch.eval(script.format(group=gname, path=path))
            self.install_group(gname, filename, overwrite=True)

    def install_group(self,
                      groupname,
                      filename,
                      overwrite=False,
                      process=True,
                      plot=True):
        """add groupname / filename to list of available data groups"""
        thisgroup = getattr(self.larch.symtable, groupname)
        thisgroup.groupname = groupname
        thisgroup.filename = filename

        datatype = getattr(thisgroup, 'datatype', 'raw')
        # file /group may already exist in list
        if filename in self.controller.file_groups and not overwrite:
            for i in range(1, 101):
                ftest = "%s (%i)" % (filename, i)
                if ftest not in self.controller.file_groups:
                    filename = ftest
                    break

        if filename not in self.controller.file_groups:
            self.controller.filelist.Append(filename)
            self.controller.file_groups[filename] = groupname
        self.nb.SetSelection(0)
        self.ShowFile(groupname=groupname, process=process, plot=plot)
        self.controller.filelist.SetStringSelection(filename)
        return thisgroup
示例#8
0
class XASFrame(wx.Frame):
    _about = """Larch XAS GUI: XAS Visualization and Analysis

    Matt Newville <newville @ cars.uchicago.edu>
    """

    def __init__(self, parent=None, _larch=None, filename=None, **kws):
        wx.Frame.__init__(self,
                          parent,
                          -1,
                          size=XASVIEW_SIZE,
                          style=FRAMESTYLE)

        self.last_array_sel = {}
        self.paths2read = []

        title = "Larch XAS GUI: XAS Visualization and Analysis"

        self.larch_buffer = parent
        if not isinstance(parent, LarchFrame):
            self.larch_buffer = LarchFrame(_larch=_larch, is_standalone=False)

        self.larch_buffer.Show()
        self.larch_buffer.Raise()
        self.larch = self.larch_buffer.larchshell
        self.larch.symtable._sys.xas_viewer = Group()

        self.controller = XASController(wxparent=self, _larch=self.larch)
        self.subframes = {}
        self.plotframe = None
        self.SetTitle(title)
        self.SetSize(XASVIEW_SIZE)

        self.SetFont(Font(FONTSIZE))
        self.larch_buffer.Hide()
        self.createMainPanel()
        self.createMenus()
        self.statusbar = self.CreateStatusBar(2, style=wx.STB_DEFAULT_STYLE)
        self.statusbar.SetStatusWidths([-3, -1])
        statusbar_fields = [" ", "initializing...."]
        for i in range(len(statusbar_fields)):
            self.statusbar.SetStatusText(statusbar_fields[i], i)
            self.current_filename = filename
        self.Show()
        if filename is not None:
            wx.CallAfter(self.onRead, filename)

    def createMainPanel(self):
        display0 = wx.Display(0)
        client_area = display0.ClientArea
        xmin, ymin, xmax, ymax = client_area
        xpos = int((xmax - xmin) * 0.02) + xmin
        ypos = int((ymax - ymin) * 0.04) + ymin
        self.SetPosition((xpos, ypos))

        splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
        splitter.SetMinimumPaneSize(250)

        leftpanel = wx.Panel(splitter)
        ltop = wx.Panel(leftpanel)

        def Btn(msg, x, act):
            b = Button(ltop, msg, size=(x, 30), action=act)
            b.SetFont(Font(FONTSIZE))
            return b

        sel_none = Btn('Select None', 120, self.onSelNone)
        sel_all = Btn('Select All', 120, self.onSelAll)

        self.controller.filelist = FileCheckList(leftpanel,
                                                 select_action=self.ShowFile,
                                                 remove_action=self.RemoveFile)
        tsizer = wx.BoxSizer(wx.HORIZONTAL)
        tsizer.Add(sel_all, 1, LEFT | wx.GROW, 1)
        tsizer.Add(sel_none, 1, LEFT | wx.GROW, 1)
        pack(ltop, tsizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(ltop, 0, LEFT | wx.GROW, 1)
        sizer.Add(self.controller.filelist, 1, LEFT | wx.GROW | wx.ALL, 1)

        pack(leftpanel, sizer)

        # right hand side
        panel = wx.Panel(splitter)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self.title = SimpleText(panel, 'initializing...', size=(300, -1))
        self.title.SetFont(Font(FONTSIZE + 2))

        ir = 0
        sizer.Add(self.title, 0, LEFT | wx.GROW | wx.ALL, 1)
        self.nb = flatnotebook(panel,
                               NB_PANELS,
                               panelkws=dict(controller=self.controller),
                               on_change=self.onNBChanged)
        sizer.Add(self.nb, 1, LEFT | wx.EXPAND, 2)
        pack(panel, sizer)

        splitter.SplitVertically(leftpanel, panel, 1)
        wx.CallAfter(self.init_larch)

    def onNBChanged(self, event=None):
        callback = getattr(self.nb.GetCurrentPage(), 'onPanelExposed', None)
        if callable(callback):
            callback()

    def onSelAll(self, event=None):
        self.controller.filelist.select_all()

    def onSelNone(self, event=None):
        self.controller.filelist.select_none()

    def init_larch(self):
        self.SetStatusText('initializing Larch', 1)
        self.title.SetLabel('')

        self.controller.init_larch()

        plotframe = self.controller.get_display(stacked=False)
        xpos, ypos = self.GetPosition()
        xsiz, ysiz = self.GetSize()
        plotframe.SetPosition((xpos + xsiz + 5, ypos))
        plotframe.SetSize((600, 650))

        self.SetStatusText('ready', 1)
        self.Raise()

    def write_message(self, msg, panel=0):
        """write a message to the Status Bar"""
        self.statusbar.SetStatusText(msg, panel)

    def RemoveFile(self, fname=None, **kws):
        if fname is not None:
            s = str(fname)
            if s in self.controller.file_groups:
                group = self.controller.file_groups.pop(s)

    def ShowFile(self,
                 evt=None,
                 groupname=None,
                 process=True,
                 plot=True,
                 **kws):
        filename = None
        if evt is not None:
            filename = str(evt.GetString())

        if groupname is None and filename is not None:
            groupname = self.controller.file_groups[filename]

        if not hasattr(self.larch.symtable, groupname):
            return

        dgroup = self.controller.get_group(groupname)
        if dgroup is None:
            return

        if filename is None:
            filename = dgroup.filename
        self.title.SetLabel(filename)
        self.current_filename = filename

        self.controller.group = dgroup
        self.controller.groupname = groupname
        cur_panel = self.nb.GetCurrentPage()
        if process:
            cur_panel.fill_form(dgroup)
            cur_panel.skip_process = True
            cur_panel.process(dgroup=dgroup)
            if plot and hasattr(cur_panel, 'plot'):
                cur_panel.plot(dgroup=dgroup)
            cur_panel.skip_process = False

    def createMenus(self):
        # ppnl = self.plotpanel
        self.menubar = wx.MenuBar()
        fmenu = wx.Menu()
        group_menu = wx.Menu()
        data_menu = wx.Menu()
        # ppeak_menu = wx.Menu()
        m = {}

        MenuItem(self, fmenu, "&Open Data File\tCtrl+O", "Open Data File",
                 self.onReadDialog)

        MenuItem(self, fmenu, "&Save Project\tCtrl+S",
                 "Save Session to Project File", self.onSaveProject)

        MenuItem(self, fmenu, "Export Selected Groups to Athena Project",
                 "Export Selected Groups to Athena Project",
                 self.onExportAthena)

        MenuItem(self, fmenu, "Export Selected Groups to CSV",
                 "Export Selected Groups to CSV", self.onExportCSV)

        fmenu.AppendSeparator()

        MenuItem(self, fmenu, 'Show Larch Buffer\tCtrl+L',
                 'Show Larch Programming Buffer', self.onShowLarchBuffer)

        MenuItem(self, fmenu, 'Save Larch Script of History\tCtrl+H',
                 'Save Session History as Larch Script',
                 self.onSaveLarchHistory)

        if WX_DEBUG:
            MenuItem(self, fmenu, "&Inspect \tCtrl+J", " wx inspection tool ",
                     self.showInspectionTool)

        MenuItem(self, fmenu, "&Quit\tCtrl+Q", "Quit program", self.onClose)

        MenuItem(self, group_menu, "Copy This Group", "Copy This Group",
                 self.onCopyGroup)

        MenuItem(self, group_menu, "Rename This Group", "Rename This Group",
                 self.onRenameGroup)

        MenuItem(self, group_menu, "Remove Selected Groups",
                 "Remove Selected Group", self.onRemoveGroups)

        group_menu.AppendSeparator()

        MenuItem(self, group_menu, "Merge Selected Groups",
                 "Merge Selected Groups", self.onMergeData)

        group_menu.AppendSeparator()

        MenuItem(self, group_menu, "Freeze Selected Groups",
                 "Freeze Selected Groups", self.onFreezeGroups)

        MenuItem(self, group_menu, "UnFreeze Selected Groups",
                 "UnFreeze Selected Groups", self.onUnFreezeGroups)

        MenuItem(self, data_menu, "Deglitch Data", "Deglitch Data",
                 self.onDeglitchData)

        MenuItem(self, data_menu, "Recalibrate Energy", "Recalibrate Energy",
                 self.onEnergyCalibrateData)

        MenuItem(self, data_menu, "Smooth Data", "Smooth Data",
                 self.onSmoothData)

        MenuItem(self, data_menu, "Rebin Data", "Rebin Data", self.onRebinData)

        MenuItem(self, data_menu, "Deconvolve Data", "Deconvolution of Data",
                 self.onDeconvolveData)

        MenuItem(self, data_menu, "Correct Over-absorption",
                 "Correct Over-absorption", self.onCorrectOverAbsorptionData)

        MenuItem(self, data_menu, "Add and Subtract Sepctra",
                 "Calculations of Spectra", self.onSpectraCalc)

        self.menubar.Append(fmenu, "&File")
        self.menubar.Append(group_menu, "Groups")
        self.menubar.Append(data_menu, "Data")

        # self.menubar.Append(ppeak_menu, "PreEdgePeaks")
        self.SetMenuBar(self.menubar)
        self.Bind(wx.EVT_CLOSE, self.onClose)

    def onShowLarchBuffer(self, evt=None):
        if self.larch_buffer is None:
            self.larch_buffer = LarchFrame(_larch=self.larch,
                                           is_standalone=False)
        self.larch_buffer.Show()
        self.larch_buffer.Raise()

    def onSaveLarchHistory(self, evt=None):
        wildcard = 'Larch file (*.lar)|*.lar|All files (*.*)|*.*'
        path = FileSave(self,
                        message='Save Session History as Larch Script',
                        wildcard=wildcard,
                        default_file='xas_viewer_history.lar')
        if path is not None:
            self.larch._larch.input.history.save(path, session_only=True)
            self.write_message("Wrote history %s" % path, 0)

    def onExportCSV(self, evt=None):
        filenames = self.controller.filelist.GetCheckedStrings()
        if len(filenames) < 1:
            Popup(self, "No files selected to export to CSV",
                  "No files selected")
            return

        dlg = ExportCSVDialog(self, filenames)
        res = dlg.GetResponse()
        dlg.Destroy()
        if res.ok:
            savegroups = [self.controller.filename2group(res.master)]
            for fname in filenames:
                dgroup = self.controller.filename2group(fname)
                if dgroup not in savegroups:
                    savegroups.append(dgroup)
            groups2csv(savegroups,
                       res.filename,
                       x='energy',
                       y=res.yarray,
                       _larch=self.larch)
            self.write_message("Exported CSV file %s" % (res.filename))

    def onExportAthena(self, evt=None):
        groups = []
        for checked in self.controller.filelist.GetCheckedStrings():
            groups.append(self.controller.file_groups[str(checked)])

        if len(groups) < 1:
            Popup(self, "No files selected to export to Athena",
                  "No files selected")
            return
        self.save_athena_project(groups[0], groups, prompt=True)

    def onSaveProject(self, evt=None):
        groups = [gname for gname in self.controller.file_groups]
        if len(groups) < 1:
            Popup(self, "No files selected to export to Athena",
                  "No files selected")
            return
        self.save_athena_project(groups[0], groups, prompt=True)

    def save_athena_project(self, filename, grouplist, prompt=True):
        if len(grouplist) < 1:
            return
        savegroups = [self.controller.get_group(gname) for gname in grouplist]

        deffile = "%s_%i.prj" % (filename, len(grouplist))
        wcards = 'Athena Projects (*.prj)|*.prj|All files (*.*)|*.*'

        outfile = FileSave(self,
                           'Save Groups to Athena Project File',
                           default_file=deffile,
                           wildcard=wcards)

        if outfile is None:
            return
        aprj = AthenaProject(filename=outfile, _larch=self.larch)
        for label, grp in zip(grouplist, savegroups):
            aprj.add_group(grp)

        aprj.save(use_gzip=True)
        self.write_message("Saved project file %s" % (outfile))

    def onConfigDataProcessing(self, event=None):
        pass

    def onNewGroup(self, datagroup):
        """
        install and display a new group, as from 'copy / modify'
        Note: this is a group object, not the groupname or filename
        """
        dgroup = datagroup
        self.install_group(dgroup.groupname, dgroup.filename, overwrite=False)
        self.ShowFile(groupname=dgroup.groupname)

    def onCopyGroup(self, event=None):
        fname = self.current_filename
        if fname is None:
            fname = self.controller.filelist.GetStringSelection()
        ngroup = self.controller.copy_group(fname)
        self.onNewGroup(ngroup)

    def onRenameGroup(self, event=None):
        fname = self.current_filename = self.controller.filelist.GetStringSelection(
        )
        if fname is None:
            return
        dlg = RenameDialog(self, fname)
        res = dlg.GetResponse()
        dlg.Destroy()

        if res.ok:
            selected = []
            for checked in self.controller.filelist.GetCheckedStrings():
                selected.append(str(checked))
            if self.current_filename in selected:
                selected.remove(self.current_filename)
                selected.append(res.newname)

            groupname = self.controller.file_groups.pop(fname)
            self.controller.file_groups[res.newname] = groupname
            self.controller.filelist.rename_item(self.current_filename,
                                                 res.newname)
            dgroup = self.controller.get_group(groupname)
            dgroup.filename = self.current_filename = res.newname

            self.controller.filelist.SetCheckedStrings(selected)
            self.controller.filelist.SetStringSelection(res.newname)

    def onRemoveGroups(self, event=None):
        groups = []
        for checked in self.controller.filelist.GetCheckedStrings():
            groups.append(str(checked))
        if len(groups) < 1:
            return

        dlg = RemoveDialog(self, groups)
        res = dlg.GetResponse()
        dlg.Destroy()

        if res.ok:
            filelist = self.controller.filelist
            all_fnames = filelist.GetItems()
            for fname in groups:
                gname = self.controller.file_groups.pop(fname)
                delattr(self.controller.symtable, gname)
                all_fnames.remove(fname)

            filelist.Clear()
            for name in all_fnames:
                filelist.Append(name)

    def onFreezeGroups(self, event=None):
        self._freeze_handler(True)

    def onUnFreezeGroups(self, event=None):
        self._freeze_handler(False)

    def _freeze_handler(self, freeze):
        current_filename = self.current_filename
        reproc_group = None
        for fname in self.controller.filelist.GetCheckedStrings():
            groupname = self.controller.file_groups[str(fname)]
            dgroup = self.controller.get_group(groupname)
            if fname == current_filename:
                reproc_group = groupname
            dgroup.is_frozen = freeze
        if reproc_group is not None:
            self.ShowFile(groupname=reproc_group, process=True)

    def onMergeData(self, event=None):
        groups = OrderedDict()
        for checked in self.controller.filelist.GetCheckedStrings():
            cname = str(checked)
            groups[cname] = self.controller.file_groups[cname]
        if len(groups) < 1:
            return

        outgroup = common_startstring(list(groups.keys()))
        outgroup = "%s (merge %d)" % (outgroup, len(groups))
        outgroup = unique_name(outgroup, self.controller.file_groups)
        dlg = MergeDialog(self, list(groups.keys()), outgroup=outgroup)
        res = dlg.GetResponse()
        dlg.Destroy()
        if res.ok:
            fname = res.group
            gname = fix_varname(res.group.lower())
            master = self.controller.file_groups[res.master]
            yname = 'norm' if res.ynorm else 'mu'
            self.controller.merge_groups(list(groups.values()),
                                         master=master,
                                         yarray=yname,
                                         outgroup=gname)
            self.install_group(gname, fname, overwrite=False)
            self.controller.filelist.SetStringSelection(fname)

    def onDeglitchData(self, event=None):
        DeglitchDialog(self, self.controller).Show()

    def onSmoothData(self, event=None):
        SmoothDataDialog(self, self.controller).Show()

    def onRebinData(self, event=None):
        RebinDataDialog(self, self.controller).Show()

    def onCorrectOverAbsorptionData(self, event=None):
        OverAbsorptionDialog(self, self.controller).Show()

    def onSpectraCalc(self, event=None):
        SpectraCalcDialog(self, self.controller).Show()

    def onEnergyCalibrateData(self, event=None):
        EnergyCalibrateDialog(self, self.controller).Show()

    def onDeconvolveData(self, event=None):
        DeconvolutionDialog(self, self.controller).Show()

    def onConfigDataFitting(self, event=None):
        pass

    def showInspectionTool(self, event=None):
        app = wx.GetApp()
        app.ShowInspectionTool()

    def onAbout(self, evt):
        dlg = wx.MessageDialog(self, self._about, "About Larch XAS GUI",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def onClose(self, event):
        dlg = QuitDialog(self)
        dlg.Raise()
        dlg.SetWindowStyle(wx.STAY_ON_TOP)
        res = dlg.GetResponse()
        dlg.Destroy()
        if not res.ok:
            return

        if res.save:
            groups = [gname for gname in self.controller.file_groups]
            if len(groups) > 0:
                self.save_athena_project(groups[0], groups, prompt=True)

        self.controller.save_config()
        wx.CallAfter(self.controller.close_all_displays)

        if self.larch_buffer is not None:
            wx.CallAfter(self.larch_buffer.Destroy)

        for name, wid in self.subframes.items():
            if hasattr(wid, 'Destroy'):
                wx.CallAfter(wid.Destroy)

        self.Destroy()

    def show_subframe(self, name, frameclass, **opts):
        shown = False
        if name in self.subframes:
            try:
                self.subframes[name].Raise()
                shown = True
            except:
                del self.subframes[name]
        if not shown:
            self.subframes[name] = frameclass(self, **opts)

    def onSelectColumns(self, event=None):
        dgroup = self.controller.get_group()
        self.show_subframe('readfile',
                           ColumnDataFileFrame,
                           group=dgroup.raw,
                           last_array_sel=self.last_array_sel,
                           _larch=self.larch,
                           read_ok_cb=partial(self.onRead_OK, overwrite=True))

    def onLoadFitResult(self, event=None):
        pass
        # print("onLoadFitResult??")
        # self.nb.SetSelection(1)
        # self.nb_panels[1].onLoadFitResult(event=event)

    def onReadDialog(self, event=None):
        dlg = wx.FileDialog(self,
                            message="Read Data File",
                            defaultDir=os.getcwd(),
                            wildcard=FILE_WILDCARDS,
                            style=wx.FD_OPEN | wx.FD_MULTIPLE)
        self.paths2read = []
        if dlg.ShowModal() == wx.ID_OK:
            self.paths2read = dlg.GetPaths()
        dlg.Destroy()

        if len(self.paths2read) < 1:
            return

        path = self.paths2read.pop(0)
        path = path.replace('\\', '/')
        do_read = True
        if path in self.controller.file_groups:
            do_read = (wx.ID_YES == Popup(self, "Re-read file '%s'?" % path,
                                          'Re-read file?'))
        if do_read:
            self.onRead(path)

    def onRead(self, path):
        filedir, filename = os.path.split(os.path.abspath(path))
        if self.controller.get_config('chdir_on_fileopen'):
            os.chdir(filedir)
            self.controller.set_workdir()

        # check for athena projects
        if is_athena_project(path):
            kwargs = dict(filename=path,
                          _larch=self.controller.larch,
                          read_ok_cb=self.onReadAthenaProject_OK)
            self.show_subframe('athena_import', AthenaImporter, **kwargs)
        else:
            kwargs = dict(filename=path,
                          _larch=self.larch_buffer.larchshell,
                          last_array_sel=self.last_array_sel,
                          read_ok_cb=self.onRead_OK)

            self.show_subframe('readfile', ColumnDataFileFrame, **kwargs)

    def onReadAthenaProject_OK(self, path, namelist):
        """read groups from a list of groups from an athena project file"""
        self.larch.eval(
            "_prj = read_athena('{path:s}', do_fft=False, do_bkg=False)".
            format(path=path))
        dgroup = None
        script = "{group:s} = extract_athenagroup(_prj.{prjgroup:s})"

        cur_panel = self.nb.GetCurrentPage()
        cur_panel.skip_plotting = True
        for gname in namelist:
            cur_panel.skip_plotting = (gname == namelist[-1])
            this = getattr(self.larch.symtable._prj, gname)
            gid = str(getattr(this, 'athena_id', gname))
            if self.larch.symtable.has_group(gid):
                count, prefix = 0, gname[:3]
                while count < 1e7 and self.larch.symtable.has_group(gid):
                    gid = prefix + make_hashkey(length=7)
                    count += 1

            self.larch.eval(script.format(group=gid, prjgroup=gname))
            dgroup = self.install_group(gid, gname, process=True, plot=False)
        self.larch.eval("del _prj")
        cur_panel.skip_plotting = False

        if len(namelist) > 0:
            gname = self.controller.file_groups[namelist[0]]
            self.ShowFile(groupname=gname, process=True, plot=True)
        self.write_message("read %d datasets from %s" % (len(namelist), path))

    def onRead_OK(self,
                  script,
                  path,
                  groupname=None,
                  filename=None,
                  array_sel=None,
                  overwrite=False):
        """ called when column data has been selected and is ready to be used
        overwrite: whether to overwrite the current datagroup, as when
        editing a datagroup
        """
        if groupname is None:
            return
        abort_read = False
        filedir, real_filename = os.path.split(path)
        if filename is None:
            filename = real_filename
        if not overwrite and hasattr(self.larch.symtable, groupname):
            groupname = file2groupname(real_filename,
                                       symtable=self.larch.symtable)

        if abort_read:
            return

        self.larch.eval(script.format(group=groupname, path=path))
        if array_sel is not None:
            self.last_array_sel = array_sel
        self.install_group(groupname, filename, overwrite=overwrite)

        # check if rebin is needed
        thisgroup = getattr(self.larch.symtable, groupname)

        do_rebin = False
        if thisgroup.datatype == 'xas':
            try:
                en = thisgroup.energy
            except:
                do_rebin = True
                en = thisgroup.energy = thisgroup.xdat
            # test for rebinning:
            #  too many data points
            #  unsorted energy data or data in angle
            #  too fine a step size at the end of the data range
            if (len(en) > 1200 or any(np.diff(en) < 0)
                    or ((max(en) - min(en)) > 300 and
                        (np.diff(en[-50:]).mean() < 0.75))):
                msg = """This dataset may need to be rebinned.
                Rebin now?"""
                dlg = wx.MessageDialog(self, msg, 'Warning', wx.YES | wx.NO)
                do_rebin = (wx.ID_YES == dlg.ShowModal())
                dlg.Destroy()

        for path in self.paths2read:
            path = path.replace('\\', '/')
            filedir, real_filename = os.path.split(path)
            gname = file2groupname(real_filename, symtable=self.larch.symtable)
            self.larch.eval(script.format(group=gname, path=path))
            self.install_group(gname, real_filename, overwrite=overwrite)

        self.write_message("read %s" % (real_filename))

        if do_rebin:
            RebinDataDialog(self, self.controller).Show()

    def install_group(self,
                      groupname,
                      filename,
                      overwrite=False,
                      process=True,
                      rebin=False,
                      plot=True):
        """add groupname / filename to list of available data groups"""

        thisgroup = getattr(self.larch.symtable, groupname)

        datatype = getattr(thisgroup, 'datatype', 'raw')
        # file /group may already exist in list
        if filename in self.controller.file_groups and not overwrite:
            fbase, i = filename, 0
            while i < 10000 and filename in self.controller.file_groups:
                filename = "%s_%d" % (fbase, i)
                i += 1

        cmds = [
            "%s.groupname = '%s'" % (groupname, groupname),
            "%s.filename = '%s'" % (groupname, filename)
        ]

        self.larch.eval('\n'.join(cmds))

        self.controller.filelist.Append(filename)
        self.controller.file_groups[filename] = groupname

        self.nb.SetSelection(0)
        self.ShowFile(groupname=groupname, process=process, plot=plot)
        self.controller.filelist.SetStringSelection(filename)
        return thisgroup
示例#9
0
    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)
示例#10
0
    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
示例#11
0
    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
示例#12
0
    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()
示例#13
0
    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
示例#14
0
    def build(self):
        sizer = wx.GridBagSizer(10, 5)
        sizer.SetVGap(5)
        sizer.SetHGap(5)

        panel = scrolled.ScrolledPanel(self)
        self.SetMinSize((675, 600))
        self.colors = GUIColors()

        # title row
        self.wids = wids = {}
        title = SimpleText(panel,
                           'Linear Combination Results',
                           font=Font(12),
                           colour=self.colors.title,
                           style=LCEN)

        wids['plot_one'] = Button(panel,
                                  'Plot This Fit',
                                  size=(150, -1),
                                  action=self.onPlotOne)
        wids['plot_sel'] = Button(panel,
                                  'Plot top N Fits',
                                  size=(150, -1),
                                  action=self.onPlotSel)

        wids['plot_ntitle'] = SimpleText(panel, 'N fits to plot: ')

        wids['plot_nchoice'] = Choice(panel,
                                      size=(100, -1),
                                      choices=['%d' % i for i in range(1, 21)])
        wids['plot_nchoice'].SetStringSelection('5')

        wids['data_title'] = SimpleText(panel,
                                        '<--> ',
                                        font=Font(12),
                                        colour=self.colors.title,
                                        style=LCEN)
        wids['nfits_title'] = SimpleText(panel, 'showing top 5 fits')

        irow = 0
        sizer.Add(title, (irow, 0), (1, 2), LCEN)
        sizer.Add(wids['data_title'], (irow, 2), (1, 2), LCEN)

        irow += 1
        sizer.Add(wids['nfits_title'], (irow, 0), (1, 4), LCEN)

        irow += 1
        sizer.Add(self.wids['plot_one'], (irow, 0), (1, 1), LCEN)
        sizer.Add(self.wids['plot_sel'], (irow, 1), (1, 1), LCEN)
        sizer.Add(self.wids['plot_ntitle'], (irow, 2), (1, 1), LCEN)
        sizer.Add(self.wids['plot_nchoice'], (irow, 3), (1, 1), LCEN)

        irow += 1
        self.wids['paramstitle'] = SimpleText(panel,
                                              '[[Parameters]]',
                                              font=Font(12),
                                              colour=self.colors.title,
                                              style=LCEN)
        sizer.Add(self.wids['paramstitle'], (irow, 0), (1, 4), LCEN)

        pview = self.wids['params'] = dv.DataViewListCtrl(panel, style=DVSTYLE)
        pview.SetMinSize((675, 200))
        pview.AppendTextColumn(' Parameter ', width=250)
        pview.AppendTextColumn(' Best-Fit Value', width=150)
        pview.AppendTextColumn(' Uncertainty ', width=150)
        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), (1, 4), LCEN)

        irow += 1
        sizer.Add(HLine(panel, size=(675, 3)), (irow, 0), (1, 4), LCEN)

        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=60)
        sview.AppendTextColumn(' N_Data', width=60)
        sview.AppendTextColumn(' N_eval', width=60)
        sview.AppendTextColumn(u' \u03c7\u00B2', width=100)
        sview.AppendTextColumn(u' \u03c7\u00B2_reduced', width=100)
        sview.AppendTextColumn(' Akaike Info', width=100)
        sview.AppendTextColumn(' Bayesian Info', width=100)

        for col in range(8):
            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(12),
                           colour=self.colors.title,
                           style=LCEN)
        sizer.Add(title, (irow, 0), (1, 4), LCEN)

        irow += 1
        sizer.Add(sview, (irow, 0), (1, 4), LCEN)

        irow += 1
        sizer.Add(HLine(panel, size=(675, 3)), (irow, 0), (1, 4), LCEN)

        irow += 1
        title = SimpleText(panel,
                           '[[Weights]]',
                           font=Font(12),
                           colour=self.colors.title,
                           style=LCEN)
        sizer.Add(title, (irow, 0), (1, 4), LCEN)
        self.wids['weightspanel'] = ppan = wx.Panel(self)

        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), LCEN)

        irow += 1
        sizer.Add(HLine(panel, size=(675, 3)), (irow, 0), (1, 4), LCEN)

        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()
示例#15
0
    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)
示例#16
0
    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))
示例#17
0
 def SLabel(label, size=(80, -1), **kws):
     return  SimpleText(panel, label,
                        size=size, style=wx.ALIGN_LEFT, **kws)
示例#18
0
    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
示例#19
0
    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)
示例#20
0
    def build_display(self):
        titleopts = dict(font=Font(12), colour='#AA0000')
        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=(150, -1),
                          action=self.onPlotOne)

        plot_sel = Button(panel,
                          'Plot Selected Groups',
                          size=(150, -1),
                          action=self.onPlotSel)

        saveconf = Button(panel,
                          'Save as Default Settings',
                          size=(200, -1),
                          action=self.onSaveConfigBtn)

        def FloatSpinWithPin(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(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 = FloatSpinWithPin('bkg_kmin', value=0, **opts)

        bkg_kmax = FloatSpinWithPin('bkg_kmax', value=20, **opts)

        fft_kmin = FloatSpinWithPin('fft_kmin', value=0, **opts)

        fft_kmax = FloatSpinWithPin('fft_kmax', value=20, **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=(125, -1))

        def add_text(text, dcol=1, newrow=True):
            panel.Add(SimpleText(panel, text), dcol=dcol, newrow=newrow)

        panel.Add(SimpleText(panel, ' EXAFS Processing', **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', **titleopts),
                  dcol=2,
                  newrow=True)

        panel.Add(Button(panel,
                         'Copy To Selected Groups',
                         size=(175, -1),
                         action=partial(self.onCopyParam, 'bkg')),
                  dcol=2)

        add_text('R bkg: ')
        panel.Add(wids['rbkg'])

        add_text('E0: ', newrow=False)
        panel.Add(wids['e0'])

        add_text('k min: ')
        panel.Add(bkg_kmin)
        add_text('k max:', newrow=False)
        panel.Add(bkg_kmax)

        add_text('kweight: ', newrow=True)
        panel.Add(wids['bkg_kweight'], dcol=1)

        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(HLine(panel, size=(500, 3)), dcol=6, newrow=True)

        panel.Add(SimpleText(panel, ' Fourier transform', **titleopts),
                  dcol=2,
                  newrow=True)

        panel.Add(Button(panel,
                         'Copy to Selected Groups',
                         size=(175, -1),
                         action=partial(self.onCopyParam, 'fft')),
                  dcol=2)

        panel.Add(SimpleText(panel, 'k min: '), newrow=True)
        panel.Add(fft_kmin)

        panel.Add(SimpleText(panel, 'k max:'))
        panel.Add(fft_kmax)

        panel.Add(SimpleText(panel, 'k weight : '), newrow=True)
        panel.Add(wids['fft_kweight'])

        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(HLine(panel, size=(500, 3)), dcol=6, newrow=True)

        panel.Add(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
示例#21
0
 def add_text(self, text, dcol=1, newrow=True):
     self.panel.Add(SimpleText(self.panel, text), dcol=dcol, newrow=newrow)
示例#22
0
    def build(self):
        sizer = wx.GridBagSizer(10, 5)
        sizer.SetVGap(5)
        sizer.SetHGap(5)

        panel = scrolled.ScrolledPanel(self)
        self.SetMinSize((600, 450))
        self.colors = GUIColors()

        # title row
        self.wids = wids = {}
        title = SimpleText(panel, 'Fit Results',  font=Font(12),
                           colour=self.colors.title, style=LCEN)

        wids['data_title'] = SimpleText(panel, '< > ',  font=Font(12),
                                             colour=self.colors.title, style=LCEN)

        wids['hist_info'] = SimpleText(panel, ' ___ ',  font=Font(12),
                                       colour=self.colors.title, style=LCEN)

        sizer.Add(title,              (0, 0), (1, 2), LCEN)
        sizer.Add(wids['data_title'], (0, 2), (1, 2), LCEN)
        sizer.Add(wids['hist_info'],  (0, 4), (1, 2), LCEN)

        irow = 1
        wids['model_desc'] = SimpleText(panel, '<Model>',  font=Font(12),
                                        size=(550, 75), style=LCEN)
        sizer.Add(wids['model_desc'],  (irow, 0), (1, 6), LCEN)

        irow += 1
        sizer.Add(HLine(panel, size=(400, 3)), (irow, 0), (1, 5), LCEN)

        irow += 1
        title = SimpleText(panel, '[[Fit Statistics]]',  font=Font(12),
                           colour=self.colors.title, style=LCEN)
        sizer.Add(title, (irow, 0), (1, 4), LCEN)

        for label, attr in (('Fit method', 'method'),
                            ('# Fit Evaluations', 'nfev'),
                            ('# Data Points', 'ndata'),
                            ('# Fit Variables', 'nvarys'),
                            ('# Free Points', 'nfree'),
                            ('Chi-square', 'chisqr'),
                            ('Reduced Chi-square', 'redchi'),
                            ('Akaike Info Criteria', 'aic'),
                            ('Bayesian Info Criteria', 'bic')):
            irow += 1
            wids[attr] = SimpleText(panel, '?')
            sizer.Add(SimpleText(panel, " %s = " % label),  (irow, 0), (1, 1), LCEN)
            sizer.Add(wids[attr],                           (irow, 1), (1, 1), LCEN)

        irow += 1
        sizer.Add(HLine(panel, size=(400, 3)), (irow, 0), (1, 5), LCEN)

        irow += 1
        title = SimpleText(panel, '[[Variables]]',  font=Font(12),
                           colour=self.colors.title, style=LCEN)
        sizer.Add(title, (irow, 0), (1, 1), LCEN)

        self.wids['copy_params'] = Button(panel, 'Update Model with Best Fit Values',
                                          size=(250, -1), action=self.onCopyParams)

        sizer.Add(self.wids['copy_params'], (irow, 1), (1, 3), LCEN)

        dvstyle = dv.DV_SINGLE|dv.DV_VERT_RULES|dv.DV_ROW_LINES
        pview = self.wids['params'] = dv.DataViewListCtrl(panel, style=dvstyle)
        self.wids['paramsdata'] = []
        pview.AppendTextColumn('Parameter',         width=150)
        pview.AppendTextColumn('Best-Fit Value',    width=100)
        pview.AppendTextColumn('Standard Error',    width=100)
        pview.AppendTextColumn('Info ',             width=275)

        for col in (0, 1, 2, 3):
            this = pview.Columns[col]
            isort, align = True, wx.ALIGN_LEFT
            if col in (1, 2):
                isort, align = False, wx.ALIGN_RIGHT
            this.Sortable = isort
            this.Alignment = this.Renderer.Alignment = align

        pview.SetMinSize((650, 200))
        pview.Bind(dv.EVT_DATAVIEW_SELECTION_CHANGED, self.onSelectParameter)

        irow += 1
        sizer.Add(pview, (irow, 0), (1, 5), LCEN)

        irow += 1
        sizer.Add(HLine(panel, size=(400, 3)), (irow, 0), (1, 5), LCEN)

        irow += 1
        title = SimpleText(panel, '[[Correlations]]',  font=Font(12),
                           colour=self.colors.title, style=LCEN)

        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=(60, -1),
                                            digits=3, increment=0.1)

        ctitle = SimpleText(panel, 'minimum correlation: ')
        sizer.Add(title,  (irow, 0), (1, 1), LCEN)
        sizer.Add(ctitle, (irow, 1), (1, 1), LCEN)
        sizer.Add(self.wids['min_correl'], (irow, 2), (1, 1), LCEN)
        sizer.Add(self.wids['all_correl'], (irow, 3), (1, 1), LCEN)

        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=100)

        for col in (0, 1, 2):
            this = cview.Columns[col]
            isort, align = True, wx.ALIGN_LEFT
            if col == 1:
                isort = False
            if col == 2:
                align = wx.ALIGN_RIGHT
            this.Sortable = isort
            this.Alignment = this.Renderer.Alignment = align
        cview.SetMinSize((450, 200))

        irow += 1
        sizer.Add(cview, (irow, 0), (1, 5), LCEN)
        irow += 1
        sizer.Add(HLine(panel, size=(400, 3)), (irow, 0), (1, 5), LCEN)

        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()
示例#23
0
    def createMainPanel(self):

        display0 = wx.Display(0)
        client_area = display0.ClientArea
        xmin, ymin, xmax, ymax = client_area
        xpos = int((xmax - xmin) * 0.02) + xmin
        ypos = int((ymax - ymin) * 0.04) + ymin
        self.SetPosition((xpos, ypos))

        splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
        splitter.SetMinimumPaneSize(250)

        leftpanel = wx.Panel(splitter)
        ltop = wx.Panel(leftpanel)

        def Btn(msg, x, act):
            b = Button(ltop, msg, size=(x, 30), action=act)
            b.SetFont(Font(FONTSIZE))
            return b

        sel_none = Btn('Select None', 120, self.onSelNone)
        sel_all = Btn('Select All', 120, self.onSelAll)
        self.controller.filelist = FileCheckList(
            leftpanel,
            # main=self,
            select_action=self.ShowFile,
            remove_action=self.RemoveFile)

        tsizer = wx.BoxSizer(wx.HORIZONTAL)
        tsizer.Add(sel_all, 1, LCEN | wx.GROW, 1)
        tsizer.Add(sel_none, 1, LCEN | wx.GROW, 1)
        pack(ltop, tsizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(ltop, 0, LCEN | wx.GROW, 1)
        sizer.Add(self.controller.filelist, 1, LCEN | wx.GROW | wx.ALL, 1)

        pack(leftpanel, sizer)

        # right hand side
        panel = wx.Panel(splitter)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self.title = SimpleText(panel, 'initializing...', size=(300, -1))
        self.title.SetFont(Font(FONTSIZE + 1))

        ir = 0
        sizer.Add(self.title, 0, LCEN | wx.GROW | wx.ALL, 1)

        self.nb = flat_nb.FlatNotebook(panel, -1, agwStyle=FNB_STYLE)

        self.nb.SetTabAreaColour(wx.Colour(250, 250, 250))
        self.nb.SetActiveTabColour(wx.Colour(254, 254, 195))

        self.nb.SetNonActiveTabTextColour(wx.Colour(10, 10, 128))
        self.nb.SetActiveTabTextColour(wx.Colour(128, 0, 0))

        self.nb_panels = []
        for name, creator in NB_PANELS:
            _panel = creator(parent=self, controller=self.controller)
            self.nb.AddPage(_panel, " %s " % name, True)
            self.nb_panels.append(_panel)

        sizer.Add(self.nb, 1, LCEN | wx.EXPAND, 2)
        self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNBChanged)
        self.nb.SetSelection(0)

        pack(panel, sizer)

        splitter.SplitVertically(leftpanel, panel, 1)
        wx.CallAfter(self.init_larch)
示例#24
0
    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()