コード例 #1
0
ファイル: StageConf.py プロジェクト: pluflou/epicsapps
    def _process_data(self):
        for sect, opts in conf_sects.items():
            if not self.cp.has_section(sect):
                # print 'skipping section ' ,sect
                continue
            bools = opts.get('bools', [])
            floats = opts.get('floats', [])
            ints = opts.get('ints', [])
            thissect = {}
            is_ordered = False
            if 'ordered' in opts:
                is_ordered = True

            for opt in self.cp.options(sect):
                get = self.cp.get
                if opt in bools:
                    get = self.cp.getboolean
                elif opt in floats:
                    get = self.cp.getfloat
                elif opt in ints:
                    get = self.cp.getint
                val = get(sect, opt)
                if is_ordered and '||' in val:
                    nam, val = val.split('||', 1)
                    opt = opt.strip()
                    val = nam, val.strip()
                thissect[opt] = val
            self.config[sect] = thissect

        if 'positions' in self.config:
            out = OrderedDict()
            poskeys = list(self.config['positions'].keys())
            poskeys.sort()
            for key in poskeys:
                name, val = self.config['positions'][key]
                name = name.strip()
                img, posval = val.strip().split('||')
                pos = [float(i) for i in posval.split(',')]
                out[name] = dict(image=img.strip(), position=pos)
            self.config['positions'] = out

        if 'stages' in self.config:
            out = OrderedDict()
            skeys = list(self.config['stages'].keys())
            skeys.sort()
            for key in skeys:
                name, val = self.config['stages'][key]
                name = name.strip()
                label, desc, sign = val.split('||')
                out[name] = dict(label=label.strip(),
                                 desc=desc.strip(),
                                 sign=int(sign))
            self.config['stages'] = out
            self.nstages = len(out)
コード例 #2
0
ファイル: instrumentpanel.py プロジェクト: guduan/epicsapps
    def __init__(self, parent, inst, db=None, writer=None,
                 pvlist=None, size=(-1, -1)):
        self.last_draw = 0
        self.inst = inst
        self.pvlist = pvlist
        self.db   = db
        self.write_message = writer
        self.pvs  = {}
        self.pv_components  = OrderedDict()

        wx.Panel.__init__(self, parent, size=size)

        #for p in self.db.get_ordered_instpvs(inst):
        #    self.add_pv(p.pv.name)


        self.colors = colors = GUIColors()
        self.parent = parent
        self.SetFont(parent.GetFont())
        titlefont  = self.GetFont()
        titlefont.PointSize += 2
        titlefont.SetWeight(wx.BOLD)

        splitter = wx.SplitterWindow(self, -1,
                                     style=wx.SP_3D|wx.SP_BORDER|wx.SP_LIVE_UPDATE)

        rpanel = wx.Panel(splitter, style=wx.BORDER_SUNKEN, size=(-1, 225))
        self.leftpanel = wx.Panel(splitter, style=wx.BORDER_SUNKEN, size=(-1,325))

        # self.leftsizer = wx.GridBagSizer(12, 4)
        self.leftsizer = wx.BoxSizer(wx.VERTICAL)

        splitter.SetMinimumPaneSize(225)

        toprow = wx.Panel(self.leftpanel)
        self.inst_title = SimpleText(toprow,  ' %s ' % inst.name,
                                     font=titlefont,
                                     colour=colors.title,
                                     minsize=(150, -1),
                                     style=wx.ALIGN_LEFT|wx.ALIGN_BOTTOM)


        self.pos_name =  wx.TextCtrl(toprow, value="", size=(250, 25),
                                     style= wx.TE_PROCESS_ENTER)
        self.pos_name.Bind(wx.EVT_TEXT_ENTER, self.onSavePosition)

        topsizer = wx.BoxSizer(wx.HORIZONTAL)
        topsizer.Add(self.inst_title, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL, 1)
        topsizer.Add(SimpleText(toprow, 'Save Current Position:',
                                minsize=(180, -1),
                                style=wx.ALIGN_CENTER), 1,
                     wx.ALIGN_CENTER_VERTICAL|wx.ALL, 1)

        topsizer.Add(self.pos_name, 0,
                     wx.GROW|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 1)

        pack(toprow, topsizer)
        self.toprow = toprow

        # start a timer to check for when to fill in PV panels
        timer_id = wx.NewId()
        self.conn_timer = wx.Timer(self)
        self.puttimer = wx.Timer(self)
        self.etimer_count = 0
        self.etimer_poll = 25

        # self.Bind(wx.EVT_TIMER, self.OnConnectTimer, self.etimer)
        self.Bind(wx.EVT_TIMER, self.OnConn_Timer, self.conn_timer)

        self.Bind(wx.EVT_TIMER, self.OnPutTimer, self.puttimer)

        rsizer = wx.BoxSizer(wx.VERTICAL)
        btn_goto = add_button(rpanel, "Go To", size=(70, -1),
                              action=self.OnMove)
        btn_show = add_button(rpanel, "Show", size=(70, -1),
                              action=self.OnShowPos)
        btn_erase = add_button(rpanel, "Erase",  size=(70, -1),
                               action=self.onErase)

        brow = wx.BoxSizer(wx.HORIZONTAL)
        brow.Add(btn_goto,   0, ALL_EXP|wx.ALIGN_LEFT, 1)
        brow.Add(btn_show,  0, ALL_EXP|wx.ALIGN_LEFT, 1)
        brow.Add(btn_erase,  0, ALL_EXP|wx.ALIGN_LEFT, 1)

        self.pos_list  = wx.ListBox(rpanel, size=(225, -1))
        self.pos_list.SetBackgroundColour((230, 230, 230))
        self.pos_list.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick)
        self.pos_list.Bind(wx.EVT_LISTBOX, self.onPosSelect)
        self.pos_list.Bind(wx.EVT_LEFT_DCLICK, self.OnMove)

        self.pos_list.Clear()
        for pos in inst.positions:
            self.pos_list.Append(pos.name)

        rsizer.Add(brow,          0, wx.ALIGN_LEFT|wx.ALL)
        rsizer.Add(self.pos_list, 1, wx.EXPAND|wx.ALIGN_CENTER, 1)
        pack(rpanel, rsizer)
        self.pos_list.Disable()

        splitter.SplitVertically(self.leftpanel, rpanel, -150)

        self.leftpanel.SetMinSize((750, 150))
        rpanel.SetMinSize((150, -1))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.GROW|wx.ALL, 0)
        pack(self, sizer)
        self.conn_timer_t0 = time.time()        
        self.conn_timer.Start(1)
コード例 #3
0
ファイル: instrumentpanel.py プロジェクト: guduan/epicsapps
class InstrumentPanel(wx.Panel):
    """ create Panel for an instrument"""
    def __init__(self, parent, inst, db=None, writer=None,
                 pvlist=None, size=(-1, -1)):
        self.last_draw = 0
        self.inst = inst
        self.pvlist = pvlist
        self.db   = db
        self.write_message = writer
        self.pvs  = {}
        self.pv_components  = OrderedDict()

        wx.Panel.__init__(self, parent, size=size)

        #for p in self.db.get_ordered_instpvs(inst):
        #    self.add_pv(p.pv.name)


        self.colors = colors = GUIColors()
        self.parent = parent
        self.SetFont(parent.GetFont())
        titlefont  = self.GetFont()
        titlefont.PointSize += 2
        titlefont.SetWeight(wx.BOLD)

        splitter = wx.SplitterWindow(self, -1,
                                     style=wx.SP_3D|wx.SP_BORDER|wx.SP_LIVE_UPDATE)

        rpanel = wx.Panel(splitter, style=wx.BORDER_SUNKEN, size=(-1, 225))
        self.leftpanel = wx.Panel(splitter, style=wx.BORDER_SUNKEN, size=(-1,325))

        # self.leftsizer = wx.GridBagSizer(12, 4)
        self.leftsizer = wx.BoxSizer(wx.VERTICAL)

        splitter.SetMinimumPaneSize(225)

        toprow = wx.Panel(self.leftpanel)
        self.inst_title = SimpleText(toprow,  ' %s ' % inst.name,
                                     font=titlefont,
                                     colour=colors.title,
                                     minsize=(150, -1),
                                     style=wx.ALIGN_LEFT|wx.ALIGN_BOTTOM)


        self.pos_name =  wx.TextCtrl(toprow, value="", size=(250, 25),
                                     style= wx.TE_PROCESS_ENTER)
        self.pos_name.Bind(wx.EVT_TEXT_ENTER, self.onSavePosition)

        topsizer = wx.BoxSizer(wx.HORIZONTAL)
        topsizer.Add(self.inst_title, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL, 1)
        topsizer.Add(SimpleText(toprow, 'Save Current Position:',
                                minsize=(180, -1),
                                style=wx.ALIGN_CENTER), 1,
                     wx.ALIGN_CENTER_VERTICAL|wx.ALL, 1)

        topsizer.Add(self.pos_name, 0,
                     wx.GROW|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 1)

        pack(toprow, topsizer)
        self.toprow = toprow

        # start a timer to check for when to fill in PV panels
        timer_id = wx.NewId()
        self.conn_timer = wx.Timer(self)
        self.puttimer = wx.Timer(self)
        self.etimer_count = 0
        self.etimer_poll = 25

        # self.Bind(wx.EVT_TIMER, self.OnConnectTimer, self.etimer)
        self.Bind(wx.EVT_TIMER, self.OnConn_Timer, self.conn_timer)

        self.Bind(wx.EVT_TIMER, self.OnPutTimer, self.puttimer)

        rsizer = wx.BoxSizer(wx.VERTICAL)
        btn_goto = add_button(rpanel, "Go To", size=(70, -1),
                              action=self.OnMove)
        btn_show = add_button(rpanel, "Show", size=(70, -1),
                              action=self.OnShowPos)
        btn_erase = add_button(rpanel, "Erase",  size=(70, -1),
                               action=self.onErase)

        brow = wx.BoxSizer(wx.HORIZONTAL)
        brow.Add(btn_goto,   0, ALL_EXP|wx.ALIGN_LEFT, 1)
        brow.Add(btn_show,  0, ALL_EXP|wx.ALIGN_LEFT, 1)
        brow.Add(btn_erase,  0, ALL_EXP|wx.ALIGN_LEFT, 1)

        self.pos_list  = wx.ListBox(rpanel, size=(225, -1))
        self.pos_list.SetBackgroundColour((230, 230, 230))
        self.pos_list.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick)
        self.pos_list.Bind(wx.EVT_LISTBOX, self.onPosSelect)
        self.pos_list.Bind(wx.EVT_LEFT_DCLICK, self.OnMove)

        self.pos_list.Clear()
        for pos in inst.positions:
            self.pos_list.Append(pos.name)

        rsizer.Add(brow,          0, wx.ALIGN_LEFT|wx.ALL)
        rsizer.Add(self.pos_list, 1, wx.EXPAND|wx.ALIGN_CENTER, 1)
        pack(rpanel, rsizer)
        self.pos_list.Disable()

        splitter.SplitVertically(self.leftpanel, rpanel, -150)

        self.leftpanel.SetMinSize((750, 150))
        rpanel.SetMinSize((150, -1))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.GROW|wx.ALL, 0)
        pack(self, sizer)
        self.conn_timer_t0 = time.time()        
        self.conn_timer.Start(1)

    def undisplay_pv(self, pvname):
        "remove pv from display"
        if pvname in self.pv_components:
            self.pv_components.pop(pvname)
            self.redraw_leftpanel()

    @EpicsFunction
    def redraw_leftpanel(self, force=False):
        """ redraws the left panel """
        # print 'redraw leftpanel ', self.inst, (time.time() - self.last_draw)
        if (time.time() - self.last_draw) < 0.5:
            return

        self.Freeze()
        self.Hide()
        self.leftsizer.Clear()

        self.leftsizer.Add(self.toprow, 0, wx.ALIGN_LEFT|wx.TOP, 2)

        current_comps = [self.toprow]
        pvcomps = list(self.pv_components.items())

        # print 'redraw leftpanel: ', time.ctime() #, pvcomps

        skip = []
        for icomp, val in enumerate(pvcomps):
            pvname, comp = val
            connected, pvtype, pv = comp
            grow = 0
            panel = None
            if pvtype == 'motor':
                try:
                    t0 = time.time()
                    panel = MotorPanel(self.leftpanel, pvname)
                except PyDeadObjectError:
                    pass
            elif pv is not None and hasattr(pv, 'pvname') and pv.pvname not in skip:
                panel = wx.Panel(self.leftpanel)
                sizer = wx.BoxSizer(wx.HORIZONTAL)

                label = SimpleText(panel, '  %s' % pvname,
                                   colour=self.colors.pvname,
                                   minsize=(180,-1), style=wx.ALIGN_LEFT)

                if pvtype == 'enum':
                    ctrl = PVEnumChoice(panel, pv=pv, size=(120, -1))
                elif pvtype in ('string', 'unicode'):
                    ctrl = PVTextCtrl(panel, pv=pv, size=(120, -1))
                else:
                    ctrl = PVFloatCtrl(panel, pv=pv, size=(120, -1))

                current_comps.append(ctrl)
                current_comps.append(label)

                sizer.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2)
                sizer.Add(ctrl,  0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2)

                if (pvtype != 'motor' and icomp < len(pvcomps)-1 and
                    pvcomps[icomp+1][1][1] != 'motor'): #  and False):
                    conn, pvtype2, pv2 = pvcomps[icomp+1][1]
                    skip.append(pv2.pvname)

                    l2 = SimpleText(panel, '  %s' % pv2.pvname,
                                    colour=self.colors.pvname,
                                    minsize=(180,-1), style=wx.ALIGN_LEFT)
                    if pvtype2 == 'enum':
                        c2 = PVEnumChoice(panel, pv=pv2, size=(120, -1))
                    elif pvtype2 in ('string', 'unicode'):
                        c2 = PVTextCtrl(panel, pv=pv2, size=(120, -1))
                    else:
                        c2 = PVFloatCtrl(panel, pv=pv2, size=(120, -1))

                    sizer.Add(l2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2)
                    sizer.Add(c2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2)
                    current_comps.append(c2)
                    current_comps.append(l2)
                pack(panel, sizer)

            if panel is not None:
                current_comps.append(panel)
                self.leftsizer.Add(panel, 0,  wx.ALIGN_LEFT|wx.TOP|wx.ALL|wx.GROW, 1)

        pack(self.leftpanel, self.leftsizer)

        for wid in self.leftpanel.Children:
            if wid not in current_comps and wid != self.toprow:
                try:
                    time.sleep(0.010)
                    wid.Destroy()
                except PyDeadObjectError:
                    pass

        self.Refresh()
        self.Layout()
        self.Thaw()
        self.Show()
        self.pos_list.SetBackgroundColour(wx.WHITE)
        self.pos_list.Enable()
        self.last_draw = time.time()

    def add_pv(self, pvname):
        """add a PV to the left panel"""
        pvname = normalize_pvname(pvname)
        # print 'Panel AddPV ', pvname
        self.pv_components[pvname] = (False, None, None)
        db_pv = self.db.get_pv(pvname)
        # print 'Instrument Panel Add PV ', pvname , db_pv , db_pv.pvtype
        if db_pv.pvtype is None:
            print 'Return because no pvtype?' , pvname, db_pv
            return
        if db_pv.pvtype.name == 'motor':
            idot = pvname.find('.')
            for ext in MOTOR_FIELDS:
                self.pvlist.connect_pv('%s%s' % (pvname[:idot], ext))
        self.PV_Panel(pvname)
        self.conn_timer_t0 = time.time()        
        self.last_draw = 0.0
        self.conn_timer.Start(0.5)

    def write(self, msg, status='normal'):
        if self.write_message is None:
            return
        self.write_message(msg, status=status)

    def OnPutTimer(self, evt=None):
        """Timer Event for GoTo to look if move is complete."""
        if self.db.restore_complete():
            self.puttimer.Stop()

    def OnConnectTimer(self, evt=None):
        """Timer Event: look for uncompleted PV panels
        and try to create them ...
        """
        if all([comp[0] for comp in self.pv_components.values()]): # "all connected"
            # self.etimer.Stop()
            self.conn_timer.Stop()
            self.redraw_leftpanel()
            # return
        # if we've done 20 rounds, there are probably
        # really unconnected PVs -- let's slow down.
        if (time.time() - self.conn_timer_t0) > 15:
            self.conn_timer.Stop()
            
    def OnConn_Timer(self, evt=None):
        for pvname in self.pv_components:
            self.PV_Panel(pvname)

        if (all([comp[0] for comp in self.pv_components.values()]) or # "all connected"
            (time.time() - self.conn_timer_t0) > 15):  # timeout
            self.redraw_leftpanel()
            self.last_draw = 0
            self.conn_timer.Stop()

    def PV_Panel(self, pvname): # , panel, sizer, current_wid=None):
        """ try to create a PV Panel for the given pv
        returns quickly for an unconnected PV, to be tried later
        by the timer"""
        pvname = str(pvname)

        if '.' not in pvname:
            pvname = '%s.VAL' % pvname

        if pvname not in self.pvlist.pvs:
            self.pvlist.connect_pv(pvname)

        if pvname in self.pvlist.pvs:
            pv = self.pvlist.pvs[pvname]
        else:
            return

        # return if not connected
        if not pv.connected:
            return

        if pvname not in self.pv_components:
            return

        # pv.get_ctrlvars()
        pvtype = self.pv_components[pvname][1]
        if pvtype is None:
            db_pv = self.db.get_pv(pvname)
            try:
                pvtype = str(db_pv.pvtype.name)
            except AttributeError:
                pass

        #   pvtype  = get_pvtypes(pv)[0]
        self.pv_components[pvname] = (True, pvtype, pv)

        self.pvs[pvname] = pv            
        # self.db.set_pvtype(pvname, pvtype)

    @EpicsFunction
    def save_current_position(self, posname):
        values = {}
        for pv in self.pvs.values():
            values[pv.pvname] = pv.get(as_string=True)
        self.db.save_position(posname, self.inst, values)
        self.write("Saved position '%s' for '%s'" % (posname, self.inst.name))

    def onSavePosition(self, evt=None):
        posname = evt.GetString().strip()
        verify = int(self.db.get_info('verify_overwrite'))
        if verify and posname in self.pos_list.GetItems():

            thispos = self.db.get_position(posname, self.inst)
            postext = ["\nSaved Values were:\n"]
            for pvpos in thispos.pvs:
                postext.append('  %s= %s' % (pvpos.pv.name, pvpos.value))
            postext = '\n'.join(postext)

            ret = popup(self, "Overwrite %s?: \n%s" % (posname, postext),
                        'Verify Overwrite',
                        style=wx.YES_NO|wx.ICON_QUESTION)
            if ret != wx.ID_YES:
                return

        self.save_current_position(posname)
        if posname not in self.pos_list.GetItems():
            self.pos_list.Append(posname)

    @EpicsFunction
    def restore_position(self, posname, exclude_pvs=None, timeout=60.0):
        self.db.restore_position(posname, self.inst,
                                 exclude_pvs=exclude_pvs)
        msg= "Moving to '%s' to position '%s'" % (self.inst.name, posname)
        if exclude_pvs is not None and len(exclude_pvs) > 0:
            msg = "%s (Partial: %i PVs not restored)" % (msg, len(exclude_pvs))
        self.write(msg)
        self.puttimer.Start(50)

    def OnMove(self, evt=None):
        """ on GoTo """
        posname = self.pos_list.GetStringSelection()
        thispos = self.db.get_position(posname, self.inst)
        if thispos is None:
            return

        verify = int(self.db.get_info('verify_move'))
        if verify == 0:
            self.restore_position(posname)
        elif verify == 1:
            dlg = MoveToDialog(self, posname, self.inst, self.db, self.pvs)
            dlg.Raise()
            if dlg.ShowModal() == wx.ID_OK:
                exclude_pvs = []
                for pvname, data, in dlg.checkboxes.items():
                    if not data[0].IsChecked():
                        exclude_pvs.append(pvname)
                self.restore_position(posname, exclude_pvs=exclude_pvs)
            else:
                return
            dlg.Destroy()

    def OnShowPos(self, evt=None):
        """ on Show Position """
        posname = self.pos_list.GetStringSelection()
        thispos = self.db.get_position(posname, self.inst)
        if thispos is None:
            return
        dlg = MoveToDialog(self, posname, self.inst, self.db, self.pvs,
                           mode='show')
        dlg.Raise()
        if dlg.ShowModal() == wx.ID_OK:
            pass
        dlg.Destroy()

    def onPosSelect(self, evt=None):
        "  "
        if evt is not None:
            self.pos_name.SetValue(evt.GetString())
            evt.Skip()


    def onRightClick(self, evt=None):
        menu = wx.Menu()
        if not hasattr(self, 'popup_up1'):
            for item in ('popup_up1', 'popup_dn1',
                         'popup_upall', 'popup_dnall',
                         'popup_rename'):
                setattr(self, item,  wx.NewId())
                self.Bind(wx.EVT_MENU, self.onPosRightEvent,
                          id=getattr(self, item))

        menu.Append(self.popup_rename, "Rename Position")
        menu.Append(self.popup_up1, "Move up")
        menu.Append(self.popup_dn1, "Move down")
        menu.Append(self.popup_upall, "Move to top")
        menu.Append(self.popup_dnall, "Move to bottom")
        self.PopupMenu(menu)
        menu.Destroy()

    def onPosRightEvent(self, event=None, posname=None):
        idx = self.pos_list.GetSelection()
        if idx < 0: # no item selected
            return

        wid = event.GetId()
        namelist = self.pos_list.GetItems()
        if wid == self.popup_up1 and idx > 0:
            namelist.insert(idx-1, namelist.pop(idx))
        elif wid == self.popup_dn1 and idx < len(namelist):
            namelist.insert(idx+1, namelist.pop(idx))
        elif wid == self.popup_upall:
            namelist.insert(0, namelist.pop(idx))
        elif wid == self.popup_dnall:
            namelist.append( namelist.pop(idx))
        elif wid == self.popup_rename:
            posname = namelist[idx]
            newname = None
            dlg = RenameDialog(self, posname, self.inst)
            dlg.Raise()
            if dlg.ShowModal() == wx.ID_OK:
                newname = dlg.newname.GetValue()
            dlg.Destroy()
            if newname is not None:
                self.db.rename_position(posname, newname, instrument=self.inst)
                namelist[idx] = newname


        self.pos_list.Clear()
        for posname in namelist:
            self.pos_list.Append(posname)

    def onErase(self, evt=None):
        posname = self.pos_list.GetStringSelection()
        verify = int(self.db.get_info('verify_erase'))

        if verify:
            ret = popup(self, "Erase position '%s'?" % (posname),
                        'Verify Erase',
                        style=wx.YES_NO|wx.ICON_QUESTION)
            if ret != wx.ID_YES:
                return

        self.db.remove_position(posname, self.inst)
        ipos  =  self.pos_list.GetSelection()
        self.pos_list.Delete(ipos)
        self.write("Erased position '%s' for '%s'" % (posname, self.inst.name))
コード例 #4
0
ファイル: StageConf.py プロジェクト: pluflou/epicsapps
        'ints': ('finex_dir', 'finey_dir')
    },
    'camera': {
        'ordered': False
    },
    'stages': {
        'ordered': True
    },
    'positions': {
        'ordered': True
    }
}

conf_objs = OrderedDict(
    (('setup', ('verify_move', 'verify_erase', 'verify_overwrite', 'finex_dir',
                'finey_dir')), ('camera', ('type', 'image_folder', 'ad_prefix',
                                           'ad_format', 'web_url')),
     ('stages', None), ('positions', None)))

conf_files = ('SampleStage_autosave.ini', 'SampleStage.ini',
              '//cars5/Data/xas_user/config/SampleStage.ini')


class StageConfig(object):
    def __init__(self, filename=None, text=None):
        self.config = {}
        self.cp = ConfigParser()
        self.nstages = 0
        conf_found = False
        if filename is None:
            for fname in conf_files:
コード例 #5
0
    def __init__(self,
                 parent,
                 inst,
                 db=None,
                 writer=None,
                 pvlist=None,
                 size=(-1, -1)):
        self.last_draw = 0
        self.inst = inst
        self.pvlist = pvlist
        self.db = db
        self.write_message = writer
        self.pvs = {}
        self.pvdesc = {}
        self.pv_components = OrderedDict()

        wx.Panel.__init__(self, parent, size=size)

        #for p in self.db.get_ordered_instpvs(inst):
        #    self.add_pv(p.pv.name)

        self.colors = colors = GUIColors()
        self.parent = parent
        self.SetFont(parent.GetFont())
        titlefont = self.GetFont()
        titlefont.PointSize += 2
        titlefont.SetWeight(wx.BOLD)

        splitter = wx.SplitterWindow(self,
                                     -1,
                                     style=wx.SP_3D | wx.SP_BORDER
                                     | wx.SP_LIVE_UPDATE)

        rpanel = wx.Panel(splitter, style=wx.BORDER_SUNKEN, size=(-1, 225))
        self.leftpanel = wx.Panel(splitter,
                                  style=wx.BORDER_SUNKEN,
                                  size=(-1, 325))

        # self.leftsizer = wx.GridBagSizer(12, 4)
        self.leftsizer = wx.BoxSizer(wx.VERTICAL)

        splitter.SetMinimumPaneSize(225)

        toprow = wx.Panel(self.leftpanel)

        self.inst_title = SimpleText(toprow,
                                     ' %s ' % inst.name,
                                     font=titlefont,
                                     colour=colors.title,
                                     minsize=(150, -1),
                                     style=wx.ALIGN_LEFT | wx.ALIGN_BOTTOM)

        self.pos_name = wx.TextCtrl(toprow,
                                    value="",
                                    size=(250, 25),
                                    style=wx.TE_PROCESS_ENTER)
        self.pos_name.Bind(wx.EVT_TEXT_ENTER, self.onSavePosition)

        topsizer = wx.BoxSizer(wx.HORIZONTAL)
        topsizer.Add(self.inst_title, 0,
                     wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 1)
        topsizer.Add(
            SimpleText(toprow,
                       'Save Current Position:',
                       minsize=(180, -1),
                       style=wx.ALIGN_CENTER), 1,
            wx.ALIGN_CENTER_VERTICAL | wx.ALL, 1)

        topsizer.Add(self.pos_name, 0,
                     wx.GROW | wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, 1)

        pack(toprow, topsizer)
        self.toprow = toprow

        # start a timer to check for when to fill in PV panels
        timer_id = wx.NewId()
        # self.etimer = wx.Timer(self)
        self.etimer2 = wx.Timer(self)
        self.puttimer = wx.Timer(self)
        self.etimer_count = 0
        self.etimer_poll = 25

        # self.Bind(wx.EVT_TIMER, self.OnConnectTimer, self.etimer)
        self.Bind(wx.EVT_TIMER, self.OnEtimer2, self.etimer2)

        self.Bind(wx.EVT_TIMER, self.OnPutTimer, self.puttimer)

        rsizer = wx.BoxSizer(wx.VERTICAL)
        btn_goto = add_button(rpanel,
                              "Go To",
                              size=(70, -1),
                              action=self.OnMove)
        btn_erase = add_button(rpanel,
                               "Erase",
                               size=(70, -1),
                               action=self.onErase)

        brow = wx.BoxSizer(wx.HORIZONTAL)
        brow.Add(btn_goto, 0, ALL_EXP | wx.ALIGN_LEFT, 1)
        brow.Add(btn_erase, 0, ALL_EXP | wx.ALIGN_LEFT, 1)

        self.pos_list = wx.ListBox(rpanel, size=(225, -1))
        self.pos_list.SetBackgroundColour(wx.WHITE)
        self.pos_list.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick)
        self.pos_list.Bind(wx.EVT_LISTBOX, self.onPosSelect)
        self.pos_list.Bind(wx.EVT_LEFT_DCLICK, self.OnMove)

        self.pos_list.Clear()
        for pos in inst.positions:
            self.pos_list.Append(pos.name)

        rsizer.Add(brow, 0, wx.ALIGN_LEFT | wx.ALL)
        rsizer.Add(self.pos_list, 1, wx.EXPAND | wx.ALIGN_CENTER, 1)
        pack(rpanel, rsizer)

        splitter.SplitVertically(self.leftpanel, rpanel, -150)

        self.leftpanel.SetMinSize((750, 150))
        rpanel.SetMinSize((150, -1))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.GROW | wx.ALL, 0)
        pack(self, sizer)
        print ' start etimer2 for ', self.inst.name, time.ctime()
        self.etimer2.Start(1)
コード例 #6
0
class InstrumentPanel(wx.Panel):
    """ create Panel for an instrument"""
    def __init__(self,
                 parent,
                 inst,
                 db=None,
                 writer=None,
                 pvlist=None,
                 size=(-1, -1)):
        self.last_draw = 0
        self.inst = inst
        self.pvlist = pvlist
        self.db = db
        self.write_message = writer
        self.pvs = {}
        self.pvdesc = {}
        self.pv_components = OrderedDict()

        wx.Panel.__init__(self, parent, size=size)

        #for p in self.db.get_ordered_instpvs(inst):
        #    self.add_pv(p.pv.name)

        self.colors = colors = GUIColors()
        self.parent = parent
        self.SetFont(parent.GetFont())
        titlefont = self.GetFont()
        titlefont.PointSize += 2
        titlefont.SetWeight(wx.BOLD)

        splitter = wx.SplitterWindow(self,
                                     -1,
                                     style=wx.SP_3D | wx.SP_BORDER
                                     | wx.SP_LIVE_UPDATE)

        rpanel = wx.Panel(splitter, style=wx.BORDER_SUNKEN, size=(-1, 225))
        self.leftpanel = wx.Panel(splitter,
                                  style=wx.BORDER_SUNKEN,
                                  size=(-1, 325))

        # self.leftsizer = wx.GridBagSizer(12, 4)
        self.leftsizer = wx.BoxSizer(wx.VERTICAL)

        splitter.SetMinimumPaneSize(225)

        toprow = wx.Panel(self.leftpanel)

        self.inst_title = SimpleText(toprow,
                                     ' %s ' % inst.name,
                                     font=titlefont,
                                     colour=colors.title,
                                     minsize=(150, -1),
                                     style=wx.ALIGN_LEFT | wx.ALIGN_BOTTOM)

        self.pos_name = wx.TextCtrl(toprow,
                                    value="",
                                    size=(250, 25),
                                    style=wx.TE_PROCESS_ENTER)
        self.pos_name.Bind(wx.EVT_TEXT_ENTER, self.onSavePosition)

        topsizer = wx.BoxSizer(wx.HORIZONTAL)
        topsizer.Add(self.inst_title, 0,
                     wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 1)
        topsizer.Add(
            SimpleText(toprow,
                       'Save Current Position:',
                       minsize=(180, -1),
                       style=wx.ALIGN_CENTER), 1,
            wx.ALIGN_CENTER_VERTICAL | wx.ALL, 1)

        topsizer.Add(self.pos_name, 0,
                     wx.GROW | wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, 1)

        pack(toprow, topsizer)
        self.toprow = toprow

        # start a timer to check for when to fill in PV panels
        timer_id = wx.NewId()
        # self.etimer = wx.Timer(self)
        self.etimer2 = wx.Timer(self)
        self.puttimer = wx.Timer(self)
        self.etimer_count = 0
        self.etimer_poll = 25

        # self.Bind(wx.EVT_TIMER, self.OnConnectTimer, self.etimer)
        self.Bind(wx.EVT_TIMER, self.OnEtimer2, self.etimer2)

        self.Bind(wx.EVT_TIMER, self.OnPutTimer, self.puttimer)

        rsizer = wx.BoxSizer(wx.VERTICAL)
        btn_goto = add_button(rpanel,
                              "Go To",
                              size=(70, -1),
                              action=self.OnMove)
        btn_erase = add_button(rpanel,
                               "Erase",
                               size=(70, -1),
                               action=self.onErase)

        brow = wx.BoxSizer(wx.HORIZONTAL)
        brow.Add(btn_goto, 0, ALL_EXP | wx.ALIGN_LEFT, 1)
        brow.Add(btn_erase, 0, ALL_EXP | wx.ALIGN_LEFT, 1)

        self.pos_list = wx.ListBox(rpanel, size=(225, -1))
        self.pos_list.SetBackgroundColour(wx.WHITE)
        self.pos_list.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick)
        self.pos_list.Bind(wx.EVT_LISTBOX, self.onPosSelect)
        self.pos_list.Bind(wx.EVT_LEFT_DCLICK, self.OnMove)

        self.pos_list.Clear()
        for pos in inst.positions:
            self.pos_list.Append(pos.name)

        rsizer.Add(brow, 0, wx.ALIGN_LEFT | wx.ALL)
        rsizer.Add(self.pos_list, 1, wx.EXPAND | wx.ALIGN_CENTER, 1)
        pack(rpanel, rsizer)

        splitter.SplitVertically(self.leftpanel, rpanel, -150)

        self.leftpanel.SetMinSize((750, 150))
        rpanel.SetMinSize((150, -1))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.GROW | wx.ALL, 0)
        pack(self, sizer)
        print ' start etimer2 for ', self.inst.name, time.ctime()
        self.etimer2.Start(1)

    def undisplay_pv(self, pvname):
        "remove pv from display"
        if pvname in self.pv_components:
            self.pv_components.pop(pvname)
            self.redraw_leftpanel()

        # @EpicsFunction
    def redraw_leftpanel(self, force=False):
        """ redraws the left panel """
        if (time.time() - self.last_draw) < 0.5:
            return

        print 'redraw left! ', time.ctime()

        self.Freeze()
        self.Hide()
        self.leftsizer.Clear()

        # print 'redraw left 1 ', time.ctime()
        self.leftsizer.Add(self.toprow, 0, wx.ALIGN_LEFT | wx.TOP, 2)

        current_comps = [self.toprow]
        pvcomps = list(self.pv_components.items())

        skip = []
        for icomp, val in enumerate(pvcomps):
            pvname, comp = val
            connected, pvtype, pv = comp
            grow = 0
            panel = None
            if pvtype == 'motor':
                try:
                    #print 'MotorPanel create ', self.inst.name, pvname
                    t0 = time.time()
                    panel = MotorPanel(self.leftpanel, pvname)
                    #print 'MotorPanel done ', time.time()-t0
                except PyDeadObjectError:
                    #print 'Error making motorpanel'
                    pass
            elif pv is not None and hasattr(
                    pv, 'pvname') and pv.pvname not in skip:
                panel = wx.Panel(self.leftpanel)
                sizer = wx.BoxSizer(wx.HORIZONTAL)

                label = SimpleText(panel,
                                   '  %s' % pvname,
                                   colour=self.colors.pvname,
                                   minsize=(180, -1),
                                   style=wx.ALIGN_LEFT)

                if pvtype == 'enum':
                    ctrl = PVEnumChoice(panel, pv=pv, size=(120, -1))
                elif pvtype in ('string', 'unicode'):
                    ctrl = PVTextCtrl(panel, pv=pv, size=(120, -1))
                else:
                    ctrl = PVFloatCtrl(panel, pv=pv, size=(120, -1))

                current_comps.append(ctrl)
                current_comps.append(label)

                sizer.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 2)
                sizer.Add(ctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 2)

                if (pvtype != 'motor' and icomp < len(pvcomps) - 1 and
                        pvcomps[icomp + 1][1][1] != 'motor'):  #  and False):
                    conn, pvtype2, pv2 = pvcomps[icomp + 1][1]
                    skip.append(pv2.pvname)

                    l2 = SimpleText(panel,
                                    '  %s' % pv2.pvname,
                                    colour=self.colors.pvname,
                                    minsize=(180, -1),
                                    style=wx.ALIGN_LEFT)
                    if pvtype2 == 'enum':
                        c2 = PVEnumChoice(panel, pv=pv2, size=(120, -1))
                    elif pvtype2 in ('string', 'unicode'):
                        c2 = PVTextCtrl(panel, pv=pv2, size=(120, -1))
                    else:
                        c2 = PVFloatCtrl(panel, pv=pv2, size=(120, -1))

                    sizer.Add(l2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 2)
                    sizer.Add(c2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 2)
                    current_comps.append(c2)
                    current_comps.append(l2)
                pack(panel, sizer)

            if panel is not None:
                current_comps.append(panel)
                self.leftsizer.Add(panel, 0,
                                   wx.ALIGN_LEFT | wx.TOP | wx.ALL | wx.GROW,
                                   1)

        pack(self.leftpanel, self.leftsizer)

        for wid in self.leftpanel.Children:
            if wid not in current_comps and wid != self.toprow:
                try:
                    time.sleep(0.010)
                    wid.Destroy()
                except PyDeadObjectError:
                    pass

        self.Refresh()
        self.Layout()
        self.Thaw()
        self.Show()
        print 'redraw left End ', time.ctime()
        self.last_draw = time.time()

    def add_pv(self, pvname):
        """add a PV to the left panel"""
        pvname = normalize_pvname(pvname)
        # print 'add pv ', pvname, self.inst.name
        self.pv_components[pvname] = (False, None, None)
        db_pv = self.db.get_pv(pvname)
        if db_pv.pvtype.name == 'motor':
            idot = pvname.find('.')
            for ext in MOTOR_FIELDS:
                self.pvlist.connect_pv('%s.%s' % (pvname[:idot], ext))
        # self.PV_Panel(pvname)

    def write(self, msg, status='normal'):
        if self.write_message is None:
            return
        self.write_message(msg, status=status)

    def OnPutTimer(self, evt=None):
        """Timer Event for GoTo to look if move is complete."""
        if self.db.restore_complete():
            self.puttimer.Stop()

    def OnConnectTimer(self, evt=None):
        """Timer Event: look for uncompleted PV panels
        and try to create them ...
        """
        if all([comp[0]
                for comp in self.pv_components.values()]):  # "all connected"
            # self.etimer.Stop()
            self.etimer2.Stop()
            self.redraw_leftpanel()
            # return
        # if we've done 20 rounds, there are probably
        # really unconnected PVs -- let's slow down.

    def OnEtimer2(self, evt=None):
        print 'etimer2 event ', self.inst.name, time.ctime()
        for pvname in self.pv_components:
            self.PV_Panel(pvname)

        if all([comp[0]
                for comp in self.pv_components.values()]):  # "all connected"
            print 'Etimer2 --> draw left ', self.inst.name, time.ctime()
            self.redraw_leftpanel()
            self.etimer2.Stop()

    def PV_Panel(self, pvname):  # , panel, sizer, current_wid=None):
        """ try to create a PV Panel for the given pv
        returns quickly for an unconnected PV, to be tried later
        by the timer"""
        pvname = str(pvname)

        if '.' not in pvname:
            pvname = '%s.VAL' % pvname

        if pvname not in self.pvlist.pvs:
            self.pvlist.connect_pv(pvname)

        # print 'PV Panel ', self.inst.name, pvname, len(self.pvlist.pvs), time.ctime()
        if pvname in self.pvlist.pvs:
            pv = self.pvlist.pvs[pvname]
        else:
            # print 'pvname not yet in pvlist ? ', pvname, len(self.pvlist.pvs)
            return

        # return if not connected
        if not pv.connected:
            print 'pv not connected'
            return

        if pvname not in self.pv_components:
            print 'pv not in components', pvname
            return

        # pv.get_ctrlvars()
        pvtype = self.pv_components[pvname][1]
        if pvtype is None:
            db_pv = self.db.get_pv(pvname)
            try:
                pvtype = str(db_pv.pvtype.name)
            except AttributeError:
                pass

        #   pvtype  = get_pvtypes(pv)[0]
        self.pv_components[pvname] = (True, pvtype, pv)

        # self.db.set_pvtype(pvname, pvtype)

    @EpicsFunction
    def save_current_position(self, posname):
        values = {}
        for pv in self.pvs.values():
            values[pv.pvname] = pv.get(as_string=True)
        self.db.save_position(posname, self.inst, values)
        self.write("Saved position '%s' for '%s'" % (posname, self.inst.name))

    def onSavePosition(self, evt=None):
        posname = evt.GetString().strip()
        verify = int(self.db.get_info('verify_overwrite'))
        if verify and posname in self.pos_list.GetItems():

            thispos = self.db.get_position(posname, self.inst)
            postext = ["\nSaved Values were:\n"]
            for pvpos in thispos.pvs:
                postext.append('  %s= %s' % (pvpos.pv.name, pvpos.value))
            postext = '\n'.join(postext)

            ret = popup(self,
                        "Overwrite %s?: \n%s" % (posname, postext),
                        'Verify Overwrite',
                        style=wx.YES_NO | wx.ICON_QUESTION)
            if ret != wx.ID_YES:
                return

        self.save_current_position(posname)
        if posname not in self.pos_list.GetItems():
            self.pos_list.Append(posname)

    @EpicsFunction
    def restore_position(self, posname, exclude_pvs=None, timeout=60.0):
        self.db.restore_position(posname, self.inst, exclude_pvs=exclude_pvs)
        msg = "Moving to '%s' to position '%s'" % (self.inst.name, posname)
        if exclude_pvs is not None and len(exclude_pvs) > 0:
            msg = "%s (Partial: %i PVs not restored)" % (msg, len(exclude_pvs))
        self.write(msg)
        self.puttimer.Start(50)

    def OnMove(self, evt=None):
        """ on GoTo """
        posname = self.pos_list.GetStringSelection()
        thispos = self.db.get_position(posname, self.inst)
        if thispos is None:
            return

        verify = int(self.db.get_info('verify_move'))
        if verify == 0:
            self.restore_position(posname)
        elif verify == 1:
            dlg = MoveToDialog(self,
                               posname,
                               self.inst,
                               self.db,
                               self.pvs,
                               pvdesc=self.pvdesc)
            dlg.Raise()
            if dlg.ShowModal() == wx.ID_OK:
                exclude_pvs = []
                for pvname, data, in dlg.checkboxes.items():
                    if not data[0].IsChecked():
                        exclude_pvs.append(pvname)
                self.restore_position(posname, exclude_pvs=exclude_pvs)
            else:
                return
            dlg.Destroy()

    def onPosSelect(self, evt=None):
        "  "
        if evt is not None:
            self.pos_name.SetValue(evt.GetString())
            evt.Skip()

    def onRightClick(self, evt=None):
        menu = wx.Menu()
        if not hasattr(self, 'popup_up1'):
            for item in ('popup_up1', 'popup_dn1', 'popup_upall',
                         'popup_dnall', 'popup_rename'):
                setattr(self, item, wx.NewId())
                self.Bind(wx.EVT_MENU,
                          self.onPosRightEvent,
                          id=getattr(self, item))

        menu.Append(self.popup_rename, "Rename Position")
        menu.Append(self.popup_up1, "Move up")
        menu.Append(self.popup_dn1, "Move down")
        menu.Append(self.popup_upall, "Move to top")
        menu.Append(self.popup_dnall, "Move to bottom")
        self.PopupMenu(menu)
        menu.Destroy()

    def onPosRightEvent(self, event=None, posname=None):
        idx = self.pos_list.GetSelection()
        if idx < 0:  # no item selected
            return

        wid = event.GetId()
        namelist = self.pos_list.GetItems()
        if wid == self.popup_up1 and idx > 0:
            namelist.insert(idx - 1, namelist.pop(idx))
        elif wid == self.popup_dn1 and idx < len(namelist):
            namelist.insert(idx + 1, namelist.pop(idx))
        elif wid == self.popup_upall:
            namelist.insert(0, namelist.pop(idx))
        elif wid == self.popup_dnall:
            namelist.append(namelist.pop(idx))
        elif wid == self.popup_rename:
            posname = namelist[idx]
            newname = None
            dlg = RenameDialog(self, posname, self.inst)
            dlg.Raise()
            if dlg.ShowModal() == wx.ID_OK:
                newname = dlg.newname.GetValue()
            dlg.Destroy()
            if newname is not None:
                self.db.rename_position(posname, newname, instrument=self.inst)
                namelist[idx] = newname

        self.pos_list.Clear()
        for posname in namelist:
            self.pos_list.Append(posname)

    def onErase(self, evt=None):
        posname = self.pos_list.GetStringSelection()
        verify = int(self.db.get_info('verify_erase'))

        if verify:
            ret = popup(self,
                        "Erase position '%s'?" % (posname),
                        'Verify Erase',
                        style=wx.YES_NO | wx.ICON_QUESTION)
            if ret != wx.ID_YES:
                return

        self.db.remove_position(posname, self.inst)
        ipos = self.pos_list.GetSelection()
        self.pos_list.Delete(ipos)
        self.write("Erased position '%s' for '%s'" % (posname, self.inst.name))