Ejemplo n.º 1
0
 def init_scandb(self):
     dbconn = self.config
     if dbconn is not None:
         self.instname = dbconn.get("instrument", "microscope_stages")
         if dbconn["port"] in ("", "None", None):
             dbconn.pop("port")
         scandb = ScanDB(**dbconn)
         self.instdb = InstrumentDB(scandb)
         if self.instdb.get_instrument(self.instname) is None:
             pvs = self.parent.config["stages"].keys()
             self.instdb.add_instrument(self.instname, pvs=pvs)
Ejemplo n.º 2
0
class PositionPanel(wx.Panel):
    """panel of position lists, with buttons"""

    def __init__(self, parent, config=None):
        wx.Panel.__init__(self, parent, -1, size=(300, 500))
        self.size = (300, 500)
        self.parent = parent
        self.config = config
        self.image_display = None
        self.pos_name = wx.TextCtrl(self, value="", size=(285, 25), style=wx.TE_PROCESS_ENTER)
        self.pos_name.Bind(wx.EVT_TEXT_ENTER, self.onSave1)

        tlabel = wx.StaticText(self, label="Save Position: ")

        bkws = dict(size=(55, -1))
        btn_save = add_button(self, "Save", action=self.onSave2, **bkws)
        btn_goto = add_button(self, "Go To", action=self.onGo, **bkws)
        btn_erase = add_button(self, "Erase", action=self.onErase, **bkws)
        btn_show = add_button(self, "Show", action=self.onShow, **bkws)
        # btn_many  = add_button(self, "Erase Many",  action=self.onEraseMany,  **bkws)

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

        self.pos_list = wx.ListBox(self)
        self.pos_list.SetBackgroundColour(wx.Colour(253, 253, 250))
        self.pos_list.Bind(wx.EVT_LISTBOX, self.onSelect)
        self.pos_list.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(tlabel, 0, wx.ALIGN_LEFT | wx.ALL)
        sizer.Add(self.pos_name, 0, wx.ALIGN_LEFT | wx.ALL)
        sizer.Add(brow, 0, wx.ALIGN_LEFT | wx.ALL)
        sizer.Add(self.pos_list, 1, ALL_EXP | wx.ALIGN_CENTER, 3)
        # print(" Position Panel ", self.GetSize(), self.size)

        pack(self, sizer)
        self.init_scandb()
        self.last_refresh = 0
        self.get_positions_from_db()
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)
        self.timer.Start(3000)

    def init_scandb(self):
        dbconn = self.config
        if dbconn is not None:
            self.instname = dbconn.get("instrument", "microscope_stages")
            if dbconn["port"] in ("", "None", None):
                dbconn.pop("port")
            scandb = ScanDB(**dbconn)
            self.instdb = InstrumentDB(scandb)
            if self.instdb.get_instrument(self.instname) is None:
                pvs = self.parent.config["stages"].keys()
                self.instdb.add_instrument(self.instname, pvs=pvs)

    def onSave1(self, event):
        "save from text enter"
        self.onSave(event.GetString().strip())

    def onSave2(self, event):
        "save from button push"
        self.onSave(self.pos_name.GetValue().strip())

    def onSave(self, name):
        if len(name) < 1:
            return

        if name in self.positions and self.parent.v_replace:
            ret = popup(
                self,
                "Overwrite Position %s?" % name,
                "Veriry Overwrite Position",
                style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
            )
            if ret != wx.ID_YES:
                return

        imgfile = "%s.jpg" % time.strftime("%b%d_%H%M%S")
        imgfile = os.path.join(self.parent.imgdir, imgfile)
        tmp_pos = self.parent.ctrlpanel.read_position()
        imgdata, count = None, 0
        while imgdata is None and count < 100:
            imgdata = self.parent.save_image(imgfile)
            if imgdata is None:
                time.sleep(0.5)
            count = count + 1

        imgdata["source"] = "SampleStage"
        imgdata["data_format"] = "file"
        imgdata.pop("data")
        notes = json.dumps(imgdata)
        fullpath = os.path.join(os.getcwd(), imgfile)

        self.positions[name] = {
            "image": fullpath,
            "timestamp": time.strftime("%b %d %H:%M:%S"),
            "position": tmp_pos,
            "notes": notes,
        }

        if name not in self.pos_list.GetItems():
            self.pos_list.Append(name)

        self.instdb.save_position(self.instname, name, tmp_pos, notes=notes, image=fullpath)

        self.pos_list.SetStringSelection(name)
        # auto-save file
        self.parent.autosave(positions=self.positions)
        self.parent.write_htmllog(name, self.positions[name])

        self.parent.write_message("Saved Position '%s', image in %s" % (name, imgfile))
        wx.CallAfter(Closure(self.onSelect, event=None, name=name))

    def onShow(self, event):
        posname = self.pos_list.GetStringSelection()
        ipos = self.pos_list.GetSelection()
        if posname is None or len(posname) < 1:
            return
        try:
            self.image_display.Show()
            self.image_display.Raise()
        except:
            del self.image_display
            self.image_display = None

        if self.image_display is None:
            self.image_display = ImageDisplayFrame()
            self.image_display.Raise()

        thispos = self.positions[posname]
        try:
            notes = json.loads(thispos["notes"])
        except:
            notes = {"data_format": ""}
        label = []
        stages = self.parent.config["stages"]
        posvals = self.positions[posname]["position"]
        for pvname, value in posvals.items():
            value = thispos["position"][pvname]
            desc = stages.get(pvname, {}).get("desc", None)
            if desc is None:
                desc = pvname
            label.append("%s=%.4f" % (desc, float(value)))
        label = ", ".join(label)
        label = "%s: %s" % (posname, label)

        data = thispos["image"]
        if str(notes["data_format"]) == "file":
            self.image_display.showfile(data, title=posname, label=label)
        elif str(notes["data_format"]) == "base64":
            size = notes.get("image_size", (800, 600))
            self.image_display.showb64img(data, size=size, title=posname, label=label)
        else:
            print "Cannot show image for %s" % posname

    def onGo(self, event):
        posname = self.pos_list.GetStringSelection()
        if posname is None or len(posname) < 1:
            return
        stages = self.parent.config["stages"]
        posvals = self.positions[posname]["position"]
        postext = []
        for pvname, value in posvals.items():
            label = pvname
            desc = stages.get(pvname, {}).get("desc", None)
            if desc is not None:
                label = "%s (%s)" % (desc, pvname)
            postext.append("  %s\t= %.4f" % (label, float(value)))
        postext = "\n".join(postext)
        if self.parent.v_move:
            ret = popup(
                self, "Move to %s?: \n%s" % (posname, postext), "Verify Move", style=wx.YES_NO | wx.ICON_QUESTION
            )
            if ret != wx.ID_YES:
                return
        for pvname, value in posvals.items():
            caput(pvname, value)
        self.parent.write_message("moved to %s" % posname)

    def onErase(self, event):
        posname = self.pos_list.GetStringSelection()
        ipos = self.pos_list.GetSelection()
        if posname is None or len(posname) < 1:
            return
        if self.parent.v_erase:
            if wx.ID_YES != popup(self, "Erase  %s?" % (posname), "Verify Erase", style=wx.YES_NO | wx.ICON_QUESTION):
                return
        self.instdb.remove_position(self.instname, posname)
        self.positions.pop(posname)
        self.pos_list.Delete(ipos)
        self.pos_name.Clear()
        self.parent.write_message("Erased Position %s" % posname)

    def onEraseMany(self, event=None):
        if self.instdb is not None:
            ErasePositionsDialog(self.positions.keys(), instname=self.instname, instdb=self.instdb)

    def onSelect(self, event=None, name=None):
        "Event handler for selecting a named position"
        if name is None:
            name = str(event.GetString().strip())
        if name is None or name not in self.positions:
            return
        self.pos_name.SetValue(name)

    def onRightClick(self, event=None):
        menu = wx.Menu()
        # make basic widgets for popup menu
        for item, name in (
            ("popup_up1", "Move up"),
            ("popup_dn1", "Move down"),
            ("popup_upall", "Move to top"),
            ("popup_dnall", "Move to bottom"),
        ):
            setattr(self, item, wx.NewId())
            wid = getattr(self, item)
            self.Bind(wx.EVT_MENU, self.onRightEvent, wid)
            menu.Append(wid, name)
        self.PopupMenu(menu)
        menu.Destroy()

    def onRightEvent(self, event=None):
        "popup box event handler"
        idx = self.pos_list.GetSelection()
        if idx < 0:  # no item selected
            return
        wid = event.GetId()
        namelist = list(self.positions.keys())[:]
        stmp = {}
        for name in namelist:
            stmp[name] = self.positions[name]

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

        newpos = {}
        for name in namelist:
            newpos[name] = stmp[name]
        self.init_positions(newpos)
        self.parent.autosave(positions=self.positions)

    def set_positions(self, positions):
        "set the list of position on the left-side panel"
        cur_sel = self.pos_list.GetStringSelection()
        self.pos_list.Clear()
        self.positions = positions
        for name, val in self.positions.items():
            self.pos_list.Append(name)
        if cur_sel in self.positions:
            self.pos_list.SetStringSelection(cur_sel)
        self.last_refresh = time.time()

    def onTimer(self, evt=None):
        posnames = self.instdb.get_positionlist(self.instname)
        if len(posnames) != len(self.posnames) or (time.time() - self.last_refresh) > 15.0:
            self.get_positions_from_db()

    def get_positions_from_db(self):
        if self.instdb is None:
            return
        positions = OrderedDict()
        iname = self.instname
        posnames = self.instdb.get_positionlist(iname)
        self.posnames = posnames
        for pname in posnames:
            thispos = self.instdb.get_position(iname, pname)
            image = ""
            notes = {}
            if thispos.image is not None:
                image = thispos.image
            if thispos.notes is not None:
                notes = thispos.notes
            pdat = OrderedDict()
            for pvpos in thispos.pvs:
                pdat[pvpos.pv.name] = pvpos.value
            positions[pname] = dict(position=pdat, image=image, notes=notes)
        self.set_positions(positions)