Exemplo n.º 1
0
class TrackerControl(QtGui.QWidget):
    def __init__(self,
                 app,
                 maxshift,
                 invert=False,
                 seqali=False,
                 tiltstep=2.0):
        self.app = app
        self.maxshift = maxshift
        self.seqali = seqali
        self.invert = invert
        self.tiltstep = tiltstep

        # the control panel
        QtGui.QWidget.__init__(self, None)

        self.gbl = QtGui.QGridLayout(self)
        self.gbl.setMargin(0)
        self.gbl.setSpacing(6)
        self.gbl.setObjectName("hbl")

        # action buttons
        self.bcenalign = QtGui.QPushButton("Center Align")
        self.bprojalign = QtGui.QPushButton("Proj. Realign")
        self.btiltaxis = QtGui.QPushButton("Tilt Axis")
        self.btiltaxisval = QtGui.QLineEdit("90.0")
        self.bsavedata = QtGui.QPushButton("Save Data")
        self.breconst = QtGui.QPushButton("3D Normal")
        self.sbmode = QtGui.QSpinBox(self)
        self.sbmode.setRange(0, 2)
        self.sbmode.setValue(0)
        self.bmagict = QtGui.QPushButton("3D Tomofill")
        self.bmagics = QtGui.QPushButton("3D Sph")
        self.bmagicc = QtGui.QPushButton("3D Cyl")
        self.vslpfilt = ValSlider(self, (0, .5), "Filter", 0.5, 50)

        self.gbl.addWidget(self.bcenalign, 0, 0)
        self.gbl.addWidget(self.bprojalign, 0, 1)
        self.gbl.addWidget(self.btiltaxis, 0, 2)
        self.gbl.addWidget(self.btiltaxisval, 0, 3)
        #		self.gbl.addWidget(self.bsavedata,0,3)
        self.gbl.addWidget(self.breconst, 1, 0)
        self.gbl.addWidget(self.sbmode, 2, 0, 1, 1)
        self.gbl.addWidget(self.vslpfilt, 3, 0, 1, 4)
        self.gbl.addWidget(self.bmagict, 1, 1)
        self.gbl.addWidget(self.bmagics, 1, 2)
        self.gbl.addWidget(self.bmagicc, 1, 3)

        QtCore.QObject.connect(self.bcenalign, QtCore.SIGNAL("clicked(bool)"),
                               self.do_cenalign)
        QtCore.QObject.connect(self.bprojalign, QtCore.SIGNAL("clicked(bool)"),
                               self.do_projalign)
        QtCore.QObject.connect(self.btiltaxis, QtCore.SIGNAL("clicked(bool)"),
                               self.do_tiltaxis)
        QtCore.QObject.connect(self.bsavedata, QtCore.SIGNAL("clicked(bool)"),
                               self.do_savedata)
        QtCore.QObject.connect(self.breconst, QtCore.SIGNAL("clicked(bool)"),
                               self.do_reconst)
        QtCore.QObject.connect(self.bmagict, QtCore.SIGNAL("clicked(bool)"),
                               self.do_magict)
        QtCore.QObject.connect(self.bmagics, QtCore.SIGNAL("clicked(bool)"),
                               self.do_magics)
        QtCore.QObject.connect(self.bmagicc, QtCore.SIGNAL("clicked(bool)"),
                               self.do_magicc)
        QtCore.QObject.connect(self.vslpfilt, QtCore.SIGNAL("valueChanged"),
                               self.do_filter)

        # the single image display widget
        self.im2d = EMImage2DWidget(application=app, winid="tomotrackbox.big")
        self.imboxed = EMImage2DWidget(application=app,
                                       winid="tomotrackbox.small")
        self.improj = EMImage2DWidget(application=app,
                                      winid="tomotrackbox.proj")
        self.imslice = EMImage2DWidget(application=app,
                                       winid="tomotrackbox.3dslice")
        self.imvol = EMImage3DModule(application=app, winid="tomotrackbox.3d")

        # get some signals from the window.
        QtCore.QObject.connect(self.im2d, QtCore.SIGNAL("mousedown"),
                               self.down)
        QtCore.QObject.connect(self.im2d, QtCore.SIGNAL("mousedrag"),
                               self.drag)
        QtCore.QObject.connect(self.im2d, QtCore.SIGNAL("mouseup"), self.up)
        QtCore.QObject.connect(self.im2d, QtCore.SIGNAL("increment_list_data"),
                               self.change_tilt)

        self.imagefile = None
        self.imageparm = None
        self.tiltshapes = None
        self.curtilt = 0
        self.oldtilt = self.curtilt
        self.map3d = None
        self.downloc = None
        self.downadjloc = None

        self.show()
        self.im2d.show()

    def closeEvent(self, event):
        self.im2d.closeEvent(QtGui.QCloseEvent())
        self.imboxed.closeEvent(QtGui.QCloseEvent())
        self.improj.closeEvent(QtGui.QCloseEvent())
        self.imslice.closeEvent(QtGui.QCloseEvent())
        self.imvol.closeEvent(QtGui.QCloseEvent())
        event.accept()

    def do_cenalign(self, x=0):
        """In response to the center align button. Just a wrapper"""
        self.cenalign_stack()
        self.update_stack()

    def do_projalign(self, x=0):
        """In response to the projection align button. Just a wrapper"""
        self.projection_align(self.tiltstep)
        self.update_stack()
#		self.do_reconst()

    def do_tiltaxis(self):
        """In response to the tilt axis button. Just a wrapper"""
        self.tilt_axis()

    def do_reconst(self, x=0):
        """In response to the normal reconstruction button. Just a wrapper"""
        stack = self.get_boxed_stack()
        mode = self.sbmode.value()
        self.map3d = self.reconstruct(stack, self.tiltstep, mode)
        self.update_3d()

    def do_magict(self, x):
        """In response to tomographic filling reconstruction button. Just a wrapper"""
        stack = self.get_boxed_stack()
        #		self.map3d=self.reconstruct_ca(stack[5:-4],0.5)
        #		init=self.reconstruct_ca(stack[5:-4],0.5)
        mode = self.sbmode.value()
        self.map3d = self.reconstruct_wedgefill(stack, self.tiltstep, mode)
        self.update_3d()

    def do_magics(self, x):
        """In response to the 3D Sph button. Just a wrapper"""
        return

    def do_magicc(self, x):
        """In response to the 3D cyl button. Just a wrapper"""
        return

    def do_filter(self, v):
        """In response to the filter ValSlider"""
        if self.map3d == None: return
        self.lpfilt = v
        self.update_3d()

    def do_savedata(self):
        ""

    def update_3d(self):
        if self.map3d == None: return

        self.filt3d = self.map3d.process(
            "filter.lowpass.gauss", {"cutoff_abs": self.vslpfilt.getValue()})

        self.imvol.set_data(self.filt3d)
        self.imvol.show()
        self.imvol.updateGL()

        sz = self.map3d["nx"]
        xsum = self.filt3d.process("misc.directional_sum", {"axis": "x"})
        xsum.set_size(sz, sz, 1)
        ysum = self.filt3d.process("misc.directional_sum", {"axis": "y"})
        ysum.set_size(sz, sz, 1)
        zsum = self.filt3d.process("misc.directional_sum", {"axis": "z"})
        zsum.set_size(sz, sz, 1)

        self.improj.set_data([zsum, ysum, xsum])
        self.improj.show()
        self.improj.updateGL()

        self.imslice.set_data(self.filt3d)
        self.imslice.show()
        self.imslice.updateGL()

    def update_stack(self):
        stack = self.get_boxed_stack()
        self.imboxed.set_data(stack)
        self.imboxed.show()
        self.imboxed.updateGL()

    def set_image(self, fsp):
        """Takes an ali file to process"""
        self.imageparm = EMData(fsp, 0, True).get_attr_dict()
        print "%d slices at %d x %d" % (
            self.imageparm["nz"], self.imageparm["nx"], self.imageparm["ny"])

        self.imagefile = fsp

        self.curtilt = self.imageparm["nz"] / 2
        self.tiltshapes = [None for i in range(self.imageparm["nz"])]
        self.update_tilt()

    def update_tilt(self):
        if self.imagefile == None: return

        self.curimg = EMData(
            self.imagefile, 0, False,
            Region(0, 0, self.curtilt, self.imageparm["nx"],
                   self.imageparm["ny"], 1))
        if self.invert: self.curimg.mult(-1.0)
        self.im2d.set_data(self.curimg)

        s = EMShape(
            ["scrlabel", .7, .3, 0, 20.0, 20.0,
             "%d" % self.curtilt, 200.0, 1])
        self.im2d.add_shape("tilt", s)

        if self.tiltshapes[self.curtilt] != None:
            self.im2d.add_shape("finalbox", self.tiltshapes[self.curtilt])

            s0 = self.tiltshapes[self.oldtilt].getShape()
            s1 = self.tiltshapes[self.curtilt].getShape()
            dx = s0[4] - s1[4]
            dy = s0[5] - s1[5]

            self.im2d.set_origin(self.im2d.origin[0] - dx,
                                 self.im2d.origin[1] - dy)
            self.oldtilt = self.curtilt

        self.im2d.updateGL()

    def change_tilt(self, direc):
        """When the user presses the up or down arrow"""
        self.oldtilt = self.curtilt
        self.curtilt += direc
        if self.curtilt < 0: self.curtilt = 0
        if self.curtilt >= self.imageparm["nz"]:
            self.curtilt = self.imageparm["nz"] - 1

        self.update_tilt()

    def down(self, event, lc):
        """The event contains the x,y coordinates in window space, lc are the coordinates in image space"""

        if event.buttons() & Qt.LeftButton:
            if event.modifiers() & Qt.ShiftModifier:
                self.downadjloc = (
                    lc, self.tiltshapes[self.curtilt].getShape()[4:8])
            else:
                self.downloc = lc

    def drag(self, event, lc):
        if self.downloc != None:
            dx = abs(lc[0] - self.downloc[0])
            dy = abs(lc[1] - self.downloc[1])
            dx = max(dx, dy)  # Make box square
            dx = good_size(dx * 2) / 2  # use only good sizes
            dy = dx
            s = EMShape([
                "rectpoint", 0, .7, 0, self.downloc[0] - dx,
                self.downloc[1] - dy, self.downloc[0] + dx,
                self.downloc[1] + dy, 1
            ])
            self.im2d.add_shape("box", s)
            s = EMShape([
                "scrlabel", .7, .7, 0, 20.0, 20.0,
                "%d (%d x %d)" % (self.curtilt, dx * 2, dy * 2), 200.0, 1
            ])
            self.im2d.add_shape("tilt", s)
        elif self.downadjloc != None:
            dx = (lc[0] - self.downadjloc[0][0])
            dy = (lc[1] - self.downadjloc[0][1])
            s = self.tiltshapes[self.curtilt].getShape()[:]
            s[4] = self.downadjloc[1][0] + dx
            s[5] = self.downadjloc[1][1] + dy
            s[6] = self.downadjloc[1][2] + dx
            s[7] = self.downadjloc[1][3] + dy
            self.im2d.add_shape("box", EMShape(s))

        self.im2d.updateGL()

    def up(self, event, lc):
        if self.downloc != None:
            dx = abs(lc[0] - self.downloc[0])
            dy = abs(lc[1] - self.downloc[1])
            dx = max(dx, dy)  # Make box square
            dx = good_size(dx * 2) / 2  # use only good sizes
            dy = dx
            s = EMShape([
                "rectpoint", .7, .2, 0, self.downloc[0] - dx,
                self.downloc[1] - dy, self.downloc[0] + dx,
                self.downloc[1] + dy, 1
            ])
            self.im2d.del_shape("box")
            if hypot(lc[0] - self.downloc[0], lc[1] - self.downloc[1]) > 5:
                self.tiltshapes = [None for i in range(self.imageparm["nz"])]
                self.find_boxes(s)

            self.update_tilt()
            self.downloc = None
        elif self.downadjloc != None:
            dx = (lc[0] - self.downadjloc[0][0])
            dy = (lc[1] - self.downadjloc[0][1])
            s = self.tiltshapes[self.curtilt].getShape()[:]
            s[4] = self.downadjloc[1][0] + dx
            s[5] = self.downadjloc[1][1] + dy
            s[6] = self.downadjloc[1][2] + dx
            s[7] = self.downadjloc[1][3] + dy
            self.tiltshapes[self.curtilt] = EMShape(s)
            self.im2d.add_shape("finalbox", self.tiltshapes[self.curtilt])
            self.im2d.del_shape("box")

            self.update_tilt()
            self.update_stack()
            self.downadjloc = None

    def get_boxed_stack(self):
        stack = []
        for i in range(self.imageparm["nz"]):
            refshape = self.tiltshapes[i].getShape()
            img = EMData(
                self.imagefile, 0, False,
                Region(refshape[4], refshape[5], i, refshape[6] - refshape[4],
                       refshape[7] - refshape[5], 1))
            img["ptcl_source_coord"] = (int((refshape[6] + refshape[4]) / 2.0),
                                        int((refshape[7] + refshape[5]) / 2.0),
                                        i)
            img["ptcl_source_image"] = str(self.imagefile)
            if self.invert: img.mult(-1.0)
            img.process_inplace("normalize.edgemean")
            stack.append(img)

        return stack

    def cenalign_stack(self):
        """This will perform an iterative centering process on a stack of particle images, centering each on the average.
	It will modify the current stack of boxing parameters in-place"""

        for it in range(5):
            stack = self.get_boxed_stack()

            # Average the stack, and center it
            av = stack[0].copy()
            for im in stack[1:]:
                av.add(im)
            av.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            av.process_inplace("filter.highpass.gauss", {"cutoff_abs": .02})
            av.process_inplace("xform.centeracf")
            #display((av,av2))

            # align to the average
            for i, im in enumerate(stack):
                im.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
                im.process_inplace("filter.highpass.gauss",
                                   {"cutoff_abs": .02})
                ali = im.align("translational", av)
                trans = ali["xform.align2d"].get_trans()
                shape = self.tiltshapes[i]
                shape.translate(-trans[0], -trans[1])

        # Update the stack display
        stack = self.get_boxed_stack()
        self.imboxed.set_data(stack)

    def reconstruct_wedgefill(self, stack, angstep, mode=2):
        """Fills the missing wedge with the average of the slices"""
        print "Making 3D tomofill"

        taxis = float(self.btiltaxisval.text())
        boxsize = stack[0]["nx"]
        pad = Util.calc_best_fft_size(int(boxsize * 1.5))

        # average all of the slices together
        av = stack[0].copy()
        for p in stack[1:]:
            av += p
        av.del_attr("xform.projection")
        av.mult(1.0 / (len(stack)))
        av = av.get_clip(
            Region(-(pad - boxsize) / 2, -(pad - boxsize) / 2, pad, pad))

        for i, p in enumerate(stack):
            p["alt"] = (i - len(stack) / 2) * angstep

        # Determine a good angular step for filling Fourier space
        fullsamp = 360.0 / (boxsize * pi)
        if angstep / fullsamp > 2.0:
            samp = 1.0 / (floor(angstep / fullsamp))
        else:
            samp = angstep

        print "Subsampling = %1.2f" % samp

        # Now the reconstruction
        recon = Reconstructors.get(
            "fourier", {
                "sym": "c1",
                "size": (pad, pad, pad),
                "mode": reconmodes[mode],
                "verbose": True
            })
        recon.setup()

        for ri in range(5):
            print "Iteration ", ri
            for a in [
                    i * samp for i in range(-int(90.0 / samp),
                                            int(90.0 / samp) + 1)
            ]:
                for ii in range(len(stack) - 1):
                    if stack[ii]["alt"] <= a and stack[ii + 1]["alt"] > a:
                        break
                else:
                    ii = -1

                if a < stack[0]["alt"]:
                    p = av
                    #frac=0.5*(a-stack[0]["alt"])/(-90.0-stack[0]["alt"])
                    ## a bit wierd. At the ends (missing wedge) we use the average over all tilts. This could be improved
                    #p=stack[0].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*(1.0-frac)+stack[-1].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*frac
#					print a," avg ",frac,stack[0]["alt"]
                elif ii == -1:
                    p = av
                    #frac=0.5*(a-stack[-1]["alt"])/(90.0-stack[-1]["alt"])+.5
                    ## a bit wierd. At the ends (missing wedge) we use the average over all tilts. This could be improved
                    #p=stack[-1].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*(1.0-frac)+stack[0].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*frac
#					print a," avg ",frac
                else:
                    # We average slices in real space, producing a rotational 'smearing' effect
                    frac = (a - stack[ii]["alt"]) / angstep
                    p = stack[ii].get_clip(
                        Region(-(pad - boxsize) / 2, -(pad - boxsize) / 2, pad,
                               pad)) * (1.0 - frac) + stack[ii + 1].get_clip(
                                   Region(-(pad - boxsize) / 2,
                                          -(pad - boxsize) / 2, pad,
                                          pad)) * frac
#					print a,ii,ii+1,stack[ii]["alt"],frac

                xf = Transform({
                    "type": "eman",
                    "alt": a,
                    "az": -taxis,
                    "phi": taxis
                })
                p["xform.projection"] = xf

                if ri % 2 == 1:
                    recon.determine_slice_agreement(p, xf, 1)
                else:
                    recon.insert_slice(p, xf)

        ret = recon.finish()
        print "Done"
        ret = ret.get_clip(
            Region((pad - boxsize) / 2, (pad - boxsize) / 2,
                   (pad - boxsize) / 2, boxsize, boxsize, boxsize))
        ret.process_inplace("normalize.edgemean")
        #		ret=ret.get_clip(Region((pad-boxsize)/2,(pad-boxsize)/2,(pad-boxsize)/2,boxsize,boxsize,boxsize))

        return ret

    def reconstruct_ca(self, stack, angstep, mode=2):
        """Cylindrically averaged tomographic model, generally used for filling empty spaces. Returned volume is padded."""
        print "Making CA"

        taxis = float(self.btiltaxisval.text())
        boxsize = stack[0]["nx"]
        pad = Util.calc_best_fft_size(int(boxsize * 1.5))

        # average all of the slices together
        av = stack[0].copy()
        for p in stack[1:]:
            av += p
        av.del_attr("xform.projection")
        p.mult(1.0 / len(stack))
        av = av.get_clip(
            Region(-(pad - boxsize) / 2, -(pad - boxsize) / 2, pad, pad))

        recon = Reconstructors.get("fourier", {
            "quiet": True,
            "sym": "c1",
            "x_in": pad,
            "y_in": pad
        })
        recon.setup()

        for ri in range(3):
            if ri > 0:
                alt = -180.0
                while (alt < 180.0):
                    recon.determine_slice_agreement(
                        av,
                        Transform({
                            "type": "eman",
                            "alt": alt,
                            "az": -taxis,
                            "phi": taxis
                        }), 1)
                    alt += angstep
            alt = -180.0
            while (alt < 180.0):
                recon.insert_slice(
                    av,
                    Transform({
                        "type": "eman",
                        "alt": alt,
                        "az": -taxis,
                        "phi": taxis
                    }))
                alt += angstep

        ret = recon.finish()
        ret.process_inplace("normalize.edgemean")
        #		ret=ret.get_clip(Region((pad-boxsize)/2,(pad-boxsize)/2,(pad-boxsize)/2,boxsize,boxsize,boxsize))

        return ret

    def reconstruct(self, stack, angstep, mode=0, initmodel=None):
        """ Tomographic reconstruction of the current stack """
        if initmodel != None: print "Using initial model"

        taxis = float(self.btiltaxisval.text())

        boxsize = stack[0]["nx"]
        pad = good_size(int(boxsize * 1.5))

        for i, p in enumerate(stack):
            p["xform.projection"] = Transform({
                "type": "eman",
                "alt": (i - len(stack) / 2) * angstep,
                "az": -taxis,
                "phi": taxis
            })

        recon = Reconstructors.get(
            "fourier", {
                "sym": "c1",
                "size": (pad, pad, pad),
                "mode": reconmodes[mode],
                "verbose": True
            })
        if initmodel != None: recon.setup(initmodel, .01)
        else: recon.setup()
        scores = []

        # First pass to assess qualities and normalizations
        for i, p in enumerate(stack):
            p2 = p.get_clip(
                Region(-(pad - boxsize) / 2, -(pad - boxsize) / 2, pad, pad))
            p2 = recon.preprocess_slice(p2, p["xform.projection"])
            recon.insert_slice(p2, p["xform.projection"], 1.0)
            print " %d    \r" % i
        print ""

        # after building the model once we can assess how well everything agrees
        for p in stack:
            p2 = p.get_clip(
                Region(-(pad - boxsize) / 2, -(pad - boxsize) / 2, pad, pad))
            p2 = recon.preprocess_slice(p2, p["xform.projection"])
            recon.determine_slice_agreement(p2, p["xform.projection"], 1.0,
                                            True)
            scores.append((p2["reconstruct_absqual"], p2["reconstruct_norm"]))
            print " %d\t%1.3f    \r" % (i, scores[-1][0])
        print ""

        # clear out the first reconstruction (probably no longer necessary)
        #		ret=recon.finish(True)
        #		ret=None

        # setup for the second run
        if initmodel != None: recon.setup(initmodel, .01)
        else: recon.setup()

        thr = 0.7 * (scores[len(scores) / 2][0] +
                     scores[len(scores) / 2 - 1][0] +
                     scores[len(scores) / 2 + 1][0]) / 3
        # this is rather arbitrary
        # First pass to assess qualities and normalizations
        for i, p in enumerate(stack):
            if scores[i][0] < thr:
                print "%d. %1.3f *" % (i, scores[i][0])
                continue

            print "%d. %1.2f \t%1.3f\t%1.3f" % (
                i, p["xform.projection"].get_rotation("eman")["alt"],
                scores[i][0], scores[i][1])
            p2 = p.get_clip(
                Region(-(pad - boxsize) / 2, -(pad - boxsize) / 2, pad, pad))
            p2 = recon.preprocess_slice(p2, p["xform.projection"])
            p2.mult(scores[i][1])
            recon.insert_slice(p2, p["xform.projection"], 1.0)

#		plot(scores)

        recon.set_param("savenorm", "norm.mrc")
        ret = recon.finish(True)
        ret = ret.get_clip(
            Region((pad - boxsize) / 2, (pad - boxsize) / 2,
                   (pad - boxsize) / 2, boxsize, boxsize, boxsize))
        #		print "Quality: ",qual

        return ret

    def tilt_axis(self):
        ntilt = self.imageparm["nz"]
        sz = good_size(self.imageparm["nx"] / 2)
        while 1:
            av = None
            n = 0
            for i in range(ntilt):
                refshape = self.tiltshapes[i].getShape()
                if refshape[4] <= sz / 2 or refshape[
                        5] <= sz / 2 or self.imageparm["nx"] - refshape[
                            4] <= sz / 2 or self.imageparm["ny"] - refshape[
                                5] <= sz / 2:
                    break
                img = EMData(
                    self.imagefile, 0, False,
                    Region(refshape[4] - sz / 2, refshape[5] - sz / 2, i, sz,
                           sz, 1))
                if self.invert: img.mult(-1.0)
                img.process_inplace("normalize.edgemean")

                if av == None: av = img
                else: av.add(img)
                n += 1

            if n == ntilt: break
            sz /= 2
            if sz < 32: return
            print "You may wish to center on a feature closer to the center of the image next time -> ", sz

        sz2 = good_size(sz + 128)
        av2 = av.get_clip(Region((sz - sz2) / 2, (sz - sz2) / 2, sz2, sz2))
        av2.process_inplace("mask.zeroedgefill")
        av2.process_inplace("filter.flattenbackground", {"radius": 64})
        av = av2.get_clip(Region((sz2 - sz) / 2, (sz2 - sz) / 2, sz, sz))
        av.process_inplace("normalize.edgemean")
        av.process_inplace("mask.sharp", {"outer_radius": sz / 2 - 1})

        #		display(av)
        f = av.do_fft()
        d = f.calc_az_dist(360, -90.25, 0.5, 10.0, sz / 2 - 1)
        d = [(i, j * 0.5 - 90) for j, i in enumerate(d)]
        self.btiltaxisval.setText(str(max(d)[1]))


#		print max(d)
#		print min(d)
#		plot(d)

    def projection_align(self, angstep=2.0):
        """realign the current set of boxes using iterative projection matching"""

        taxis = float(self.btiltaxisval.text())

        stack = self.get_boxed_stack()
        for i, p in enumerate(stack):
            ort = Transform({
                "type": "eman",
                "alt": (i - len(stack) / 2) * angstep,
                "az": -taxis,
                "phi": taxis
            })  # is this right ?
            curshape = self.tiltshapes[i].getShape()

            # Read the reference at the user specified size, then pad it a bit
            ref = self.map3d.project("standard", ort)
            ref.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            ref.process_inplace("normalize.edgemean")
            ref = ref.get_clip(
                Region(-self.maxshift, -self.maxshift,
                       ref["nx"] + self.maxshift * 2,
                       ref["ny"] + self.maxshift * 2))

            # when we read the alignment target, we pad with actual image data since the object will have moved
            trg = EMData(
                self.imagefile, 0, False,
                Region(curshape[4] - self.maxshift,
                       curshape[5] - self.maxshift, i,
                       curshape[6] - curshape[4] + self.maxshift * 2,
                       curshape[7] - curshape[5] + self.maxshift * 2, 1))
            trg.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            trg.process_inplace("normalize.edgemean")
            if self.invert: trg.mult(-1.0)

            aln = ref.align("translational", trg, {
                "intonly": 1,
                "maxshift": self.maxshift * 4 / 5
            })
            trans = aln["xform.align2d"].get_trans()
            print i, trans[0], trans[1]
            if i > len(stack) - 4: display([ref, trg, aln])
            #			if i==self.curtilt+3 : display((ref,trg,aln,ref.calc_ccf(trg)))

            self.tiltshapes[i].translate(trans[0], trans[1])

    def find_boxes(self, mainshape):
        """Starting with a user selected box at the current tilt, search for the same shape in the entire
	tilt series"""

        if self.imagefile == None: return

        self.tiltshapes[self.curtilt] = mainshape

        lref = None
        for i in range(self.curtilt + 1, self.imageparm["nz"]):
            refshape = self.tiltshapes[i - 1].getShape()

            # Read the reference at the user specified size, then pad it a bit
            ref = EMData(
                self.imagefile, 0, False,
                Region(refshape[4], refshape[5], i - 1,
                       refshape[6] - refshape[4], refshape[7] - refshape[5],
                       1))
            ref.process_inplace("threshold.clampminmax.nsigma",
                                {"nsigma": 4.0})
            ref.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            ref.process_inplace("normalize.edgemean")
            ref = ref.get_clip(
                Region(-self.maxshift, -self.maxshift,
                       ref["nx"] + self.maxshift * 2,
                       ref["ny"] + self.maxshift * 2))
            if lref != None and self.seqali: ref.add(lref)
            ref.process_inplace(
                "normalize.edgemean")  # older images contribute less
            lref = ref

            # when we read the alignment target, we pad with actual image data since the object will have moved
            trg = EMData(
                self.imagefile, 0, False,
                Region(refshape[4] - self.maxshift,
                       refshape[5] - self.maxshift, i,
                       refshape[6] - refshape[4] + self.maxshift * 2,
                       refshape[7] - refshape[5] + self.maxshift * 2, 1))
            trg.process_inplace("threshold.clampminmax.nsigma",
                                {"nsigma": 4.0})
            trg.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            trg.process_inplace("normalize.edgemean")

            aln = ref.align("translational", trg, {
                "intonly": 1,
                "maxshift": self.maxshift * 4 / 5,
                "masked": 1
            })
            ref.write_image("dbug.hdf", -1)
            trg.write_image("dbug.hdf", -1)
            aln.write_image("dbug.hdf", -1)
            trans = aln["xform.align2d"].get_trans()
            #			if i==self.curtilt+3 : display((ref,trg,aln,ref.calc_ccf(trg)))

            self.tiltshapes[i] = EMShape([
                "rectpoint", .7, .2, 0, refshape[4] + trans[0],
                refshape[5] + trans[1], refshape[6] + trans[0],
                refshape[7] + trans[1], 1
            ])
            print i, trans[0], trans[1]

        lref = None
        for i in range(self.curtilt - 1, -1, -1):
            refshape = self.tiltshapes[i + 1].getShape()

            # Read the reference at the user specified size, then pad it a bit
            ref = EMData(
                self.imagefile, 0, False,
                Region(refshape[4], refshape[5], i + 1,
                       refshape[6] - refshape[4], refshape[7] - refshape[5],
                       1))
            ref.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            ref.process_inplace("normalize.edgemean")
            ref = ref.get_clip(
                Region(-self.maxshift, -self.maxshift,
                       ref["nx"] + self.maxshift * 2,
                       ref["ny"] + self.maxshift * 2))
            if lref != None and self.seqali: ref.add(lref)
            ref.process_inplace("normalize.edgemean")
            lref = ref

            # when we read the alignment target, we pad with actual image data since the object will have moved
            trg = EMData(
                self.imagefile, 0, False,
                Region(refshape[4] - self.maxshift,
                       refshape[5] - self.maxshift, i,
                       refshape[6] - refshape[4] + self.maxshift * 2,
                       refshape[7] - refshape[5] + self.maxshift * 2, 1))
            trg.process_inplace("filter.lowpass.gauss", {"cutoff_abs": .1})
            trg.process_inplace("normalize.edgemean")

            aln = ref.align("translational", trg, {
                "intonly": 1,
                "maxshift": self.maxshift * 4 / 5,
                "masked": 1
            })
            trans = aln["xform.align2d"].get_trans()
            if i == self.curtilt + 3:
                display((ref, trg, aln, ref.calc_ccf(trg)))

            self.tiltshapes[i] = EMShape([
                "rectpoint", .7, .2, 0, refshape[4] + trans[0],
                refshape[5] + trans[1], refshape[6] + trans[0],
                refshape[7] + trans[1], 1
            ])
            print i, trans[0], trans[1]

        self.update_stack()
Exemplo n.º 2
0
class EMItem3DInspector(QtGui.QTabWidget):
    """
	Class to make the EMItem GUI controls
	"""
    def __init__(self, name, item3d):
        QtGui.QTabWidget.__init__(self)
        self.item3d = weakref.ref(item3d)
        self.name = name
        self.inspector = None
        self.transfromboxmaxheight = 400  # This might be problematic

        self.addTabs()

    def setInspector(self, inspector):
        """ This is a reference back to the main inspector, which holds all the item inspectors"""
        self.inspector = weakref.ref(inspector)

    def addTabs(self):
        """ Add a tab for each 'column' """
        tabwidget = QtGui.QWidget()
        gridbox = QtGui.QGridLayout()

        EMItem3DInspector.addControls(self, gridbox)

        tabwidget.setLayout(gridbox)
        self.addTab(tabwidget, "basic")

    def addControls(self, gridbox):
        """ Construct all the widgets in this Item Inspector """
        # selection box and label
        font = QtGui.QFont()
        font.setBold(True)
        label = QtGui.QLabel(self.name, self)
        label.setFont(font)
        label.setAlignment(QtCore.Qt.AlignCenter)
        gridbox.addWidget(label, 0, 0, 1, 1)
        databox = QtGui.QHBoxLayout()
        self.boundingbox = None
        if self.item3d().boundingboxsize:
            self.boundingbox = QtGui.QLabel(
                "Size: " + self.item3d().boundingboxsize, self)
            databox.addWidget(self.boundingbox)
        gridbox.addLayout(databox, 1, 0, 1, 1)
        # angluar controls
        xformframe = QtGui.QFrame()
        xformframe.setFrameShape(QtGui.QFrame.StyledPanel)
        xformbox = QtGui.QGridLayout()
        xformlabel = QtGui.QLabel("Transformation", xformframe)
        xformlabel.setFont(font)
        xformlabel.setAlignment(QtCore.Qt.AlignCenter)
        xformbox.addWidget(xformlabel, 0, 0, 1, 2)
        # Rotations
        self.rotcombobox = QtGui.QComboBox()
        xformbox.addWidget(self.rotcombobox, 1, 0, 1, 2)
        self.rotstackedwidget = QtGui.QStackedWidget()
        self.addRotationWidgets()
        xformbox.addWidget(self.rotstackedwidget, 2, 0, 1, 2)
        #translations
        txlabel = QtGui.QLabel("TX", xformframe)
        txlabel.setAlignment(QtCore.Qt.AlignCenter)
        xformbox.addWidget(txlabel, 3, 0, 1, 1)
        tylabel = QtGui.QLabel("TY", xformframe)
        tylabel.setAlignment(QtCore.Qt.AlignCenter)
        xformbox.addWidget(tylabel, 3, 1, 1, 1)
        self.tx = EMSpinWidget(0.0, 1.0)
        self.ty = EMSpinWidget(0.0, 1.0)
        xformbox.addWidget(self.tx, 4, 0, 1, 1)
        xformbox.addWidget(self.ty, 4, 1, 1, 1)
        tzlabel = QtGui.QLabel("TZ", xformframe)
        tzlabel.setAlignment(QtCore.Qt.AlignCenter)
        xformbox.addWidget(tzlabel, 5, 0, 1, 1)
        zoomlabel = QtGui.QLabel("Zoom", xformframe)
        zoomlabel.setAlignment(QtCore.Qt.AlignCenter)
        xformbox.addWidget(zoomlabel, 5, 1, 1, 1)
        self.tz = EMSpinWidget(0.0, 1.0)
        self.zoom = EMSpinWidget(1.0, 0.1, postivemode=True, wheelstep=0.1)
        xformbox.addWidget(self.tz, 6, 0, 1, 1)
        xformbox.addWidget(self.zoom, 6, 1, 1, 1)
        self.resetbuttontx = QtGui.QPushButton("Reset Tx")
        self.resetbuttonrot = QtGui.QPushButton("Reset Rot")
        xformbox.addWidget(self.resetbuttontx, 7, 0, 1, 1)
        xformbox.addWidget(self.resetbuttonrot, 7, 1, 1, 1)
        xformframe.setLayout(xformbox)
        xformframe.setMaximumWidth(350)

        xformframe.setMaximumHeight(self.transfromboxmaxheight)
        xformframe.setLayout(xformbox)
        gridbox.addWidget(xformframe, 2, 0, 1, 1)

        # set to default, but run only as a base class
        if type(self) == EMItem3DInspector: self.updateItemControls()

        QtCore.QObject.connect(self.tx, QtCore.SIGNAL("valueChanged(int)"),
                               self._on_translation)
        QtCore.QObject.connect(self.ty, QtCore.SIGNAL("valueChanged(int)"),
                               self._on_translation)
        QtCore.QObject.connect(self.tz, QtCore.SIGNAL("valueChanged(int)"),
                               self._on_translation)
        QtCore.QObject.connect(self.zoom, QtCore.SIGNAL("valueChanged(int)"),
                               self._on_scale)
        QtCore.QObject.connect(self.resetbuttontx, QtCore.SIGNAL("clicked()"),
                               self._on_resettx)
        QtCore.QObject.connect(self.resetbuttonrot, QtCore.SIGNAL("clicked()"),
                               self._on_resetrot)

    def _on_translation(self, value):
        """
		Need to contain the right coords. And do translation in the correct corrd system
		"""
        tt = t = Transform({
            "tx": self.tx.getValue(),
            "ty": self.ty.getValue(),
            "tz": self.tz.getValue()
        })
        tp = self.item3d().getParentMatrixProduct()
        if tp: tt = tp.inverse() * t
        self.item3d().getTransform().set_trans(tt.get_trans())
        self.inspector().updateSceneGraph()

    def _on_scale(self, value):
        self.item3d().getTransform().set_scale(self.zoom.getValue())
        self.inspector().updateSceneGraph()

    def _on_resettx(self):

        self.item3d().getTransform().set_trans(0.0, 0.0, 0.0)
        self.updateItemControls()
        self.inspector().updateSceneGraph()

    def _on_resetrot(self):
        self.item3d().getTransform().set_rotation({
            "type": "eman",
            "az": 0.0,
            "alt": 0.0,
            "phi": 0.0
        })
        self.updateItemControls()
        self.inspector().updateSceneGraph()

    def _isRotNaN(self, rot1, rot2, rot3):
        """ Better check to make sure get_rotation did not return Nan, so to prevent a crash """
        if rot1 != rot1: return True
        if rot2 != rot2: return True
        if rot3 != rot3: return True
        return False

    def updateItemControls(self):
        """ Updates this item inspector. Function is called by the item it observes"""
        # Translation update
        stdtransfrom = self.item3d().getTransformStdCoord()
        translation = stdtransfrom.get_trans()

        self.tx.setValue(translation[0])
        self.ty.setValue(translation[1])
        self.tz.setValue(translation[2])
        # Rotation update
        rotation = stdtransfrom.get_rotation(
            str(self.rotcombobox.currentText()))
        is_identity = stdtransfrom.is_rot_identity()
        comboboxidx = self.rotcombobox.currentIndex()
        if comboboxidx == 0:
            if self._isRotNaN(rotation["az"], rotation["alt"],
                              rotation["phi"]):
                return
            self.emanazslider.setValue(rotation["az"], quiet=1)
            self.emanaltslider.setValue(rotation["alt"], quiet=1)
            self.emanphislider.setValue(rotation["phi"], quiet=1)
        if comboboxidx == 1:
            if self._isRotNaN(rotation["gamma"], rotation["beta"],
                              rotation["alpha"]):
                return
            self.imagicgammaslider.setValue(rotation["gamma"], quiet=1)
            self.imagicbetaslider.setValue(rotation["beta"], quiet=1)
            self.imagicalphaslider.setValue(rotation["alpha"], quiet=1)
        if comboboxidx == 2:
            if self._isRotNaN(rotation["psi"], rotation["theta"],
                              rotation["phi"]):
                return
            self.spiderpsislider.setValue(rotation["psi"], quiet=1)
            self.spiderthetaslider.setValue(rotation["theta"], quiet=1)
            self.spiderphislider.setValue(rotation["phi"], quiet=1)
        if comboboxidx == 3:
            if self._isRotNaN(rotation["phi"], rotation["theta"],
                              rotation["omega"]):
                return
            self.mrcpsislider.setValue(rotation["phi"], quiet=1)
            self.mrcthetaslider.setValue(rotation["theta"], quiet=1)
            self.mrcomegaslider.setValue(rotation["omega"], quiet=1)
        if comboboxidx == 4:
            if self._isRotNaN(rotation["ztilt"], rotation["ytilt"],
                              rotation["xtilt"]):
                return
            self.xyzzslider.setValue(rotation["ztilt"], quiet=1)
            self.xyzyslider.setValue(rotation["ytilt"], quiet=1)
            self.xyzxslider.setValue(rotation["xtilt"], quiet=1)
        if comboboxidx == 5:
            if self._isRotNaN(rotation["n1"], rotation["n2"], rotation["n3"]):
                return
            if is_identity and self.spinn1slider.getValue(
            ) == 0.0 and self.spinn2slider.getValue(
            ) == 0.0 and self.spinn3slider.getValue() == 0.0:
                self.spinomegaslider.setValue(0.0, quiet=1)
                self.spinn1slider.setValue(0.0, quiet=1)
                self.spinn2slider.setValue(0.0, quiet=1)
                self.spinn3slider.setValue(1.0, quiet=1)
            else:
                self.spinomegaslider.setValue(rotation["omega"], quiet=1)
                # Don't change slider if reult is Nan
                if rotation["n1"] == rotation["n1"]:
                    self.spinn1slider.setValue(rotation["n1"], quiet=1)
                if rotation["n2"] == rotation["n2"]:
                    self.spinn2slider.setValue(rotation["n2"], quiet=1)
                if rotation["n3"] == rotation["n3"]:
                    self.spinn3slider.setValue(rotation["n3"], quiet=1)
        if comboboxidx == 6:
            if self._isRotNaN(rotation["n1"], rotation["n2"], rotation["n3"]):
                return
            if is_identity and self.spinn1slider.getValue(
            ) == 0.0 and self.spinn2slider.getValue(
            ) == 0.0 and self.spinn3slider.getValue() == 0.0:
                self.spinomegaslider.setValue(0.0, quiet=1)
                self.sgirotn1slider.setValue(0.0, quiet=1)
                self.sgirotn2slider.setValue(0.0, quiet=1)
                self.sgirotn3slider.setValue(1.0, quiet=1)
            else:
                self.spinomegaslider.setValue(rotation["q"], quiet=1)
                # Don't change slider if reult is Nan
                if rotation["n1"] == rotation["n1"]:
                    self.sgirotn1slider.setValue(rotation["n1"], quiet=1)
                if rotation["n2"] == rotation["n2"]:
                    self.sgirotn2slider.setValue(rotation["n2"], quiet=1)
                if rotation["n3"] == rotation["n3"]:
                    self.sgirotn3slider.setValue(rotation["n3"], quiet=1)
        if comboboxidx == 7:
            if self._isRotNaN(rotation["e1"], rotation["e2"], rotation["e3"]):
                return
            if is_identity:
                self.quaternione0slider.setValue(1.0, quiet=1)
                self.quaternione1slider.setValue(0.0, quiet=1)
                self.quaternione2slider.setValue(0.0, quiet=1)
                self.quaternione3slider.setValue(0.0, quiet=1)
            else:
                self.quaternione0slider.setValue(rotation["e0"], quiet=1)
                self.quaternione1slider.setValue(rotation["e1"], quiet=1)
                self.quaternione2slider.setValue(rotation["e2"], quiet=1)
                self.quaternione3slider.setValue(rotation["e3"], quiet=1)
        # Scaling update
        self.zoom.setValue(self.item3d().getTransform().get_scale())

    def updateMetaData(self):
        """
		I didn't want to put this in update b/c this data doesn't change very often, and I don't want to waste CPU
		Its a judgement call really, less coupling vs. more efficiency
		"""
        if self.boundingbox:
            self.boundingbox.setText("Size: " + self.item3d().boundingboxsize)

    def addRotationWidgets(self):
        """ Add alll the widgets for the various EMAN2 rotation conventions """
        EMANwidget = QtGui.QWidget()
        Imagicwidget = QtGui.QWidget()
        Spiderwidget = QtGui.QWidget()
        MRCwidget = QtGui.QWidget()
        XYZwidget = QtGui.QWidget()
        spinwidget = QtGui.QWidget()
        sgirotwidget = QtGui.QWidget()
        quaternionwidget = QtGui.QWidget()
        # EMAN
        emanbox = QtGui.QVBoxLayout()
        self.emanazslider = ValSlider(EMANwidget, (0.0, 360.0),
                                      "  Az",
                                      rounding=1)
        self.emanaltslider = ValSlider(EMANwidget, (0.0, 180.0),
                                       "Alt",
                                       rounding=1)
        self.emanphislider = ValSlider(EMANwidget, (0.0, 360.0),
                                       "Phi",
                                       rounding=1)
        emanbox.addWidget(self.emanazslider)
        emanbox.addWidget(self.emanaltslider)
        emanbox.addWidget(self.emanphislider)
        EMANwidget.setLayout(emanbox)
        # Imagic
        imagicbox = QtGui.QVBoxLayout()
        self.imagicgammaslider = ValSlider(Imagicwidget, (0.0, 360.0),
                                           "Gamma",
                                           rounding=1)
        self.imagicbetaslider = ValSlider(Imagicwidget, (0.0, 180.0),
                                          "     Beta",
                                          rounding=1)
        self.imagicalphaslider = ValSlider(Imagicwidget, (0.0, 360.0),
                                           "   Alpha",
                                           rounding=1)
        imagicbox.addWidget(self.imagicgammaslider)
        imagicbox.addWidget(self.imagicbetaslider)
        imagicbox.addWidget(self.imagicalphaslider)
        Imagicwidget.setLayout(imagicbox)
        # Spider
        spiderbox = QtGui.QVBoxLayout()
        self.spiderpsislider = ValSlider(Spiderwidget, (0.0, 360.0),
                                         "   Psi",
                                         rounding=1)
        self.spiderthetaslider = ValSlider(Spiderwidget, (0.0, 180.0),
                                           "Theta",
                                           rounding=1)
        self.spiderphislider = ValSlider(Spiderwidget, (0.0, 360.0),
                                         "   Phi",
                                         rounding=1)
        spiderbox.addWidget(self.spiderpsislider)
        spiderbox.addWidget(self.spiderthetaslider)
        spiderbox.addWidget(self.spiderphislider)
        Spiderwidget.setLayout(spiderbox)
        # MRC
        mrcbox = QtGui.QVBoxLayout()
        self.mrcpsislider = ValSlider(MRCwidget, (0.0, 360.0),
                                      "      Psi",
                                      rounding=1)
        self.mrcthetaslider = ValSlider(MRCwidget, (0.0, 180.0),
                                        "  Theta",
                                        rounding=1)
        self.mrcomegaslider = ValSlider(MRCwidget, (0.0, 360.0),
                                        "Omega",
                                        rounding=1)
        mrcbox.addWidget(self.mrcpsislider)
        mrcbox.addWidget(self.mrcthetaslider)
        mrcbox.addWidget(self.mrcomegaslider)
        MRCwidget.setLayout(mrcbox)
        # XYZ
        xyzbox = QtGui.QVBoxLayout()
        self.xyzzslider = ValSlider(XYZwidget, (0.0, 360.0), "Z", rounding=1)
        self.xyzyslider = ValSlider(XYZwidget, (0.0, 180.0), "Y", rounding=1)
        self.xyzxslider = ValSlider(XYZwidget, (0.0, 360.0), "X", rounding=1)
        xyzbox.addWidget(self.xyzzslider)
        xyzbox.addWidget(self.xyzyslider)
        xyzbox.addWidget(self.xyzxslider)
        XYZwidget.setLayout(xyzbox)
        # spin
        spinbox = QtGui.QVBoxLayout()
        self.spinomegaslider = ValSlider(spinwidget, (0.0, 180.0),
                                         "Omega",
                                         rounding=1)
        self.spinn1slider = ValSlider(spinwidget, (0.0, 1.0),
                                      "       N1",
                                      rounding=4)
        self.spinn2slider = ValSlider(spinwidget, (0.0, 1.0),
                                      "       N2",
                                      rounding=4)
        self.spinn3slider = ValSlider(spinwidget, (0.0, 1.0),
                                      "       N3",
                                      rounding=4)
        spinbox.addWidget(self.spinomegaslider)
        spinbox.addWidget(self.spinn1slider)
        spinbox.addWidget(self.spinn2slider)
        spinbox.addWidget(self.spinn3slider)
        spinwidget.setLayout(spinbox)
        # sgirot
        sgirotbox = QtGui.QVBoxLayout()
        self.sgirotqslider = ValSlider(sgirotwidget, (0.0, 180.0),
                                       " Q",
                                       rounding=1)
        self.sgirotn1slider = ValSlider(sgirotwidget, (0.0, 1.0),
                                        "N1",
                                        rounding=4)
        self.sgirotn2slider = ValSlider(sgirotwidget, (0.0, 1.0),
                                        "N2",
                                        rounding=4)
        self.sgirotn3slider = ValSlider(sgirotwidget, (0.0, 1.0),
                                        "N3",
                                        rounding=4)
        sgirotbox.addWidget(self.sgirotqslider)
        sgirotbox.addWidget(self.sgirotn1slider)
        sgirotbox.addWidget(self.sgirotn2slider)
        sgirotbox.addWidget(self.sgirotn3slider)
        sgirotwidget.setLayout(sgirotbox)
        # quaternion
        quaternionbox = QtGui.QVBoxLayout()
        self.quaternione0slider = ValSlider(quaternionwidget, (0.0, 1.0),
                                            "E0",
                                            rounding=4)
        self.quaternione1slider = ValSlider(quaternionwidget, (0.0, 1.0),
                                            "E1",
                                            rounding=4)
        self.quaternione2slider = ValSlider(quaternionwidget, (0.0, 1.0),
                                            "E2",
                                            rounding=4)
        self.quaternione3slider = ValSlider(quaternionwidget, (0.0, 1.0),
                                            "E3",
                                            rounding=4)
        quaternionbox.addWidget(self.quaternione0slider)
        quaternionbox.addWidget(self.quaternione1slider)
        quaternionbox.addWidget(self.quaternione2slider)
        quaternionbox.addWidget(self.quaternione3slider)
        quaternionwidget.setLayout(quaternionbox)
        # Add widgets to the stack
        self.rotstackedwidget.addWidget(EMANwidget)
        self.rotstackedwidget.addWidget(Imagicwidget)
        self.rotstackedwidget.addWidget(Spiderwidget)
        self.rotstackedwidget.addWidget(MRCwidget)
        self.rotstackedwidget.addWidget(XYZwidget)
        self.rotstackedwidget.addWidget(spinwidget)
        self.rotstackedwidget.addWidget(sgirotwidget)
        self.rotstackedwidget.addWidget(quaternionwidget)
        # add choices to combobox
        self.rotcombobox.addItem("EMAN")
        self.rotcombobox.addItem("Imagic")
        self.rotcombobox.addItem("Spider")
        self.rotcombobox.addItem("MRC")
        self.rotcombobox.addItem("XYZ")
        self.rotcombobox.addItem("spin")
        self.rotcombobox.addItem("sgirot")
        self.rotcombobox.addItem("quaternion")

        # Signal for all sliders
        QtCore.QObject.connect(self.rotcombobox,
                               QtCore.SIGNAL("activated(int)"),
                               self._rotcombobox_changed)
        QtCore.QObject.connect(self.emanazslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_EMAN_rotation)
        QtCore.QObject.connect(self.emanaltslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_EMAN_rotation)
        QtCore.QObject.connect(self.emanphislider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_EMAN_rotation)
        QtCore.QObject.connect(self.imagicgammaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_Imagic_rotation)
        QtCore.QObject.connect(self.imagicbetaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_Imagic_rotation)
        QtCore.QObject.connect(self.imagicalphaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_Imagic_rotation)
        QtCore.QObject.connect(self.spiderpsislider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_Spider_rotation)
        QtCore.QObject.connect(self.spiderthetaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_Spider_rotation)
        QtCore.QObject.connect(self.spiderphislider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_Spider_rotation)
        QtCore.QObject.connect(self.mrcpsislider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_MRC_rotation)
        QtCore.QObject.connect(self.mrcthetaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_MRC_rotation)
        QtCore.QObject.connect(self.mrcomegaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_MRC_rotation)
        QtCore.QObject.connect(self.xyzzslider, QtCore.SIGNAL("valueChanged"),
                               self._on_XYZ_rotation)
        QtCore.QObject.connect(self.xyzyslider, QtCore.SIGNAL("valueChanged"),
                               self._on_XYZ_rotation)
        QtCore.QObject.connect(self.xyzxslider, QtCore.SIGNAL("valueChanged"),
                               self._on_XYZ_rotation)
        QtCore.QObject.connect(self.spinomegaslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_spin_rotation)
        QtCore.QObject.connect(self.spinn1slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_spin_rotation)
        QtCore.QObject.connect(self.spinn2slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_spin_rotation)
        QtCore.QObject.connect(self.spinn3slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_spin_rotation)
        QtCore.QObject.connect(self.sgirotqslider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_sgirot_rotation)
        QtCore.QObject.connect(self.sgirotn1slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_sgirot_rotation)
        QtCore.QObject.connect(self.sgirotn2slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_sgirot_rotation)
        QtCore.QObject.connect(self.sgirotn3slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_sgirot_rotation)
        QtCore.QObject.connect(self.quaternione0slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_quaternion_rotation)
        QtCore.QObject.connect(self.quaternione1slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_quaternion_rotation)
        QtCore.QObject.connect(self.quaternione2slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_quaternion_rotation)
        QtCore.QObject.connect(self.quaternione3slider,
                               QtCore.SIGNAL("valueChanged"),
                               self._on_quaternion_rotation)

    def _rotcombobox_changed(self, idx):
        self.rotstackedwidget.setCurrentIndex(idx)
        self.updateItemControls()

    def _on_EMAN_rotation(self, value):
        self._set_rotation_std_coords(
            Transform({
                "type": "eman",
                "az": self.emanazslider.getValue(),
                "alt": self.emanaltslider.getValue(),
                "phi": self.emanphislider.getValue()
            }))
        self.inspector().updateSceneGraph()

    def _on_Imagic_rotation(self, value):
        self._set_rotation_std_coords(
            Transform({
                "type": "imagic",
                "gamma": self.imagicgammaslider.getValue(),
                "beta": self.imagicbetaslider.getValue(),
                "alpha": self.imagicalphaslider.getValue()
            }))
        self.inspector().updateSceneGraph()

    def _on_Spider_rotation(self, value):
        self._set_rotation_std_coords(
            Transform({
                "type": "spider",
                "psi": self.spiderpsislider.getValue(),
                "theta": self.spiderthetaslider.getValue(),
                "phi": self.spiderphislider.getValue()
            }))
        self.inspector().updateSceneGraph()

    def _on_MRC_rotation(self, value):
        self._set_rotation_std_coords(
            Transform({
                "type": "mrc",
                "phi": self.mrcpsislider.getValue(),
                "theta": self.mrcthetaslider.getValue(),
                "omega": self.mrcomegaslider.getValue()
            }))
        self.inspector().updateSceneGraph()

    def _on_XYZ_rotation(self, value):
        self._set_rotation_std_coords(
            Transform({
                "type": "xyz",
                "ztilt": self.xyzzslider.getValue(),
                "ytilt": self.xyzyslider.getValue(),
                "xtilt": self.xyzxslider.getValue()
            }))
        self.inspector().updateSceneGraph()

    def _on_spin_rotation(self, value):
        v = Vec3f(self.spinn1slider.getValue(), self.spinn2slider.getValue(),
                  self.spinn3slider.getValue())
        v.normalize()
        self._set_rotation_std_coords(
            Transform({
                "type": "spin",
                "omega": self.spinomegaslider.getValue(),
                "n1": v[0],
                "n2": v[1],
                "n3": v[2]
            }))
        self.inspector().updateSceneGraph()

    def _on_sgirot_rotation(self, value):
        v = Vec3f(self.sgirotn1slider.getValue(),
                  self.sgirotn2slider.getValue(),
                  self.sgirotn3slider.getValue())
        v.normalize()
        self._set_rotation_std_coords(
            Transform({
                "type": "sgirot",
                "q": self.sgirotqslider.getValue(),
                "n1": v[0],
                "n2": v[1],
                "n3": v[2]
            }))
        self.inspector().updateSceneGraph()

    def _on_quaternion_rotation(self, value):
        v = Vec4f(self.quaternione0slider.getValue(),
                  self.quaternione1slider.getValue(),
                  self.quaternione2slider.getValue(),
                  self.quaternione3slider.getValue())
        v.normalize()
        self._set_rotation_std_coords(
            Transform({
                "type": "quaternion",
                "e0": v[0],
                "e1": v[1],
                "e2": v[2],
                "e3": v[3]
            }))
        self.inspector().updateSceneGraph()

    def _set_rotation_std_coords(self, rotation):
        """ This function sets the rotation as if there were no preceeding ones, otherwise a rot around Z could be arounf y,x, etc.
		Works by transforming local coords into global corrds"""
        tt = rotation
        tp = self.item3d().getParentMatrixProduct()
        if tp: tt = tp.inverse() * rotation
        self.item3d().getTransform().set_rotation(tt.get_rotation())
Exemplo n.º 3
0
class TrackerControl(QtGui.QWidget):
	def __init__(self,app,maxshift,invert=False,seqali=False,tiltstep=2.0):
		self.app=app
		self.maxshift=maxshift
		self.seqali=seqali
		self.invert=invert
		self.tiltstep=tiltstep
		
		# the control panel
		QtGui.QWidget.__init__(self,None)

		self.gbl = QtGui.QGridLayout(self)
		self.gbl.setMargin(0)
		self.gbl.setSpacing(6)
		self.gbl.setObjectName("hbl")
		
		# action buttons
		self.bcenalign=QtGui.QPushButton("Center Align")
		self.bprojalign=QtGui.QPushButton("Proj. Realign")
		self.btiltaxis=QtGui.QPushButton("Tilt Axis")
		self.btiltaxisval=QtGui.QLineEdit("90.0")
		self.bsavedata=QtGui.QPushButton("Save Data")
		self.breconst=QtGui.QPushButton("3D Normal")
		self.sbmode=QtGui.QSpinBox(self)
		self.sbmode.setRange(0,2)
		self.sbmode.setValue(0)
		self.bmagict=QtGui.QPushButton("3D Tomofill")
		self.bmagics=QtGui.QPushButton("3D Sph")
		self.bmagicc=QtGui.QPushButton("3D Cyl")
		self.vslpfilt=ValSlider(self,(0,.5),"Filter",0.5,50)
		
		self.gbl.addWidget(self.bcenalign,0,0)
		self.gbl.addWidget(self.bprojalign,0,1)
		self.gbl.addWidget(self.btiltaxis,0,2)
		self.gbl.addWidget(self.btiltaxisval,0,3)
#		self.gbl.addWidget(self.bsavedata,0,3)
		self.gbl.addWidget(self.breconst,1,0)
		self.gbl.addWidget(self.sbmode,2,0,1,1)
		self.gbl.addWidget(self.vslpfilt,3,0,1,4)
		self.gbl.addWidget(self.bmagict,1,1)
		self.gbl.addWidget(self.bmagics,1,2)
		self.gbl.addWidget(self.bmagicc,1,3)
		
		QtCore.QObject.connect(self.bcenalign,QtCore.SIGNAL("clicked(bool)"),self.do_cenalign)
		QtCore.QObject.connect(self.bprojalign,QtCore.SIGNAL("clicked(bool)"),self.do_projalign)
		QtCore.QObject.connect(self.btiltaxis,QtCore.SIGNAL("clicked(bool)"),self.do_tiltaxis)
		QtCore.QObject.connect(self.bsavedata,QtCore.SIGNAL("clicked(bool)"),self.do_savedata)
		QtCore.QObject.connect(self.breconst,QtCore.SIGNAL("clicked(bool)"),self.do_reconst)
		QtCore.QObject.connect(self.bmagict,QtCore.SIGNAL("clicked(bool)"),self.do_magict)
		QtCore.QObject.connect(self.bmagics,QtCore.SIGNAL("clicked(bool)"),self.do_magics)
		QtCore.QObject.connect(self.bmagicc,QtCore.SIGNAL("clicked(bool)"),self.do_magicc)
		QtCore.QObject.connect(self.vslpfilt,QtCore.SIGNAL("valueChanged"),self.do_filter)

		# the single image display widget
		self.im2d =    EMImage2DWidget(application=app,winid="tomotrackbox.big")
		self.imboxed = EMImage2DWidget(application=app,winid="tomotrackbox.small")
		self.improj =  EMImage2DWidget(application=app,winid="tomotrackbox.proj")
		self.imslice = EMImage2DWidget(application=app,winid="tomotrackbox.3dslice")
		self.imvol =   EMImage3DModule(application=app,winid="tomotrackbox.3d")
	
		# get some signals from the window. 
		QtCore.QObject.connect(self.im2d,QtCore.SIGNAL("mousedown"),self.down)
		QtCore.QObject.connect(self.im2d,QtCore.SIGNAL("mousedrag"),self.drag)
		QtCore.QObject.connect(self.im2d,QtCore.SIGNAL("mouseup"),self.up)
		QtCore.QObject.connect(self.im2d,QtCore.SIGNAL("increment_list_data"),self.change_tilt)
	
		self.imagefile=None
		self.imageparm=None
		self.tiltshapes=None
		self.curtilt=0
		self.oldtilt=self.curtilt
		self.map3d=None
		self.downloc=None
		self.downadjloc=None
		
		self.show()
		self.im2d.show()
		
	def closeEvent(self,event):
		self.im2d.closeEvent(QtGui.QCloseEvent())
		self.imboxed.closeEvent(QtGui.QCloseEvent())
		self.improj.closeEvent(QtGui.QCloseEvent())
		self.imslice.closeEvent(QtGui.QCloseEvent())
		self.imvol.closeEvent(QtGui.QCloseEvent())
		event.accept()
		
	def do_cenalign(self,x=0):
		"""In response to the center align button. Just a wrapper"""
		self.cenalign_stack()
		self.update_stack()
		
	def do_projalign(self,x=0):
		"""In response to the projection align button. Just a wrapper"""
		self.projection_align(self.tiltstep)
		self.update_stack()
#		self.do_reconst()

	def do_tiltaxis(self):
		"""In response to the tilt axis button. Just a wrapper"""
		self.tilt_axis()
		
	def do_reconst(self,x=0):
		"""In response to the normal reconstruction button. Just a wrapper"""
		stack=self.get_boxed_stack()
		mode=self.sbmode.value()
		self.map3d=self.reconstruct(stack,self.tiltstep,mode)
		self.update_3d()

		
	def do_magict(self,x):
		"""In response to tomographic filling reconstruction button. Just a wrapper"""
		stack=self.get_boxed_stack()
#		self.map3d=self.reconstruct_ca(stack[5:-4],0.5)
#		init=self.reconstruct_ca(stack[5:-4],0.5)
		mode=self.sbmode.value()
		self.map3d=self.reconstruct_wedgefill(stack,self.tiltstep,mode)
		self.update_3d()
		
	def do_magics(self,x):
		"""In response to the 3D Sph button. Just a wrapper"""
		return
		
	def do_magicc(self,x):
		"""In response to the 3D cyl button. Just a wrapper"""
		return
		
	def do_filter(self,v):
		"""In response to the filter ValSlider"""
		if self.map3d==None : return
		self.lpfilt=v
		self.update_3d()
		
	def do_savedata(self):
		""
	
	def update_3d(self):
		if self.map3d==None : return
		
		self.filt3d=self.map3d.process("filter.lowpass.gauss",{"cutoff_abs":self.vslpfilt.getValue()})
		
		self.imvol.set_data(self.filt3d)
		self.imvol.show()
		self.imvol.updateGL()

		sz=self.map3d["nx"]
		xsum=self.filt3d.process("misc.directional_sum",{"axis":"x"})
		xsum.set_size(sz,sz,1)
		ysum=self.filt3d.process("misc.directional_sum",{"axis":"y"})
		ysum.set_size(sz,sz,1)
		zsum=self.filt3d.process("misc.directional_sum",{"axis":"z"})
		zsum.set_size(sz,sz,1)
		
		self.improj.set_data([zsum,ysum,xsum])
		self.improj.show()
		self.improj.updateGL()

		self.imslice.set_data(self.filt3d)
		self.imslice.show()
		self.imslice.updateGL()
	
	def update_stack(self):
		stack=self.get_boxed_stack()
		self.imboxed.set_data(stack)
		self.imboxed.show()
		self.imboxed.updateGL()
		

	def set_image(self,fsp):
		"""Takes an ali file to process"""
		self.imageparm=EMData(fsp,0,True).get_attr_dict()
		print "%d slices at %d x %d"%(self.imageparm["nz"],self.imageparm["nx"],self.imageparm["ny"])

		self.imagefile=fsp

		self.curtilt=self.imageparm["nz"]/2
		self.tiltshapes=[None for i in range(self.imageparm["nz"])]
		self.update_tilt()

	def update_tilt(self):
		if self.imagefile==None : return
		
		self.curimg=EMData(self.imagefile,0,False,Region(0,0,self.curtilt,self.imageparm["nx"],self.imageparm["ny"],1))
		if self.invert : self.curimg.mult(-1.0)
		self.im2d.set_data(self.curimg)

		s=EMShape(["scrlabel",.7,.3,0,20.0,20.0,"%d"%self.curtilt,200.0,1])
		self.im2d.add_shape("tilt",s)
		
		if self.tiltshapes[self.curtilt]!=None :
			self.im2d.add_shape("finalbox",self.tiltshapes[self.curtilt])
			
			s0=self.tiltshapes[self.oldtilt].getShape()
			s1=self.tiltshapes[self.curtilt].getShape()
			dx=s0[4]-s1[4]
			dy=s0[5]-s1[5]
			
			self.im2d.set_origin(self.im2d.origin[0]-dx,self.im2d.origin[1]-dy)
			self.oldtilt=self.curtilt
			
		self.im2d.updateGL()

	def change_tilt(self,direc):
		"""When the user presses the up or down arrow"""
		self.oldtilt=self.curtilt
		self.curtilt+=direc
		if self.curtilt<0 : self.curtilt=0
		if self.curtilt>=self.imageparm["nz"] : self.curtilt=self.imageparm["nz"]-1
		
		self.update_tilt()

	def down(self,event,lc):
		"""The event contains the x,y coordinates in window space, lc are the coordinates in image space"""

		if event.buttons()&Qt.LeftButton:
			if event.modifiers()&Qt.ShiftModifier : 
				self.downadjloc=(lc,self.tiltshapes[self.curtilt].getShape()[4:8])
			else :
				self.downloc=lc

	def drag(self,event,lc):
		if self.downloc!=None:
			dx=abs(lc[0]-self.downloc[0])
			dy=abs(lc[1]-self.downloc[1])
			dx=max(dx,dy)	# Make box square
			dx=good_size(dx*2)/2	# use only good sizes
			dy=dx
			s=EMShape(["rectpoint",0,.7,0,self.downloc[0]-dx,self.downloc[1]-dy,self.downloc[0]+dx,self.downloc[1]+dy,1])
			self.im2d.add_shape("box",s)
			s=EMShape(["scrlabel",.7,.7,0,20.0,20.0,"%d (%d x %d)"%(self.curtilt,dx*2,dy*2),200.0,1])
			self.im2d.add_shape("tilt",s)
		elif self.downadjloc!=None:
			dx=(lc[0]-self.downadjloc[0][0])
			dy=(lc[1]-self.downadjloc[0][1])
			s=self.tiltshapes[self.curtilt].getShape()[:]
			s[4]=self.downadjloc[1][0]+dx
			s[5]=self.downadjloc[1][1]+dy
			s[6]=self.downadjloc[1][2]+dx
			s[7]=self.downadjloc[1][3]+dy
			self.im2d.add_shape("box",EMShape(s))

		self.im2d.updateGL()
	
	def up(self,event,lc):
		if self.downloc!=None :
			dx=abs(lc[0]-self.downloc[0])
			dy=abs(lc[1]-self.downloc[1])
			dx=max(dx,dy)	# Make box square
			dx=good_size(dx*2)/2	# use only good sizes
			dy=dx
			s=EMShape(["rectpoint",.7,.2,0,self.downloc[0]-dx,self.downloc[1]-dy,self.downloc[0]+dx,self.downloc[1]+dy,1])
			self.im2d.del_shape("box")
			if hypot(lc[0]-self.downloc[0],lc[1]-self.downloc[1])>5 : 
				self.tiltshapes=[None for i in range(self.imageparm["nz"])]
				self.find_boxes(s)
			
			self.update_tilt()
			self.downloc=None
		elif self.downadjloc!=None :
			dx=(lc[0]-self.downadjloc[0][0])
			dy=(lc[1]-self.downadjloc[0][1])
			s=self.tiltshapes[self.curtilt].getShape()[:]
			s[4]=self.downadjloc[1][0]+dx
			s[5]=self.downadjloc[1][1]+dy
			s[6]=self.downadjloc[1][2]+dx
			s[7]=self.downadjloc[1][3]+dy
			self.tiltshapes[self.curtilt]=EMShape(s)
			self.im2d.add_shape("finalbox",self.tiltshapes[self.curtilt])
			self.im2d.del_shape("box")

			self.update_tilt()
			self.update_stack()
			self.downadjloc=None
			

	def get_boxed_stack(self):
		stack=[]
		for i in range(self.imageparm["nz"]):
			refshape=self.tiltshapes[i].getShape()
			img=EMData(self.imagefile,0,False,Region(refshape[4],refshape[5],i,refshape[6]-refshape[4],refshape[7]-refshape[5],1))
			img["ptcl_source_coord"]=(int((refshape[6]+refshape[4])/2.0),int((refshape[7]+refshape[5])/2.0),i)
			img["ptcl_source_image"]=str(self.imagefile)
			if self.invert : img.mult(-1.0)
			img.process_inplace("normalize.edgemean")
			stack.append(img)
			
		return stack

	def cenalign_stack(self):
		"""This will perform an iterative centering process on a stack of particle images, centering each on the average.
	It will modify the current stack of boxing parameters in-place"""
		
		for it in range(5):
			stack=self.get_boxed_stack()
			
			# Average the stack, and center it
			av=stack[0].copy()
			for im in stack[1:]:
				av.add(im)
			av.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			av.process_inplace("filter.highpass.gauss",{"cutoff_abs":.02})
			av.process_inplace("xform.centeracf")
			#display((av,av2))
			
			# align to the average
			for i,im in enumerate(stack):
				im.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
				im.process_inplace("filter.highpass.gauss",{"cutoff_abs":.02})
				ali=im.align("translational",av)
				trans=ali["xform.align2d"].get_trans()
				shape=self.tiltshapes[i]
				shape.translate(-trans[0],-trans[1])

		# Update the stack display
		stack=self.get_boxed_stack()
		self.imboxed.set_data(stack)
	
	def reconstruct_wedgefill(self,stack,angstep,mode=2):
		"""Fills the missing wedge with the average of the slices"""
		print "Making 3D tomofill"
		
		taxis=float(self.btiltaxisval.text())
		boxsize=stack[0]["nx"]
		pad=Util.calc_best_fft_size(int(boxsize*1.5))

		# average all of the slices together
		av=stack[0].copy()
		for p in stack[1:]: av+=p
		av.del_attr("xform.projection")
		av.mult(1.0/(len(stack)))
		av=av.get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))
		
		for i,p in enumerate(stack) : 
			p["alt"]=(i-len(stack)/2)*angstep
		
		# Determine a good angular step for filling Fourier space
		fullsamp=360.0/(boxsize*pi)
		if angstep/fullsamp>2.0 :
			samp=1.0/(floor(angstep/fullsamp))
		else :
			samp=angstep
		
		print "Subsampling = %1.2f"%samp

		# Now the reconstruction
		recon=Reconstructors.get("fourier", {"sym":"c1","size":(pad,pad,pad),"mode":reconmodes[mode],"verbose":True})
		recon.setup()
		
		for ri in range(5):
			print "Iteration ",ri
			for a in [i*samp for i in range(-int(90.0/samp),int(90.0/samp)+1)]:
				for ii in range(len(stack)-1):
					if stack[ii]["alt"]<=a and stack[ii+1]["alt"]>a : break
				else: ii=-1
				
				if a<stack[0]["alt"] :
					p=av
					#frac=0.5*(a-stack[0]["alt"])/(-90.0-stack[0]["alt"])
					## a bit wierd. At the ends (missing wedge) we use the average over all tilts. This could be improved
					#p=stack[0].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*(1.0-frac)+stack[-1].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*frac
#					print a," avg ",frac,stack[0]["alt"]
				elif ii==-1 :
					p=av
					#frac=0.5*(a-stack[-1]["alt"])/(90.0-stack[-1]["alt"])+.5
					## a bit wierd. At the ends (missing wedge) we use the average over all tilts. This could be improved
					#p=stack[-1].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*(1.0-frac)+stack[0].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*frac
#					print a," avg ",frac
				else:
					# We average slices in real space, producing a rotational 'smearing' effect
					frac=(a-stack[ii]["alt"])/angstep
					p=stack[ii].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*(1.0-frac)+stack[ii+1].get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))*frac
#					print a,ii,ii+1,stack[ii]["alt"],frac
				
				xf=Transform({"type":"eman","alt":a,"az":-taxis,"phi":taxis})
				p["xform.projection"]=xf
						
				if ri%2==1:	
					recon.determine_slice_agreement(p,xf,1)
				else :
					recon.insert_slice(p,xf)
		
		ret=recon.finish()
		print "Done"
		ret=ret.get_clip(Region((pad-boxsize)/2,(pad-boxsize)/2,(pad-boxsize)/2,boxsize,boxsize,boxsize))
		ret.process_inplace("normalize.edgemean")
#		ret=ret.get_clip(Region((pad-boxsize)/2,(pad-boxsize)/2,(pad-boxsize)/2,boxsize,boxsize,boxsize))
		
		return ret
	
	def reconstruct_ca(self,stack,angstep,mode=2):
		"""Cylindrically averaged tomographic model, generally used for filling empty spaces. Returned volume is padded."""
		print "Making CA"
		
		taxis=float(self.btiltaxisval.text())
		boxsize=stack[0]["nx"]
		pad=Util.calc_best_fft_size(int(boxsize*1.5))

		# average all of the slices together
		av=stack[0].copy()
		for p in stack[1:]: av+=p
		av.del_attr("xform.projection")
		p.mult(1.0/len(stack))
		av=av.get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))

		recon=Reconstructors.get("fourier", {"quiet":True,"sym":"c1","x_in":pad,"y_in":pad})
		recon.setup()
		
		for ri in range(3):
			if ri>0 :
				alt=-180.0
				while (alt<180.0):
					recon.determine_slice_agreement(av,Transform({"type":"eman","alt":alt,"az":-taxis,"phi":taxis}),1)
					alt+=angstep
			alt=-180.0
			while (alt<180.0) :
				recon.insert_slice(av,Transform({"type":"eman","alt":alt,"az":-taxis,"phi":taxis}))
				alt+=angstep
		
		ret=recon.finish()
		ret.process_inplace("normalize.edgemean")
#		ret=ret.get_clip(Region((pad-boxsize)/2,(pad-boxsize)/2,(pad-boxsize)/2,boxsize,boxsize,boxsize))
		
		return ret
		
	
	def reconstruct(self,stack,angstep,mode=0,initmodel=None):
		""" Tomographic reconstruction of the current stack """
		if initmodel!=None : print "Using initial model"
		
		taxis=float(self.btiltaxisval.text())
		
		boxsize=stack[0]["nx"]
		pad=good_size(int(boxsize*1.5))
		
		for i,p in enumerate(stack) : p["xform.projection"]=Transform({"type":"eman","alt":(i-len(stack)/2)*angstep,"az":-taxis,"phi":taxis})
		
		recon=Reconstructors.get("fourier", {"sym":"c1","size":(pad,pad,pad),"mode":reconmodes[mode],"verbose":True})
		if initmodel!=None : recon.setup(initmodel,.01)
		else : recon.setup()
		scores=[]
		
		# First pass to assess qualities and normalizations
		for i,p in enumerate(stack):
			p2=p.get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))
			p2=recon.preprocess_slice(p2,p["xform.projection"])
			recon.insert_slice(p2,p["xform.projection"],1.0)
			print " %d    \r"%i
		print ""

		# after building the model once we can assess how well everything agrees
		for p in stack:
			p2=p.get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))
			p2=recon.preprocess_slice(p2,p["xform.projection"])
			recon.determine_slice_agreement(p2,p["xform.projection"],1.0,True)
			scores.append((p2["reconstruct_absqual"],p2["reconstruct_norm"]))
			print " %d\t%1.3f    \r"%(i,scores[-1][0])
		print ""

		# clear out the first reconstruction (probably no longer necessary)
#		ret=recon.finish(True)
#		ret=None
		
		# setup for the second run
		if initmodel!=None : recon.setup(initmodel,.01)
		else : recon.setup()

		thr=0.7*(scores[len(scores)/2][0]+scores[len(scores)/2-1][0]+scores[len(scores)/2+1][0])/3;		# this is rather arbitrary
		# First pass to assess qualities and normalizations
		for i,p in enumerate(stack):
			if scores[i][0]<thr : 
				print "%d. %1.3f *"%(i,scores[i][0])
				continue
			
			print "%d. %1.2f \t%1.3f\t%1.3f"%(i,p["xform.projection"].get_rotation("eman")["alt"],scores[i][0],scores[i][1])
			p2=p.get_clip(Region(-(pad-boxsize)/2,-(pad-boxsize)/2,pad,pad))
			p2=recon.preprocess_slice(p2,p["xform.projection"])
			p2.mult(scores[i][1])
			recon.insert_slice(p2,p["xform.projection"],1.0)

#		plot(scores)
		
		recon.set_param("savenorm","norm.mrc")
		ret=recon.finish(True)
		ret=ret.get_clip(Region((pad-boxsize)/2,(pad-boxsize)/2,(pad-boxsize)/2,boxsize,boxsize,boxsize))
#		print "Quality: ",qual
		
		return ret
	
	def tilt_axis(self):
		ntilt=self.imageparm["nz"]
		sz=good_size(self.imageparm["nx"]/2)
		while 1:
			av=None
			n=0
			for i in range(ntilt):
				refshape=self.tiltshapes[i].getShape()
				if refshape[4]<=sz/2 or refshape[5]<=sz/2 or self.imageparm["nx"]-refshape[4]<=sz/2 or self.imageparm["ny"]-refshape[5]<=sz/2 : break
				img=EMData(self.imagefile,0,False,Region(refshape[4]-sz/2,refshape[5]-sz/2,i,sz,sz,1))
				if self.invert : img.mult(-1.0)
				img.process_inplace("normalize.edgemean")
				
				if av==None: av=img
				else : av.add(img)
				n+=1
				
			if n==ntilt : break
			sz/=2
			if sz<32: return
			print "You may wish to center on a feature closer to the center of the image next time -> ",sz
		
		sz2=good_size(sz+128)
		av2=av.get_clip(Region((sz-sz2)/2,(sz-sz2)/2,sz2,sz2))
		av2.process_inplace("mask.zeroedgefill")
		av2.process_inplace("filter.flattenbackground",{"radius":64})
		av=av2.get_clip(Region((sz2-sz)/2,(sz2-sz)/2,sz,sz))
		av.process_inplace("normalize.edgemean")
		av.process_inplace("mask.sharp",{"outer_radius":sz/2-1})

#		display(av)
		f=av.do_fft()
		d=f.calc_az_dist(360,-90.25,0.5,10.0,sz/2-1)
		d=[(i,j*0.5-90) for j,i in enumerate(d)]
		self.btiltaxisval.setText(str(max(d)[1]))
#		print max(d)
#		print min(d)
#		plot(d)

	
	def projection_align(self,angstep=2.0):
		"""realign the current set of boxes using iterative projection matching"""
		
		taxis=float(self.btiltaxisval.text())

		stack=self.get_boxed_stack()
		for i,p in enumerate(stack) : 
			ort=Transform({"type":"eman","alt":(i-len(stack)/2)*angstep,"az":-taxis,"phi":taxis})		# is this right ?
			curshape=self.tiltshapes[i].getShape()
			
			# Read the reference at the user specified size, then pad it a bit
			ref=self.map3d.project("standard",ort)
			ref.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			ref.process_inplace("normalize.edgemean")
			ref=ref.get_clip(Region(-self.maxshift,-self.maxshift,ref["nx"]+self.maxshift*2,ref["ny"]+self.maxshift*2))
			
			# when we read the alignment target, we pad with actual image data since the object will have moved
			trg=EMData(self.imagefile,0,False,Region(curshape[4]-self.maxshift,curshape[5]-self.maxshift,i,curshape[6]-curshape[4]+self.maxshift*2,curshape[7]-curshape[5]+self.maxshift*2,1))
			trg.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			trg.process_inplace("normalize.edgemean")
			if self.invert : trg.mult(-1.0)
			
			aln=ref.align("translational",trg,{"intonly":1,"maxshift":self.maxshift*4/5})
			trans=aln["xform.align2d"].get_trans()
			print i,trans[0],trans[1]
			if i>len(stack)-4 : display([ref,trg,aln])
#			if i==self.curtilt+3 : display((ref,trg,aln,ref.calc_ccf(trg)))

			self.tiltshapes[i].translate(trans[0],trans[1])

		
	
	def find_boxes(self,mainshape):
		"""Starting with a user selected box at the current tilt, search for the same shape in the entire
	tilt series"""
	
		if self.imagefile==None: return 
		
		self.tiltshapes[self.curtilt]=mainshape
		
		lref=None
		for i in range(self.curtilt+1,self.imageparm["nz"]):
			refshape=self.tiltshapes[i-1].getShape()
			
			# Read the reference at the user specified size, then pad it a bit
			ref=EMData(self.imagefile,0,False,Region(refshape[4],refshape[5],i-1,refshape[6]-refshape[4],refshape[7]-refshape[5],1))
			ref.process_inplace("threshold.clampminmax.nsigma",{"nsigma":4.0})
			ref.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			ref.process_inplace("normalize.edgemean")
			ref=ref.get_clip(Region(-self.maxshift,-self.maxshift,ref["nx"]+self.maxshift*2,ref["ny"]+self.maxshift*2))
			if lref!=None and self.seqali : ref.add(lref)
			ref.process_inplace("normalize.edgemean")		# older images contribute less
			lref=ref
			
			# when we read the alignment target, we pad with actual image data since the object will have moved
			trg=EMData(self.imagefile,0,False,Region(refshape[4]-self.maxshift,refshape[5]-self.maxshift,i,refshape[6]-refshape[4]+self.maxshift*2,refshape[7]-refshape[5]+self.maxshift*2,1))
			trg.process_inplace("threshold.clampminmax.nsigma",{"nsigma":4.0})
			trg.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			trg.process_inplace("normalize.edgemean")
			
			aln=ref.align("translational",trg,{"intonly":1,"maxshift":self.maxshift*4/5,"masked":1})
			ref.write_image("dbug.hdf",-1)
			trg.write_image("dbug.hdf",-1)
			aln.write_image("dbug.hdf",-1)
			trans=aln["xform.align2d"].get_trans()
#			if i==self.curtilt+3 : display((ref,trg,aln,ref.calc_ccf(trg)))

			self.tiltshapes[i]=EMShape(["rectpoint",.7,.2,0,refshape[4]+trans[0],refshape[5]+trans[1],refshape[6]+trans[0],refshape[7]+trans[1],1])
			print i,trans[0],trans[1]
			
		lref=None
		for i in range(self.curtilt-1,-1,-1):
			refshape=self.tiltshapes[i+1].getShape()
			
			# Read the reference at the user specified size, then pad it a bit
			ref=EMData(self.imagefile,0,False,Region(refshape[4],refshape[5],i+1,refshape[6]-refshape[4],refshape[7]-refshape[5],1))
			ref.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			ref.process_inplace("normalize.edgemean")
			ref=ref.get_clip(Region(-self.maxshift,-self.maxshift,ref["nx"]+self.maxshift*2,ref["ny"]+self.maxshift*2))
			if lref!=None and self.seqali : ref.add(lref)
			ref.process_inplace("normalize.edgemean")
			lref=ref
			
			# when we read the alignment target, we pad with actual image data since the object will have moved
			trg=EMData(self.imagefile,0,False,Region(refshape[4]-self.maxshift,refshape[5]-self.maxshift,i,refshape[6]-refshape[4]+self.maxshift*2,refshape[7]-refshape[5]+self.maxshift*2,1))
			trg.process_inplace("filter.lowpass.gauss",{"cutoff_abs":.1})
			trg.process_inplace("normalize.edgemean")
			
			aln=ref.align("translational",trg,{"intonly":1,"maxshift":self.maxshift*4/5,"masked":1})
			trans=aln["xform.align2d"].get_trans()
			if i==self.curtilt+3 : display((ref,trg,aln,ref.calc_ccf(trg)))

			self.tiltshapes[i]=EMShape(["rectpoint",.7,.2,0,refshape[4]+trans[0],refshape[5]+trans[1],refshape[6]+trans[0],refshape[7]+trans[1],1])
			print i,trans[0],trans[1]
		
		self.update_stack()
Exemplo n.º 4
0
class EMTransformPanel:
	def __init__(self,target,parent):
		self.target = weakref.ref(target)
		self.parent = weakref.ref(parent)
		
		self.label_src = QtGui.QLabel(parent)
		self.label_src.setText('Rotation Convention')
		
		self.src = QtGui.QComboBox(parent)
		self.load_src_options(self.src)
		
		self.x_label = QtGui.QLabel()
		self.x_label.setText('x')
		
		self.x_trans = QtGui.QDoubleSpinBox(parent)
		self.x_trans.setMinimum(-10000)
		self.x_trans.setMaximum(10000)
		self.x_trans.setValue(0.0)
	
		self.y_label = QtGui.QLabel()
		self.y_label.setText('y')
		
		self.y_trans = QtGui.QDoubleSpinBox(parent)
		self.y_trans.setMinimum(-10000)
		self.y_trans.setMaximum(10000)
		self.y_trans.setValue(0.0)
		
		self.z_label = QtGui.QLabel()
		self.z_label.setText('z')
		
		self.z_trans = QtGui.QDoubleSpinBox(parent)
		self.z_trans.setMinimum(-10000)
		self.z_trans.setMaximum(10000)
		self.z_trans.setValue(0.0)
		
		self.az = ValSlider(parent,(-360.0,360.0),"az",-1)
		self.az.setObjectName("az")
		self.az.setValue(0.0)
		
		self.alt = ValSlider(parent,(-180.0,180.0),"alt",-1)
		self.alt.setObjectName("alt")
		self.alt.setValue(0.0)
		
		self.phi = ValSlider(parent,(-360.0,360.0),"phi",-1)
		self.phi.setObjectName("phi")
		self.phi.setValue(0.0)
		
		self.scale = ValSlider(parent,(0.01,30.0),"Zoom:")
		self.scale.setObjectName("scale")
		self.scale.setValue(1.0)
		
		self.n3_showing = False
		
		self.current_src = "eman"
		
		QtCore.QObject.connect(self.az, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.alt, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.phi, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.src, QtCore.SIGNAL("currentIndexChanged(QString)"), self.set_src)
		QtCore.QObject.connect(self.scale, QtCore.SIGNAL("valueChanged"), self.target().set_scale)
		QtCore.QObject.connect(self.x_trans, QtCore.SIGNAL("valueChanged(double)"), self.target().set_cam_x)
		QtCore.QObject.connect(self.y_trans, QtCore.SIGNAL("valueChanged(double)"), self.target().set_cam_y)
		QtCore.QObject.connect(self.z_trans, QtCore.SIGNAL("valueChanged(double)"), self.target().set_cam_z)
		
		
	def set_defaults(self):
		self.x_trans.setValue(0.0)
		self.y_trans.setValue(0.0)
		self.z_trans.setValue(0.0)
		self.scale.setValue(1.0)
		self.az.setValue(0.0)
		self.alt.setValue(0.0)
		self.phi.setValue(0.0)
		
	def slider_rotate(self):
		self.target().load_rotation(self.get_current_rotation())
		
	def get_current_rotation(self):
		convention = self.src.currentText()
		rot = {}
		if ( self.current_src == "spin" ):
			rot[self.az.getLabel()] = self.az.getValue()
			
			n1 = self.alt.getValue()
			n2 = self.phi.getValue()
			n3 = self.n3.getValue()
			
			norm = sqrt(n1*n1 + n2*n2 + n3*n3)
			
			n1 /= norm
			n2 /= norm
			n3 /= norm
			
			rot[self.alt.getLabel()] = n1
			rot[self.phi.getLabel()] = n2
			rot[self.n3.getLabel()] = n3
			
		else:
			rot[self.az.getLabel()] = self.az.getValue()
			rot[self.alt.getLabel()] = self.alt.getValue()
			rot[self.phi.getLabel()] = self.phi.getValue()
		
		rot["type"] = self.current_src
		
		return Transform(rot)
	
	def addWidgets(self,target):
		
		target.addWidget(self.scale)
		self.hbl_trans = QtGui.QHBoxLayout()
		self.hbl_trans.setMargin(0)
		self.hbl_trans.setSpacing(6)
		self.hbl_trans.setObjectName("Trans")
		self.hbl_trans.addWidget(self.x_label)
		self.hbl_trans.addWidget(self.x_trans)
		self.hbl_trans.addWidget(self.y_label)
		self.hbl_trans.addWidget(self.y_trans)
		self.hbl_trans.addWidget(self.z_label)
		self.hbl_trans.addWidget(self.z_trans)
		
		target.addLayout(self.hbl_trans)
		
		self.hbl_src = QtGui.QHBoxLayout()
		self.hbl_src.setMargin(0)
		self.hbl_src.setSpacing(6)
		self.hbl_src.setObjectName("hbl")
		self.hbl_src.addWidget(self.label_src)
		self.hbl_src.addWidget(self.src)
		
		
		target.addLayout(self.hbl_src)
		target.addWidget(self.az)
		target.addWidget(self.alt)
		target.addWidget(self.phi)
	
	def set_src(self, val):
		t3d = self.get_current_rotation()
		
		if (self.n3_showing) :
			self.parent().get_transform_layout().removeWidget(self.n3)
			self.n3.deleteLater()
			self.n3_showing = False
			self.az.setRange(-360,360)
			self.alt.setRange(-180,180)
			self.phi.setRange(-360,660)
		
		if ( self.src_map[str(val)] == "spider" ):
			self.az.setLabel('phi')
			self.alt.setLabel('theta')
			self.phi.setLabel('psi')
		elif ( self.src_map[str(val)] == "eman" ):
			self.az.setLabel('az')
			self.alt.setLabel('alt')
			self.phi.setLabel('phi')
		elif ( self.src_map[str(val)] == "imagic"):
			self.az.setLabel('alpha')
			self.alt.setLabel('beta')
			self.phi.setLabel('gamma')
		elif ( self.src_map[str(val)] == "xyz"):
			self.az.setLabel('xtilt')
			self.alt.setLabel('ytilt')
			self.phi.setLabel('ztilt')
		elif ( self.src_map[str(val)] == "mrc" ):
			self.az.setLabel('phi')
			self.alt.setLabel('theta')
			self.phi.setLabel('omega')
		elif ( self.src_map[str(val)] == "spin" ):
			self.az.setLabel('Omega')
			self.alt.setRange(-1,1)
			self.phi.setRange(-1,1)
			
			self.alt.setLabel('n1')
			self.phi.setLabel('n2')
			
			self.n3 = ValSlider(self.parent(),(-360.0,360.0),"n3",-1)
			self.n3.setRange(-1,1)
			self.n3.setObjectName("n3")
			self.parent().get_transform_layout().addWidget(self.n3)
			QtCore.QObject.connect(self.n3, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
			self.n3_showing = True
		
		self.current_src = self.src_map[str(val)]
		self.update_rotations(t3d)
	
	def load_src_options(self,widgit):
		self.load_src()
		for i in self.src_strings:
			widgit.addItem(i)
			
	def load_src(self):
		# supported_rot_conventions
		src_flags = []
		src_flags.append("eman")
		src_flags.append("spider")
		src_flags.append("imagic")
		src_flags.append("mrc")
		src_flags.append("spin")
		src_flags.append("xyz")
		
		self.src_strings = []
		self.src_map = {}
		for i in src_flags:
			self.src_strings.append(str(i))
			self.src_map[str(i)] = i
			
	def update_rotations(self,t3d):
		rot = t3d.get_rotation(self.src_map[str(self.src.itemText(self.src.currentIndex()))])
		
		convention = self.src.currentText()
		if ( self.src_map[str(convention)] == "spin" ):
			self.n3.setValue(rot[self.n3.getLabel()],True)
		
		self.az.setValue(rot[self.az.getLabel()],True)
		self.alt.setValue(rot[self.alt.getLabel()],True)
		self.phi.setValue(rot[self.phi.getLabel()],True)
		
	def set_scale(self,newscale):
		self.scale.setValue(newscale)
		
	def set_xy_trans(self, x, y):
		self.x_trans.setValue(x)
		self.y_trans.setValue(y)
		
	def set_xyz_trans(self, x, y,z):
		self.x_trans.setValue(x)
		self.y_trans.setValue(y)
		self.z_trans.setValue(z)
Exemplo n.º 5
0
class EMItem3DInspector(QtGui.QTabWidget):
	"""
	Class to make the EMItem GUI controls
	"""
	def __init__(self, name, item3d):
		QtGui.QTabWidget.__init__(self)
		self.item3d = weakref.ref(item3d)
		self.name = name
		self.inspector = None
		self.transfromboxmaxheight = 400	# This might be problematic
		
		self.addTabs()	
			
	def setInspector(self, inspector):
		""" This is a reference back to the main inspector, which holds all the item inspectors"""
		self.inspector = weakref.ref(inspector)
		
	def addTabs(self):
		""" Add a tab for each 'column' """
		tabwidget = QtGui.QWidget()
		gridbox = QtGui.QGridLayout()
		
		EMItem3DInspector.addControls(self, gridbox)
		
		tabwidget.setLayout(gridbox)
		self.addTab(tabwidget, "basic")
		
	def addControls(self, gridbox):
		""" Construct all the widgets in this Item Inspector """
		# selection box and label
		font = QtGui.QFont()
		font.setBold(True)
		label = QtGui.QLabel(self.name,self)
		label.setFont(font)
		label.setAlignment(QtCore.Qt.AlignCenter)
		gridbox.addWidget(label, 0, 0, 1, 1)
		databox = QtGui.QHBoxLayout()
		self.boundingbox = None
		if self.item3d().boundingboxsize:
			self.boundingbox = QtGui.QLabel("Size: "+self.item3d().boundingboxsize,self)
			databox.addWidget(self.boundingbox)
		gridbox.addLayout(databox, 1, 0, 1, 1)
		# angluar controls
		xformframe = QtGui.QFrame()
		xformframe.setFrameShape(QtGui.QFrame.StyledPanel)
		xformbox = QtGui.QGridLayout()
		xformlabel = QtGui.QLabel("Transformation", xformframe)
		xformlabel.setFont(font)
		xformlabel.setAlignment(QtCore.Qt.AlignCenter)
		xformbox.addWidget(xformlabel, 0, 0, 1, 2)
		# Rotations
		self.rotcombobox = QtGui.QComboBox()
		xformbox.addWidget(self.rotcombobox, 1, 0, 1, 2)
		self.rotstackedwidget = QtGui.QStackedWidget()
		self.addRotationWidgets()
		xformbox.addWidget(self.rotstackedwidget, 2, 0, 1, 2)
		#translations
		txlabel = QtGui.QLabel("TX",xformframe)
		txlabel.setAlignment(QtCore.Qt.AlignCenter)
		xformbox.addWidget(txlabel, 3, 0, 1, 1)
		tylabel = QtGui.QLabel("TY",xformframe)
		tylabel.setAlignment(QtCore.Qt.AlignCenter)
		xformbox.addWidget(tylabel, 3, 1, 1, 1)
		self.tx = EMSpinWidget(0.0, 1.0)
		self.ty = EMSpinWidget(0.0, 1.0)
		xformbox.addWidget(self.tx, 4, 0, 1, 1)
		xformbox.addWidget(self.ty, 4, 1, 1, 1)
		tzlabel = QtGui.QLabel("TZ",xformframe)
		tzlabel.setAlignment(QtCore.Qt.AlignCenter)
		xformbox.addWidget(tzlabel, 5, 0, 1, 1)
		zoomlabel = QtGui.QLabel("Zoom",xformframe)
		zoomlabel.setAlignment(QtCore.Qt.AlignCenter)
		xformbox.addWidget(zoomlabel, 5, 1, 1, 1)
		self.tz = EMSpinWidget(0.0, 1.0)
		self.zoom = EMSpinWidget(1.0, 0.1, postivemode=True, wheelstep=0.1)
		xformbox.addWidget(self.tz, 6, 0, 1, 1)
		xformbox.addWidget(self.zoom, 6, 1, 1, 1)
		self.resetbuttontx = QtGui.QPushButton("Reset Tx")
		self.resetbuttonrot = QtGui.QPushButton("Reset Rot")
		xformbox.addWidget(self.resetbuttontx, 7, 0, 1, 1)
		xformbox.addWidget(self.resetbuttonrot, 7, 1, 1, 1)
		xformframe.setLayout(xformbox)
		xformframe.setMaximumWidth(350)
				
		xformframe.setMaximumHeight(self.transfromboxmaxheight)
		xformframe.setLayout(xformbox)
		gridbox.addWidget(xformframe, 2, 0, 1, 1)
		
		# set to default, but run only as a base class
		if type(self) == EMItem3DInspector: self.updateItemControls()
		
		QtCore.QObject.connect(self.tx,QtCore.SIGNAL("valueChanged(int)"),self._on_translation)
		QtCore.QObject.connect(self.ty,QtCore.SIGNAL("valueChanged(int)"),self._on_translation)
		QtCore.QObject.connect(self.tz,QtCore.SIGNAL("valueChanged(int)"),self._on_translation)
		QtCore.QObject.connect(self.zoom,QtCore.SIGNAL("valueChanged(int)"),self._on_scale)
		QtCore.QObject.connect(self.resetbuttontx,QtCore.SIGNAL("clicked()"),self._on_resettx)
		QtCore.QObject.connect(self.resetbuttonrot,QtCore.SIGNAL("clicked()"),self._on_resetrot)
	
	def _on_translation(self, value):
		"""
		Need to contain the right coords. And do translation in the correct corrd system
		"""
		tt = t = Transform({"tx":self.tx.getValue(),"ty":self.ty.getValue(),"tz":self.tz.getValue()})
		tp = self.item3d().getParentMatrixProduct()
		if tp: tt = tp.inverse()*t
		self.item3d().getTransform().set_trans(tt.get_trans())
		self.inspector().updateSceneGraph()
		
	def _on_scale(self, value):
		self.item3d().getTransform().set_scale(self.zoom.getValue())
		self.inspector().updateSceneGraph()

	def _on_resettx(self):
		
		self.item3d().getTransform().set_trans(0.0, 0.0, 0.0)
		self.updateItemControls()
		self.inspector().updateSceneGraph()
		
	def _on_resetrot(self):
		self.item3d().getTransform().set_rotation({"type":"eman","az":0.0,"alt":0.0,"phi":0.0})
		self.updateItemControls()
		self.inspector().updateSceneGraph()
	
	def _isRotNaN(self, rot1, rot2, rot3):
		""" Better check to make sure get_rotation did not return Nan, so to prevent a crash """
		if rot1 != rot1: return True
		if rot2 != rot2: return True
		if rot3 != rot3: return True
		return False
		
	def updateItemControls(self):
		""" Updates this item inspector. Function is called by the item it observes"""
		# Translation update
		stdtransfrom = self.item3d().getTransformStdCoord()
		translation =  stdtransfrom.get_trans()
		
		self.tx.setValue(translation[0])
		self.ty.setValue(translation[1])
		self.tz.setValue(translation[2])
		# Rotation update
		rotation =  stdtransfrom.get_rotation(str(self.rotcombobox.currentText()))
		is_identity = stdtransfrom.is_rot_identity()
		comboboxidx = self.rotcombobox.currentIndex()
		if comboboxidx == 0:
			if self._isRotNaN(rotation["az"],rotation["alt"],rotation["phi"]): return
			self.emanazslider.setValue(rotation["az"], quiet=1)
			self.emanaltslider.setValue(rotation["alt"], quiet=1)
			self.emanphislider.setValue(rotation["phi"], quiet=1)
		if comboboxidx == 1:
			if self._isRotNaN(rotation["gamma"],rotation["beta"],rotation["alpha"]): return
			self.imagicgammaslider.setValue(rotation["gamma"], quiet=1)
			self.imagicbetaslider.setValue(rotation["beta"], quiet=1)
			self.imagicalphaslider.setValue(rotation["alpha"], quiet=1)
		if comboboxidx == 2:
			if self._isRotNaN(rotation["psi"],rotation["theta"],rotation["phi"]): return
			self.spiderpsislider.setValue(rotation["psi"], quiet=1)
			self.spiderthetaslider.setValue(rotation["theta"], quiet=1)
			self.spiderphislider.setValue(rotation["phi"], quiet=1)
		if comboboxidx == 3:
			if self._isRotNaN(rotation["phi"],rotation["theta"],rotation["omega"]): return
			self.mrcpsislider.setValue(rotation["phi"], quiet=1)
			self.mrcthetaslider.setValue(rotation["theta"], quiet=1)
			self.mrcomegaslider.setValue(rotation["omega"], quiet=1)
		if comboboxidx == 4:
			if self._isRotNaN(rotation["ztilt"],rotation["ytilt"],rotation["xtilt"]): return
			self.xyzzslider.setValue(rotation["ztilt"], quiet=1)
			self.xyzyslider.setValue(rotation["ytilt"], quiet=1)
			self.xyzxslider.setValue(rotation["xtilt"], quiet=1)
		if comboboxidx == 5:
			if self._isRotNaN(rotation["n1"],rotation["n2"],rotation["n3"]): return
			if is_identity and self.spinn1slider.getValue() == 0.0 and self.spinn2slider.getValue() == 0.0 and self.spinn3slider.getValue() == 0.0:
				self.spinomegaslider .setValue(0.0, quiet=1)
				self.spinn1slider.setValue(0.0, quiet=1)
				self.spinn2slider.setValue(0.0, quiet=1)
				self.spinn3slider.setValue(1.0, quiet=1)				
			else:
				self.spinomegaslider .setValue(rotation["omega"], quiet=1)
				# Don't change slider if reult is Nan
				if rotation["n1"] == rotation["n1"]: self.spinn1slider.setValue(rotation["n1"], quiet=1)
				if rotation["n2"] == rotation["n2"]: self.spinn2slider.setValue(rotation["n2"], quiet=1)
				if rotation["n3"] == rotation["n3"]: self.spinn3slider.setValue(rotation["n3"], quiet=1)
		if comboboxidx == 6:
			if self._isRotNaN(rotation["n1"],rotation["n2"],rotation["n3"]): return
			if is_identity and self.spinn1slider.getValue() == 0.0 and self.spinn2slider.getValue() == 0.0 and self.spinn3slider.getValue() == 0.0:
				self.spinomegaslider.setValue(0.0, quiet=1)
				self.sgirotn1slider.setValue(0.0, quiet=1)
				self.sgirotn2slider.setValue(0.0, quiet=1)
				self.sgirotn3slider.setValue(1.0, quiet=1)
			else:
				self.spinomegaslider.setValue(rotation["q"], quiet=1)
				# Don't change slider if reult is Nan
				if rotation["n1"] == rotation["n1"]: self.sgirotn1slider.setValue(rotation["n1"], quiet=1)
				if rotation["n2"] == rotation["n2"]: self.sgirotn2slider.setValue(rotation["n2"], quiet=1)
				if rotation["n3"] == rotation["n3"]: self.sgirotn3slider.setValue(rotation["n3"], quiet=1)
		if comboboxidx == 7:
			if self._isRotNaN(rotation["e1"],rotation["e2"],rotation["e3"]): return
			if is_identity:
				self.quaternione0slider.setValue(1.0, quiet=1)
				self.quaternione1slider.setValue(0.0, quiet=1)
				self.quaternione2slider.setValue(0.0, quiet=1)
				self.quaternione3slider.setValue(0.0, quiet=1)
			else:	
				self.quaternione0slider.setValue(rotation["e0"], quiet=1)
				self.quaternione1slider.setValue(rotation["e1"], quiet=1)
				self.quaternione2slider.setValue(rotation["e2"], quiet=1)
				self.quaternione3slider.setValue(rotation["e3"], quiet=1)
		# Scaling update
		self.zoom.setValue(self.item3d().getTransform().get_scale())
		
	def updateMetaData(self):
		"""
		I didn't want to put this in update b/c this data doesn't change very often, and I don't want to waste CPU
		Its a judgement call really, less coupling vs. more efficiency
		"""
		if self.boundingbox: self.boundingbox.setText("Size: "+self.item3d().boundingboxsize)
			
		
	def addRotationWidgets(self):
		""" Add alll the widgets for the various EMAN2 rotation conventions """
		EMANwidget = QtGui.QWidget()
		Imagicwidget = QtGui.QWidget()
		Spiderwidget = QtGui.QWidget()
		MRCwidget = QtGui.QWidget()
		XYZwidget = QtGui.QWidget()
		spinwidget = QtGui.QWidget()
		sgirotwidget = QtGui.QWidget()
		quaternionwidget = QtGui.QWidget()
		# EMAN
		emanbox = QtGui.QVBoxLayout()
		self.emanazslider = ValSlider(EMANwidget, (0.0, 360.0), "  Az", rounding = 1)
		self.emanaltslider = ValSlider(EMANwidget, (0.0, 180.0), "Alt", rounding = 1)
		self.emanphislider = ValSlider(EMANwidget, (0.0, 360.0), "Phi", rounding = 1)
		emanbox.addWidget(self.emanazslider)
		emanbox.addWidget(self.emanaltslider)
		emanbox.addWidget(self.emanphislider)
		EMANwidget.setLayout(emanbox)
		# Imagic
		imagicbox = QtGui.QVBoxLayout()
		self.imagicgammaslider = ValSlider(Imagicwidget, (0.0, 360.0), "Gamma", rounding = 1)
		self.imagicbetaslider = ValSlider(Imagicwidget, (0.0, 180.0), "     Beta", rounding = 1)
		self.imagicalphaslider = ValSlider(Imagicwidget, (0.0, 360.0), "   Alpha", rounding = 1)
		imagicbox.addWidget(self.imagicgammaslider)
		imagicbox.addWidget(self.imagicbetaslider)
		imagicbox.addWidget(self.imagicalphaslider)
		Imagicwidget.setLayout(imagicbox)
		# Spider
		spiderbox = QtGui.QVBoxLayout()
		self.spiderpsislider = ValSlider(Spiderwidget, (0.0, 360.0), "   Psi", rounding = 1)
		self.spiderthetaslider = ValSlider(Spiderwidget, (0.0, 180.0), "Theta", rounding = 1)
		self.spiderphislider = ValSlider(Spiderwidget, (0.0, 360.0), "   Phi", rounding = 1)
		spiderbox.addWidget(self.spiderpsislider)
		spiderbox.addWidget(self.spiderthetaslider)
		spiderbox.addWidget(self.spiderphislider)
		Spiderwidget.setLayout(spiderbox)
		# MRC
		mrcbox = QtGui.QVBoxLayout()
		self.mrcpsislider = ValSlider(MRCwidget, (0.0, 360.0), "      Psi", rounding = 1)
		self.mrcthetaslider = ValSlider(MRCwidget, (0.0, 180.0), "  Theta", rounding = 1)
		self.mrcomegaslider = ValSlider(MRCwidget, (0.0, 360.0), "Omega", rounding = 1)
		mrcbox.addWidget(self.mrcpsislider)
		mrcbox.addWidget(self.mrcthetaslider)
		mrcbox.addWidget(self.mrcomegaslider)
		MRCwidget.setLayout(mrcbox)
		# XYZ
		xyzbox = QtGui.QVBoxLayout()
		self.xyzzslider = ValSlider(XYZwidget, (0.0, 360.0), "Z", rounding = 1)
		self.xyzyslider = ValSlider(XYZwidget, (0.0, 180.0), "Y", rounding = 1)
		self.xyzxslider = ValSlider(XYZwidget, (0.0, 360.0), "X", rounding = 1)
		xyzbox.addWidget(self.xyzzslider)
		xyzbox.addWidget(self.xyzyslider)
		xyzbox.addWidget(self.xyzxslider)
		XYZwidget.setLayout(xyzbox)
		# spin
		spinbox = QtGui.QVBoxLayout()
		self.spinomegaslider = ValSlider(spinwidget, (0.0, 180.0), "Omega", rounding = 1)
		self.spinn1slider = ValSlider(spinwidget, (0.0, 1.0), "       N1", rounding = 4)
		self.spinn2slider = ValSlider(spinwidget, (0.0, 1.0), "       N2", rounding = 4)
		self.spinn3slider = ValSlider(spinwidget, (0.0, 1.0), "       N3", rounding = 4)
		spinbox.addWidget(self.spinomegaslider)
		spinbox.addWidget(self.spinn1slider)
		spinbox.addWidget(self.spinn2slider)
		spinbox.addWidget(self.spinn3slider)
		spinwidget.setLayout(spinbox)
		# sgirot
		sgirotbox = QtGui.QVBoxLayout()
		self.sgirotqslider = ValSlider(sgirotwidget, (0.0, 180.0), " Q", rounding = 1)
		self.sgirotn1slider = ValSlider(sgirotwidget, (0.0, 1.0), "N1", rounding = 4)
		self.sgirotn2slider = ValSlider(sgirotwidget, (0.0, 1.0), "N2", rounding = 4)
		self.sgirotn3slider = ValSlider(sgirotwidget, (0.0, 1.0), "N3", rounding = 4)
		sgirotbox.addWidget(self.sgirotqslider)
		sgirotbox.addWidget(self.sgirotn1slider)
		sgirotbox.addWidget(self.sgirotn2slider)
		sgirotbox.addWidget(self.sgirotn3slider)
		sgirotwidget.setLayout(sgirotbox)
		# quaternion
		quaternionbox = QtGui.QVBoxLayout()
		self.quaternione0slider = ValSlider(quaternionwidget, (0.0, 1.0), "E0", rounding = 4)
		self.quaternione1slider = ValSlider(quaternionwidget, (0.0, 1.0), "E1", rounding = 4)
		self.quaternione2slider = ValSlider(quaternionwidget, (0.0, 1.0), "E2", rounding = 4)
		self.quaternione3slider = ValSlider(quaternionwidget, (0.0, 1.0), "E3", rounding = 4)
		quaternionbox.addWidget(self.quaternione0slider)
		quaternionbox.addWidget(self.quaternione1slider)
		quaternionbox.addWidget(self.quaternione2slider)
		quaternionbox.addWidget(self.quaternione3slider)
		quaternionwidget.setLayout(quaternionbox)
		# Add widgets to the stack
		self.rotstackedwidget.addWidget(EMANwidget)
		self.rotstackedwidget.addWidget(Imagicwidget)
		self.rotstackedwidget.addWidget(Spiderwidget)
		self.rotstackedwidget.addWidget(MRCwidget)
		self.rotstackedwidget.addWidget(XYZwidget)
		self.rotstackedwidget.addWidget(spinwidget)
		self.rotstackedwidget.addWidget(sgirotwidget)
		self.rotstackedwidget.addWidget(quaternionwidget)
		# add choices to combobox
		self.rotcombobox.addItem("EMAN")
		self.rotcombobox.addItem("Imagic")
		self.rotcombobox.addItem("Spider")
		self.rotcombobox.addItem("MRC")
		self.rotcombobox.addItem("XYZ")
		self.rotcombobox.addItem("spin")
		self.rotcombobox.addItem("sgirot")
		self.rotcombobox.addItem("quaternion")
	
		# Signal for all sliders
		QtCore.QObject.connect(self.rotcombobox, QtCore.SIGNAL("activated(int)"), self._rotcombobox_changed)
		QtCore.QObject.connect(self.emanazslider,QtCore.SIGNAL("valueChanged"),self._on_EMAN_rotation)
		QtCore.QObject.connect(self.emanaltslider,QtCore.SIGNAL("valueChanged"),self._on_EMAN_rotation)
		QtCore.QObject.connect(self.emanphislider,QtCore.SIGNAL("valueChanged"),self._on_EMAN_rotation)
		QtCore.QObject.connect(self.imagicgammaslider,QtCore.SIGNAL("valueChanged"),self._on_Imagic_rotation)
		QtCore.QObject.connect(self.imagicbetaslider,QtCore.SIGNAL("valueChanged"),self._on_Imagic_rotation)
		QtCore.QObject.connect(self.imagicalphaslider,QtCore.SIGNAL("valueChanged"),self._on_Imagic_rotation)
		QtCore.QObject.connect(self.spiderpsislider,QtCore.SIGNAL("valueChanged"),self._on_Spider_rotation)
		QtCore.QObject.connect(self.spiderthetaslider,QtCore.SIGNAL("valueChanged"),self._on_Spider_rotation)
		QtCore.QObject.connect(self.spiderphislider,QtCore.SIGNAL("valueChanged"),self._on_Spider_rotation)
		QtCore.QObject.connect(self.mrcpsislider,QtCore.SIGNAL("valueChanged"),self._on_MRC_rotation)
		QtCore.QObject.connect(self.mrcthetaslider,QtCore.SIGNAL("valueChanged"),self._on_MRC_rotation)
		QtCore.QObject.connect(self.mrcomegaslider,QtCore.SIGNAL("valueChanged"),self._on_MRC_rotation)
		QtCore.QObject.connect(self.xyzzslider,QtCore.SIGNAL("valueChanged"),self._on_XYZ_rotation)
		QtCore.QObject.connect(self.xyzyslider,QtCore.SIGNAL("valueChanged"),self._on_XYZ_rotation)
		QtCore.QObject.connect(self.xyzxslider,QtCore.SIGNAL("valueChanged"),self._on_XYZ_rotation)
		QtCore.QObject.connect(self.spinomegaslider,QtCore.SIGNAL("valueChanged"),self._on_spin_rotation)
		QtCore.QObject.connect(self.spinn1slider,QtCore.SIGNAL("valueChanged"),self._on_spin_rotation)
		QtCore.QObject.connect(self.spinn2slider,QtCore.SIGNAL("valueChanged"),self._on_spin_rotation)
		QtCore.QObject.connect(self.spinn3slider,QtCore.SIGNAL("valueChanged"),self._on_spin_rotation)
		QtCore.QObject.connect(self.sgirotqslider,QtCore.SIGNAL("valueChanged"),self._on_sgirot_rotation)
		QtCore.QObject.connect(self.sgirotn1slider,QtCore.SIGNAL("valueChanged"),self._on_sgirot_rotation)
		QtCore.QObject.connect(self.sgirotn2slider,QtCore.SIGNAL("valueChanged"),self._on_sgirot_rotation)
		QtCore.QObject.connect(self.sgirotn3slider,QtCore.SIGNAL("valueChanged"),self._on_sgirot_rotation)
		QtCore.QObject.connect(self.quaternione0slider,QtCore.SIGNAL("valueChanged"),self._on_quaternion_rotation)
		QtCore.QObject.connect(self.quaternione1slider,QtCore.SIGNAL("valueChanged"),self._on_quaternion_rotation)
		QtCore.QObject.connect(self.quaternione2slider,QtCore.SIGNAL("valueChanged"),self._on_quaternion_rotation)
		QtCore.QObject.connect(self.quaternione3slider,QtCore.SIGNAL("valueChanged"),self._on_quaternion_rotation)	
		
	def _rotcombobox_changed(self, idx):
		self.rotstackedwidget.setCurrentIndex(idx)
		self.updateItemControls()
		
	def _on_EMAN_rotation(self, value):
		self._set_rotation_std_coords(Transform({"type":"eman","az":self.emanazslider.getValue(),"alt":self.emanaltslider.getValue(),"phi":self.emanphislider.getValue()}))
		self.inspector().updateSceneGraph()
		
	def _on_Imagic_rotation(self, value):
		self._set_rotation_std_coords(Transform({"type":"imagic","gamma":self.imagicgammaslider.getValue(),"beta":self.imagicbetaslider.getValue(),"alpha":self.imagicalphaslider.getValue()}))
		self.inspector().updateSceneGraph()
		
	def _on_Spider_rotation(self, value):
		self._set_rotation_std_coords(Transform({"type":"spider","psi":self.spiderpsislider.getValue(),"theta":self.spiderthetaslider.getValue(),"phi":self.spiderphislider.getValue()}))
		self.inspector().updateSceneGraph()
		
	def _on_MRC_rotation(self, value):
		self._set_rotation_std_coords(Transform({"type":"mrc","phi":self.mrcpsislider.getValue(),"theta":self.mrcthetaslider.getValue(),"omega":self.mrcomegaslider.getValue()}))
		self.inspector().updateSceneGraph()
		
	def _on_XYZ_rotation(self, value):
		self._set_rotation_std_coords(Transform({"type":"xyz","ztilt":self.xyzzslider.getValue(),"ytilt":self.xyzyslider.getValue(),"xtilt":self.xyzxslider.getValue()}))
		self.inspector().updateSceneGraph()
		
	def _on_spin_rotation(self, value):
		v = Vec3f(self.spinn1slider.getValue(), self.spinn2slider.getValue(), self.spinn3slider.getValue())
		v.normalize()
		self._set_rotation_std_coords(Transform({"type":"spin","omega":self.spinomegaslider.getValue(),"n1":v[0],"n2":v[1],"n3":v[2]}))
		self.inspector().updateSceneGraph()
		
	def _on_sgirot_rotation(self, value):
		v = Vec3f(self.sgirotn1slider.getValue(), self.sgirotn2slider.getValue(), self.sgirotn3slider.getValue())
		v.normalize()
		self._set_rotation_std_coords(Transform({"type":"sgirot","q":self.sgirotqslider.getValue(),"n1":v[0],"n2":v[1],"n3":v[2]}))
		self.inspector().updateSceneGraph()
		
	def _on_quaternion_rotation(self, value):
		v = Vec4f(self.quaternione0slider.getValue(), self.quaternione1slider.getValue(), self.quaternione2slider.getValue(), self.quaternione3slider.getValue())
		v.normalize()
		self._set_rotation_std_coords(Transform({"type":"quaternion","e0":v[0],"e1":v[1],"e2":v[2],"e3":v[3]}))
		self.inspector().updateSceneGraph()
		
	def _set_rotation_std_coords(self, rotation):
		""" This function sets the rotation as if there were no preceeding ones, otherwise a rot around Z could be arounf y,x, etc.
		Works by transforming local coords into global corrds"""
		tt = rotation
		tp = self.item3d().getParentMatrixProduct()
		if tp: tt = tp.inverse()*rotation
		self.item3d().getTransform().set_rotation(tt.get_rotation())
Exemplo n.º 6
0
class GUIctfsim(QtGui.QWidget):
    def __init__(self,
                 application,
                 apix=1.0,
                 voltage=300.0,
                 cs=4.1,
                 ac=10.0,
                 samples=256):
        """CTF simulation dialog
		"""
        try:
            from emimage2d import EMImage2DWidget
        except:
            print "Cannot import EMAN image GUI objects (EMImage2DWidget)"
            sys.exit(1)
        try:
            from emplot2d import EMPlot2DWidget
        except:
            print "Cannot import EMAN plot GUI objects (is matplotlib installed?)"
            sys.exit(1)

        self.app = weakref.ref(application)

        self.df_voltage = voltage
        self.df_apix = apix
        self.df_cs = cs
        self.df_ac = ac
        self.df_samples = samples
        self.img = None

        QtGui.QWidget.__init__(self, None)
        self.setWindowIcon(QtGui.QIcon(get_image_directory() + "ctf.png"))

        self.data = []
        self.curset = 0
        self.plotmode = 0

        self.guiim = EMImage2DWidget(application=self.app())
        self.guiiminit = True  # a flag that's used to auto resize the first time the gui's set_data function is called
        self.guiplot = EMPlot2DWidget(application=self.app())
        #		self.guirealim=EMImage2DWidget(application=self.app())	# This will show the original particle images

        #		self.guirealim.connect(self.guirealim,QtCore.SIGNAL("keypress"),self.realimgkey)
        self.guiim.connect(self.guiim, QtCore.SIGNAL("mousedown"),
                           self.imgmousedown)
        self.guiim.connect(self.guiim, QtCore.SIGNAL("mousedrag"),
                           self.imgmousedrag)
        self.guiim.connect(self.guiim, QtCore.SIGNAL("mouseup"),
                           self.imgmouseup)
        self.guiplot.connect(self.guiplot, QtCore.SIGNAL("mousedown"),
                             self.plotmousedown)

        self.guiim.mmode = "app"

        # This object is itself a widget we need to set up
        self.hbl = QtGui.QHBoxLayout(self)
        self.hbl.setMargin(0)
        self.hbl.setSpacing(6)
        self.hbl.setObjectName("hbl")

        # plot list and plot mode combobox
        self.vbl2 = QtGui.QVBoxLayout()
        self.setlist = MyListWidget(self)
        self.setlist.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                   QtGui.QSizePolicy.Expanding)
        self.vbl2.addWidget(self.setlist)

        self.splotmode = QtGui.QComboBox(self)
        self.splotmode.addItem("Amplitude")
        self.splotmode.addItem("Intensity")
        self.splotmode.addItem("Int w sum")
        self.splotmode.addItem("Amp w sum")
        self.vbl2.addWidget(self.splotmode)
        self.hbl.addLayout(self.vbl2)

        # ValSliders for CTF parameters
        self.vbl = QtGui.QVBoxLayout()
        self.vbl.setMargin(0)
        self.vbl.setSpacing(6)
        self.vbl.setObjectName("vbl")
        self.hbl.addLayout(self.vbl)

        #self.samp = ValSlider(self,(0,5.0),"Amp:",0)
        #self.vbl.addWidget(self.samp)

        self.imginfo = QtGui.QLabel("Info", self)
        self.vbl.addWidget(self.imginfo)

        self.sdefocus = ValSlider(self, (0, 5), "Defocus:", 0, 90)
        self.vbl.addWidget(self.sdefocus)

        self.sbfactor = ValSlider(self, (0, 1600), "B factor:", 0, 90)
        self.vbl.addWidget(self.sbfactor)

        self.sdfdiff = ValSlider(self, (0, 1), "DF Diff:", 0, 90)
        self.vbl.addWidget(self.sdfdiff)

        self.sdfang = ValSlider(self, (0, 180), "Df Angle:", 0, 90)
        self.vbl.addWidget(self.sdfang)

        self.sampcont = ValSlider(self, (0, 100), "% AC", 0, 90)
        self.vbl.addWidget(self.sampcont)

        self.sapix = ValSlider(self, (.2, 10), "A/Pix:", 2, 90)
        self.vbl.addWidget(self.sapix)

        self.svoltage = ValSlider(self, (0, 1000), "Voltage (kV):", 0, 90)
        self.vbl.addWidget(self.svoltage)

        self.scs = ValSlider(self, (0, 5), "Cs (mm):", 0, 90)
        self.vbl.addWidget(self.scs)

        self.ssamples = ValSlider(self, (32, 1024), "# Samples:", 0, 90)
        self.ssamples.setIntonly(True)
        self.vbl.addWidget(self.ssamples)

        self.hbl_buttons = QtGui.QHBoxLayout()
        self.newbut = QtGui.QPushButton("New")
        self.hbl_buttons.addWidget(self.newbut)
        self.vbl.addLayout(self.hbl_buttons)

        self.on_new_but()

        QtCore.QObject.connect(self.sdefocus, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.sbfactor, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.sdfdiff, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.sdfang, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.sapix, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.sampcont, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.svoltage, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.scs, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.ssamples, QtCore.SIGNAL("valueChanged"),
                               self.newCTF)
        QtCore.QObject.connect(self.setlist,
                               QtCore.SIGNAL("currentRowChanged(int)"),
                               self.newSet)
        QtCore.QObject.connect(self.setlist, QtCore.SIGNAL("keypress"),
                               self.listkey)
        QtCore.QObject.connect(self.splotmode,
                               QtCore.SIGNAL("currentIndexChanged(int)"),
                               self.newPlotMode)

        QtCore.QObject.connect(self.newbut, QtCore.SIGNAL("clicked(bool)"),
                               self.on_new_but)

        self.resize(
            720, 380
        )  # figured these values out by printing the width and height in resize event

        E2loadappwin("e2ctfsim", "main", self)
        E2loadappwin("e2ctfsim", "image", self.guiim.qt_parent)
        #		E2loadappwin("e2ctf","realimage",self.guirealim.qt_parent)
        E2loadappwin("e2ctfsim", "plot", self.guiplot.qt_parent)

        self.setWindowTitle("CTF")

    def listkey(self, event):

        if event.key() >= Qt.Key_0 and event.key() <= Qt.Key_9:
            q = int(event.key()) - Qt.Key_0
            self.squality.setValue(q)
        elif event.key() == Qt.Key_Left:
            self.sdefocus.setValue(self.sdefocus.getValue() - 0.01)
        elif event.key() == Qt.Key_Right:
            self.sdefocus.setValue(self.sdefocus.getValue() + 0.01)
        elif event.key() == Qt.Key_R:
            self.on_recall_params()

    def on_new_but(self):
        ctf = EMAN2Ctf()
        ctf.defocus = 1.0
        ctf.voltage = self.df_voltage
        ctf.apix = self.df_apix
        ctf.cs = self.df_cs
        ctf.ac = self.df_ac
        ctf.samples = self.df_samples
        self.data.append((str(len(self.setlist) + 1), ctf))
        self.curset = len(self.data)
        self.update_data()

    def show_guis(self):
        if self.guiim != None:
            self.app().show_specific(self.guiim)
        if self.guiplot != None:
            self.app().show_specific(self.guiplot)
        #if self.guirealim != None:
        #self.app().show_specific(self.guirealim)

        self.show()

    def closeEvent(self, event):
        #		QtGui.QWidget.closeEvent(self,event)
        #		self.app.app.closeAllWindows()
        E2saveappwin("e2ctf", "main", self)

        if self.guiim != None:
            E2saveappwin("e2ctf", "image", self.guiim.qt_parent)
            self.app().close_specific(self.guiim)
            self.guiim = None
        if self.guiplot != None:
            E2saveappwin("e2ctf", "plot", self.guiplot.qt_parent)
            self.app().close_specific(self.guiplot)
        #if self.guirealim != None:
        #E2saveappwin("e2ctf","realimage",self.guirealim.qt_parent)
        #self.app().close_specific(self.guirealim)

        event.accept()
        self.app().close_specific(self)
        self.emit(
            QtCore.SIGNAL("module_closed")
        )  # this signal is important when e2ctf is being used by a program running its own event loop

    def update_data(self):
        """This will make sure the various widgets properly show the current data sets"""
        self.setlist.clear()
        for i, j in enumerate(self.data):
            self.setlist.addItem(j[0])
        self.setlist.setCurrentRow(self.curset)

    def update_plot(self):
        if self.guiplot == None: return  # it's closed/not visible

        for d in xrange(len(self.data)):
            ctf = self.data[d][1]
            ds = 1.0 / (ctf.apix * 2.0 * ctf.samples)
            s = arange(0, ds * ctf.samples, ds)

            curve = array(ctf.compute_1d(len(s) * 2, ds, Ctf.CtfType.CTF_AMP))
            if self.plotmode == 1 or self.plotmode == 2:
                curve = curve**2

            if self.plotmode == 2 or self.plotmode == 3:
                if d == 0: avg = curve[:]
                else:
                    if len(curve) != len(avg):
                        print "Number of samples must be fixed to compute an average ({})".format(
                            d + 1)
                    else:
                        avg += curve

            self.guiplot.set_data((s, curve),
                                  self.data[d][0],
                                  d == 0,
                                  True,
                                  color=d + 1)

        if self.plotmode in (2, 3):
            self.guiplot.set_data((s, avg), "Sum", False, True, color=0)

        self.guiplot.setAxisParms("s (1/$\AA$)", "CTF")

        ctf.compute_2d_complex(self.img, Ctf.CtfType.CTF_AMP, None)
        self.guiim.set_data(self.img)

    def newSet(self, val=0):
        "called when a new data set is selected from the list"
        self.curset = val

        self.sdefocus.setValue(self.data[val][1].defocus, True)
        self.sbfactor.setValue(self.data[val][1].bfactor, True)
        self.sapix.setValue(self.data[val][1].apix, True)
        self.sampcont.setValue(self.data[val][1].ampcont, True)
        self.svoltage.setValue(self.data[val][1].voltage, True)
        self.scs.setValue(self.data[val][1].cs, True)
        self.sdfdiff.setValue(self.data[val][1].dfdiff, True)
        self.sdfang.setValue(self.data[val][1].dfang, True)
        self.ssamples.setValue(self.data[val][1].samples, True)

        # make new image if necessary
        if self.img == None or self.img["ny"] != self.data[val][1].samples:
            self.img = EMData(self.data[val][1].samples + 2,
                              self.data[val][1].samples)
            self.img.to_zero()
            self.img.set_complex(1)
        self.guiim.set_data(self.img)
        #		self.imginfo.setText("%s particles     SNR = %s"%(ptcl,ssnr))

        #if self.guiim != None:
        ##			print self.data
        #self.guiim.set_data(self.data[val][4])
        #if self.guiiminit:
        #self.guiim.optimally_resize()
        #self.guiiminit = False
        #self.guiim.updateGL()
        #self.update_plot()

        #		print "self.data[val]=",self.data[val][0].split('#')[-1]

        self.guiim.qt_parent.setWindowTitle("e2ctfsim - 2D FFT - " +
                                            self.data[val][0])
        #		self.guirealim.qt_parent.setWindowTitle("e2ctf - "+self.data[val][0].split('#')[-1])
        self.guiplot.qt_parent.setWindowTitle("e2ctfsim - Plot ")

        #n=EMUtil.get_image_count(self.data[val][0])
        #if n>1:
        #self.ptcldata=EMData.read_images(self.data[val][0],range(0,min(20,n)))
        #im=sum(self.ptcldata)
        #im.mult(1.0/len(self.ptcldata))
        #self.ptcldata.insert(0,im)
        #self.guirealim.set_data(self.ptcldata)
        #else : self.guirealim.set_data([EMData()])
        self.update_plot()

    def newPlotMode(self, mode):
        self.plotmode = mode
        self.update_plot()

    def newCTF(self):
        #		print traceback.print_stack()
        self.data[self.curset][1].defocus = self.sdefocus.value
        self.data[self.curset][1].bfactor = self.sbfactor.value
        self.data[self.curset][1].dfdiff = self.sdfdiff.value
        self.data[self.curset][1].dfang = self.sdfang.value
        self.data[self.curset][1].apix = self.sapix.value
        self.data[self.curset][1].ampcont = self.sampcont.value
        self.data[self.curset][1].voltage = self.svoltage.value
        self.data[self.curset][1].cs = self.scs.value
        self.data[self.curset][1].samples = self.ssamples.value

        if self.img == None or self.img["ny"] != self.ssamples.value:
            self.img = EMData(self.ssamples.value + 2, self.ssamples.value)
            self.img.to_zero()
            self.img.set_complex(1)
            self.guiim.set_data(self.img)
        self.update_plot()

    def realimgkey(self, event):
        """Keypress in the image display window"""

        if event.key(
        ) == Qt.Key_I:  # if user presses I in this window we invert the stack on disk
            fsp = self.data[self.curset][0]
            n = EMUtil.get_image_count(fsp)
            print "Inverting images in %s" % fsp
            for i in xrange(n):
                img = EMData(fsp, i)
                img.mult(-1.0)
                img.write_image(fsp, i)

            #self.ptcldata=EMData.read_images(fsp,range(0,20))
            #self.guirealim.set_data(self.ptcldata)

    def imgmousedown(self, event):
        m = self.guiim.scr_to_img((event.x(), event.y()))
        #self.guiim.add_shape("cen",["rect",.9,.9,.4,x0,y0,x0+2,y0+2,1.0])

    def imgmousedrag(self, event):
        m = self.guiim.scr_to_img((event.x(), event.y()))

        # box deletion when shift held down
        #if event.modifiers()&Qt.ShiftModifier:
        #for i,j in enumerate(self.boxes):

    def imgmouseup(self, event):
        m = self.guiim.scr_to_img((event.x(), event.y()))

    def plotmousedown(self, event):
        m = self.guiim.scr_to_img((event.x(), event.y()))

    def run(self):
        """If you make your own application outside of this object, you are free to use
		your own local app.exec_(). This is a convenience for ctf-only programs."""
        self.app.exec_()

        #		E2saveappwin("boxer","imagegeom",self.guiim)
        #		try:
        #			E2setappval("boxer","imcontrol",self.guiim.inspector.isVisible())
        #			if self.guiim.inspector.isVisible() : E2saveappwin("boxer","imcontrolgeom",self.guiim.inspector)
        #		except : E2setappval("boxer","imcontrol",False)

        return
Exemplo n.º 7
0
class EMGLPlotInspector(QtGui.QWidget):
	def __init__(self,target) :
		QtGui.QWidget.__init__(self,None)
		self.target=target
		
		self.vbl = QtGui.QVBoxLayout(self)
		self.vbl.setMargin(0)
		self.vbl.setSpacing(6)
		self.vbl.setObjectName("vbl")
		
		self.hbl = QtGui.QHBoxLayout()
		self.hbl.setMargin(0)
		self.hbl.setSpacing(6)
		self.hbl.setObjectName("hbl")
		self.vbl.addLayout(self.hbl)
		
		self.hist = ImgHistogram(self)
		self.hist.setObjectName("hist")
		self.hbl.addWidget(self.hist)
		
		self.vbl2 = QtGui.QVBoxLayout()
		self.vbl2.setMargin(0)
		self.vbl2.setSpacing(6)
		self.vbl2.setObjectName("vbl2")
		self.hbl.addLayout(self.vbl2)
		
		self.wiretog = QtGui.QPushButton("Wire")
		self.wiretog.setCheckable(1)
		self.vbl2.addWidget(self.wiretog)
		
		self.lighttog = QtGui.QPushButton("Light")
		self.lighttog.setCheckable(1)
		self.vbl2.addWidget(self.lighttog)
		
		self.tabwidget = QtGui.QTabWidget()
		self.maintab = None
		self.tabwidget.addTab(self.get_main_tab(), "Main")
		self.tabwidget.addTab(self.get_GL_tab(),"GL")
		self.vbl.addWidget(self.tabwidget)
		self.n3_showing = False
		
		QtCore.QObject.connect(self.scale, QtCore.SIGNAL("valueChanged"), target.set_scale)
		QtCore.QObject.connect(self.az, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.alt, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.phi, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.cbb, QtCore.SIGNAL("currentIndexChanged(QString)"), target.setColor)
		QtCore.QObject.connect(self.src, QtCore.SIGNAL("currentIndexChanged(QString)"), self.set_src)
		QtCore.QObject.connect(self.x_trans, QtCore.SIGNAL("valueChanged(double)"), target.set_cam_x)
		QtCore.QObject.connect(self.y_trans, QtCore.SIGNAL("valueChanged(double)"), target.set_cam_y)
		QtCore.QObject.connect(self.z_trans, QtCore.SIGNAL("valueChanged(double)"), target.set_cam_z)
		QtCore.QObject.connect(self.wiretog, QtCore.SIGNAL("toggled(bool)"), target.toggle_wire)
		QtCore.QObject.connect(self.lighttog, QtCore.SIGNAL("toggled(bool)"), target.toggle_light)
		QtCore.QObject.connect(self.glcontrast, QtCore.SIGNAL("valueChanged"), target.set_GL_contrast)
		QtCore.QObject.connect(self.glbrightness, QtCore.SIGNAL("valueChanged"), target.set_GL_brightness)
	
	def get_GL_tab(self):
		self.gltab = QtGui.QWidget()
		gltab = self.gltab
		
		gltab.vbl = QtGui.QVBoxLayout(self.gltab )
		gltab.vbl.setMargin(0)
		gltab.vbl.setSpacing(6)
		gltab.vbl.setObjectName("Main")
		
		self.glcontrast = ValSlider(gltab,(1.0,5.0),"GLShd:")
		self.glcontrast.setObjectName("GLShade")
		self.glcontrast.setValue(1.0)
		gltab.vbl.addWidget(self.glcontrast)
		
		self.glbrightness = ValSlider(gltab,(-1.0,0.0),"GLBst:")
		self.glbrightness.setObjectName("GLBoost")
		self.glbrightness.setValue(0.1)
		self.glbrightness.setValue(0.0)
		gltab.vbl.addWidget(self.glbrightness)
	
		return gltab
	
	def get_main_tab(self):
		if ( self.maintab == None ):
			self.maintab = QtGui.QWidget()
			maintab = self.maintab
			maintab.vbl = QtGui.QVBoxLayout(self.maintab)
			maintab.vbl.setMargin(0)
			maintab.vbl.setSpacing(6)
			maintab.vbl.setObjectName("Main")
			
			self.scale = ValSlider(maintab,(0.01,30.0),"Zoom:")
			self.scale.setObjectName("scale")
			self.scale.setValue(1.0)
			maintab.vbl.addWidget(self.scale)
			
			self.hbl_color = QtGui.QHBoxLayout()
			self.hbl_color.setMargin(0)
			self.hbl_color.setSpacing(6)
			self.hbl_color.setObjectName("Material")
			maintab.vbl.addLayout(self.hbl_color)
			
			self.color_label = QtGui.QLabel()
			self.color_label.setText('Material')
			self.hbl_color.addWidget(self.color_label)
			
			self.cbb = QtGui.QComboBox(maintab)
			self.hbl_color.addWidget(self.cbb)
	
			self.hbl_trans = QtGui.QHBoxLayout()
			self.hbl_trans.setMargin(0)
			self.hbl_trans.setSpacing(6)
			self.hbl_trans.setObjectName("Trans")
			maintab.vbl.addLayout(self.hbl_trans)
			
			self.x_label = QtGui.QLabel()
			self.x_label.setText('x')
			self.hbl_trans.addWidget(self.x_label)
			
			self.x_trans = QtGui.QDoubleSpinBox(self)
			self.x_trans.setMinimum(-10000)
			self.x_trans.setMaximum(10000)
			self.x_trans.setValue(0.0)
			self.hbl_trans.addWidget(self.x_trans)
			
			self.y_label = QtGui.QLabel()
			self.y_label.setText('y')
			self.hbl_trans.addWidget(self.y_label)
			
			self.y_trans = QtGui.QDoubleSpinBox(maintab)
			self.y_trans.setMinimum(-10000)
			self.y_trans.setMaximum(10000)
			self.y_trans.setValue(0.0)
			self.hbl_trans.addWidget(self.y_trans)
			
			
			self.z_label = QtGui.QLabel()
			self.z_label.setText('z')
			self.hbl_trans.addWidget(self.z_label)
			
			self.z_trans = QtGui.QDoubleSpinBox(maintab)
			self.z_trans.setMinimum(-10000)
			self.z_trans.setMaximum(10000)
			self.z_trans.setValue(0.0)
			self.hbl_trans.addWidget(self.z_trans)
			
			self.hbl_src = QtGui.QHBoxLayout()
			self.hbl_src.setMargin(0)
			self.hbl_src.setSpacing(6)
			self.hbl_src.setObjectName("hbl")
			maintab.vbl.addLayout(self.hbl_src)
			
			self.label_src = QtGui.QLabel()
			self.label_src.setText('Rotation Convention')
			self.hbl_src.addWidget(self.label_src)
			
			self.src = QtGui.QComboBox(maintab)
			self.load_src_options(self.src)
			self.hbl_src.addWidget(self.src)
			
			# set default value -1 ensures that the val slider is updated the first time it is created
			self.az = ValSlider(self,(-360.0,360.0),"az",-1)
			self.az.setObjectName("az")
			maintab.vbl.addWidget(self.az)
			
			self.alt = ValSlider(self,(-180.0,180.0),"alt",-1)
			self.alt.setObjectName("alt")
			maintab.vbl.addWidget(self.alt)
			
			self.phi = ValSlider(self,(-360.0,360.0),"phi",-1)
			self.phi.setObjectName("phi")
			maintab.vbl.addWidget(self.phi)
		
			self.current_src = EULER_EMAN
		
		return self.maintab

	def set_xy_trans(self, x, y):
		self.x_trans.setValue(x)
		self.y_trans.setValue(y)
	
	def set_translate_scale(self, xscale,yscale,zscale):
		self.x_trans.setSingleStep(xscale)
		self.y_trans.setSingleStep(yscale)
		self.z_trans.setSingleStep(zscale)

	def update_rotations(self,t3d):
		rot = t3d.get_rotation(self.src_map[str(self.src.itemText(self.src.currentIndex()))])
		
		convention = self.src.currentText()
		if ( self.src_map[str(convention)] == EULER_SPIN ):
			self.n3.setValue(rot[self.n3.getLabel()],True)
		
		self.az.setValue(rot[self.az.getLabel()],True)
		self.alt.setValue(rot[self.alt.getLabel()],True)
		self.phi.setValue(rot[self.phi.getLabel()],True)
	
	def slider_rotate(self):
		self.target.load_rotation(self.get_current_rotation())
	
	def get_current_rotation(self):
		convention = self.src.currentText()
		rot = {}
		if ( self.current_src == EULER_SPIN ):
			rot[self.az.getLabel()] = self.az.getValue()
			
			n1 = self.alt.getValue()
			n2 = self.phi.getValue()
			n3 = self.n3.getValue()
			
			norm = sqrt(n1*n1 + n2*n2 + n3*n3)
			
			n1 /= norm
			n2 /= norm
			n3 /= norm
			
			rot[self.alt.getLabel()] = n1
			rot[self.phi.getLabel()] = n2
			rot[self.n3.getLabel()] = n3
			
		else:
			rot[self.az.getLabel()] = self.az.getValue()
			rot[self.alt.getLabel()] = self.alt.getValue()
			rot[self.phi.getLabel()] = self.phi.getValue()
		
		return Transform3D(self.current_src, rot)
	
	def set_src(self, val):
		t3d = self.get_current_rotation()
		
		if (self.n3_showing) :
			self.vbl.removeWidget(self.n3)
			self.n3.deleteLater()
			self.n3_showing = False
			self.az.setRange(-360,360)
			self.alt.setRange(-180,180)
			self.phi.setRange(-360,660)
		
		if ( self.src_map[str(val)] == EULER_SPIDER ):
			self.az.setLabel('phi')
			self.alt.setLabel('theta')
			self.phi.setLabel('psi')
		elif ( self.src_map[str(val)] == EULER_EMAN ):
			self.az.setLabel('az')
			self.alt.setLabel('alt')
			self.phi.setLabel('phi')
		elif ( self.src_map[str(val)] == EULER_IMAGIC ):
			self.az.setLabel('alpha')
			self.alt.setLabel('beta')
			self.phi.setLabel('gamma')
		elif ( self.src_map[str(val)] == EULER_XYZ ):
			self.az.setLabel('xtilt')
			self.alt.setLabel('ytilt')
			self.phi.setLabel('ztilt')
		elif ( self.src_map[str(val)] == EULER_MRC ):
			self.az.setLabel('phi')
			self.alt.setLabel('theta')
			self.phi.setLabel('omega')
		elif ( self.src_map[str(val)] == EULER_SPIN ):
			self.az.setLabel('Omega')
			self.alt.setRange(-1,1)
			self.phi.setRange(-1,1)
			
			self.alt.setLabel('n1')
			self.phi.setLabel('n2')
			
			self.n3 = ValSlider(self,(-360.0,360.0),"n3",-1)
			self.n3.setRange(-1,1)
			self.n3.setObjectName("n3")
			self.vbl.addWidget(self.n3)
			QtCore.QObject.connect(self.n3, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
			self.n3_showing = True
		
		self.current_src = self.src_map[str(val)]
		self.update_rotations(t3d)
	
	def load_src_options(self,widgit):
		self.load_src()
		for i in self.src_strings:
			widgit.addItem(i)
	
	# read src as 'supported rotation conventions'
	def load_src(self):
		# supported_rot_conventions
		src_flags = []
		src_flags.append(EULER_EMAN)
		src_flags.append(EULER_SPIDER)
		src_flags.append(EULER_IMAGIC)
		src_flags.append(EULER_MRC)
		src_flags.append(EULER_SPIN)
		src_flags.append(EULER_XYZ)
		
		self.src_strings = []
		self.src_map = {}
		for i in src_flags:
			self.src_strings.append(str(i))
			self.src_map[str(i)] = i
		
	
	def setColors(self,colors,current_color):
		a = 0
		for i in colors:
			self.cbb.addItem(i)
			if ( i == current_color):
				self.cbb.setCurrentIndex(a)
			a += 1

	def set_scale(self,newscale):
		self.scale.setValue(newscale)
Exemplo n.º 8
0
class GUIctfsim(QtGui.QWidget):
	def __init__(self,application,apix=1.0,voltage=300.0,cs=4.1,ac=10.0,samples=256):
		"""CTF simulation dialog
		"""
		try:
			from emimage2d import EMImage2DWidget
		except:
			print "Cannot import EMAN image GUI objects (EMImage2DWidget)"
			sys.exit(1)
		try:
			from emplot2d import EMPlot2DWidget
		except:
			print "Cannot import EMAN plot GUI objects (is matplotlib installed?)"
			sys.exit(1)

		self.app = weakref.ref(application)

		self.df_voltage=voltage
		self.df_apix=apix
		self.df_cs=cs
		self.df_ac=ac
		self.df_samples=samples
		self.img=None

		QtGui.QWidget.__init__(self,None)
		self.setWindowIcon(QtGui.QIcon(get_image_directory() + "ctf.png"))

		self.data=[]
		self.curset=0
		self.plotmode=0

		self.guiim=EMImage2DWidget(application=self.app())
		self.guiiminit = True # a flag that's used to auto resize the first time the gui's set_data function is called
		self.guiplot=EMPlot2DWidget(application=self.app())
#		self.guirealim=EMImage2DWidget(application=self.app())	# This will show the original particle images

#		self.guirealim.connect(self.guirealim,QtCore.SIGNAL("keypress"),self.realimgkey)
		self.guiim.connect(self.guiim,QtCore.SIGNAL("mousedown"),self.imgmousedown)
		self.guiim.connect(self.guiim,QtCore.SIGNAL("mousedrag"),self.imgmousedrag)
		self.guiim.connect(self.guiim,QtCore.SIGNAL("mouseup")  ,self.imgmouseup)
		self.guiplot.connect(self.guiplot,QtCore.SIGNAL("mousedown"),self.plotmousedown)

		self.guiim.mmode="app"

		# This object is itself a widget we need to set up
		self.hbl = QtGui.QHBoxLayout(self)
		self.hbl.setMargin(0)
		self.hbl.setSpacing(6)
		self.hbl.setObjectName("hbl")

		# plot list and plot mode combobox
		self.vbl2 = QtGui.QVBoxLayout()
		self.setlist=MyListWidget(self)
		self.setlist.setSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Expanding)
		self.vbl2.addWidget(self.setlist)

		self.splotmode=QtGui.QComboBox(self)
		self.splotmode.addItem("Amplitude")
		self.splotmode.addItem("Intensity")
		self.splotmode.addItem("Int w sum")
		self.splotmode.addItem("Amp w sum")
		self.vbl2.addWidget(self.splotmode)
		self.hbl.addLayout(self.vbl2)

		# ValSliders for CTF parameters
		self.vbl = QtGui.QVBoxLayout()
		self.vbl.setMargin(0)
		self.vbl.setSpacing(6)
		self.vbl.setObjectName("vbl")
		self.hbl.addLayout(self.vbl)

		#self.samp = ValSlider(self,(0,5.0),"Amp:",0)
		#self.vbl.addWidget(self.samp)

		self.imginfo=QtGui.QLabel("Info",self)
		self.vbl.addWidget(self.imginfo)

		self.sdefocus=ValSlider(self,(0,5),"Defocus:",0,90)
		self.vbl.addWidget(self.sdefocus)

		self.sbfactor=ValSlider(self,(0,1600),"B factor:",0,90)
		self.vbl.addWidget(self.sbfactor)

		self.sdfdiff=ValSlider(self,(0,1),"DF Diff:",0,90)
		self.vbl.addWidget(self.sdfdiff)

		self.sdfang=ValSlider(self,(0,180),"Df Angle:",0,90)
		self.vbl.addWidget(self.sdfang)

		self.sampcont=ValSlider(self,(0,100),"% AC",0,90)
		self.vbl.addWidget(self.sampcont)

		self.sapix=ValSlider(self,(.2,10),"A/Pix:",2,90)
		self.vbl.addWidget(self.sapix)

		self.svoltage=ValSlider(self,(0,1000),"Voltage (kV):",0,90)
		self.vbl.addWidget(self.svoltage)

		self.scs=ValSlider(self,(0,5),"Cs (mm):",0,90)
		self.vbl.addWidget(self.scs)

		self.ssamples=ValSlider(self,(32,1024),"# Samples:",0,90)
		self.ssamples.setIntonly(True)
		self.vbl.addWidget(self.ssamples)


		self.hbl_buttons = QtGui.QHBoxLayout()
		self.newbut = QtGui.QPushButton("New")
		self.hbl_buttons.addWidget(self.newbut)
		self.vbl.addLayout(self.hbl_buttons)

		self.on_new_but()

		QtCore.QObject.connect(self.sdefocus, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.sbfactor, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.sdfdiff, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.sdfang, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.sapix, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.sampcont, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.svoltage, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.scs, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.ssamples, QtCore.SIGNAL("valueChanged"), self.newCTF)
		QtCore.QObject.connect(self.setlist,QtCore.SIGNAL("currentRowChanged(int)"),self.newSet)
		QtCore.QObject.connect(self.setlist,QtCore.SIGNAL("keypress"),self.listkey)
		QtCore.QObject.connect(self.splotmode,QtCore.SIGNAL("currentIndexChanged(int)"),self.newPlotMode)

	   	QtCore.QObject.connect(self.newbut,QtCore.SIGNAL("clicked(bool)"),self.on_new_but)


		self.resize(720,380) # figured these values out by printing the width and height in resize event


		E2loadappwin("e2ctfsim","main",self)
		E2loadappwin("e2ctfsim","image",self.guiim.qt_parent)
#		E2loadappwin("e2ctf","realimage",self.guirealim.qt_parent)
		E2loadappwin("e2ctfsim","plot",self.guiplot.qt_parent)

		self.setWindowTitle("CTF")

	def listkey(self,event):

		if event.key()>=Qt.Key_0 and event.key()<=Qt.Key_9 :
			q=int(event.key())-Qt.Key_0
			self.squality.setValue(q)
		elif event.key() == Qt.Key_Left:
			self.sdefocus.setValue(self.sdefocus.getValue()-0.01)
		elif event.key() == Qt.Key_Right:
			self.sdefocus.setValue(self.sdefocus.getValue()+0.01)
		elif event.key()==Qt.Key_R :
			self.on_recall_params()


	def on_new_but(self):
		ctf=EMAN2Ctf()
		ctf.defocus=1.0
		ctf.voltage=self.df_voltage
		ctf.apix=self.df_apix
		ctf.cs=self.df_cs
		ctf.ac=self.df_ac
		ctf.samples=self.df_samples
		self.data.append((str(len(self.setlist)+1),ctf))
		self.curset=len(self.data)
		self.update_data()
		
	def show_guis(self):
		if self.guiim != None:
			self.app().show_specific(self.guiim)
		if self.guiplot != None:
			self.app().show_specific(self.guiplot)
		#if self.guirealim != None:
			#self.app().show_specific(self.guirealim)

		self.show()

	def closeEvent(self,event):
#		QtGui.QWidget.closeEvent(self,event)
#		self.app.app.closeAllWindows()
		E2saveappwin("e2ctf","main",self)

		if self.guiim != None:
			E2saveappwin("e2ctf","image",self.guiim.qt_parent)
			self.app().close_specific(self.guiim)
			self.guiim = None
		if self.guiplot != None:
			E2saveappwin("e2ctf","plot",self.guiplot.qt_parent)
			self.app().close_specific(self.guiplot)
		#if self.guirealim != None:
			#E2saveappwin("e2ctf","realimage",self.guirealim.qt_parent)
			#self.app().close_specific(self.guirealim)

		event.accept()
		self.app().close_specific(self)
		self.emit(QtCore.SIGNAL("module_closed")) # this signal is important when e2ctf is being used by a program running its own event loop

	def update_data(self):
		"""This will make sure the various widgets properly show the current data sets"""
		self.setlist.clear()
		for i,j in enumerate(self.data):
			self.setlist.addItem(j[0])
		self.setlist.setCurrentRow(self.curset)

	def update_plot(self):
		if self.guiplot == None: return # it's closed/not visible

		for d in xrange(len(self.data)):
			ctf=self.data[d][1]
			ds=1.0/(ctf.apix*2.0*ctf.samples)
			s=arange(0,ds*ctf.samples,ds)
			
			curve=array(ctf.compute_1d(len(s)*2,ds,Ctf.CtfType.CTF_AMP))
			if self.plotmode==1 or self.plotmode==2:
				curve=curve**2
			
			if self.plotmode==2 or self.plotmode==3:
				if d==0 : avg=curve[:]
				else:
					if len(curve)!=len(avg) :
						print "Number of samples must be fixed to compute an average ({})".format(d+1)
					else:
						avg+=curve
			
			self.guiplot.set_data((s,curve),self.data[d][0],d==0,True,color=d+1)

		if self.plotmode in (2,3) :
			self.guiplot.set_data((s,avg),"Sum",False,True,color=0)
			
		self.guiplot.setAxisParms("s (1/$\AA$)","CTF")

		ctf.compute_2d_complex(self.img,Ctf.CtfType.CTF_AMP,None)
		self.guiim.set_data(self.img)

	def newSet(self,val=0):
		"called when a new data set is selected from the list"
		self.curset=val

		self.sdefocus.setValue(self.data[val][1].defocus,True)
		self.sbfactor.setValue(self.data[val][1].bfactor,True)
		self.sapix.setValue(self.data[val][1].apix,True)
		self.sampcont.setValue(self.data[val][1].ampcont,True)
		self.svoltage.setValue(self.data[val][1].voltage,True)
		self.scs.setValue(self.data[val][1].cs,True)
		self.sdfdiff.setValue(self.data[val][1].dfdiff,True)
		self.sdfang.setValue(self.data[val][1].dfang,True)
		self.ssamples.setValue(self.data[val][1].samples,True)

		# make new image if necessary
		if self.img==None or self.img["ny"]!=self.data[val][1].samples :
			self.img=EMData(self.data[val][1].samples+2,self.data[val][1].samples)
			self.img.to_zero()
			self.img.set_complex(1)
		self.guiim.set_data(self.img)
#		self.imginfo.setText("%s particles     SNR = %s"%(ptcl,ssnr))

		#if self.guiim != None:
##			print self.data
			#self.guiim.set_data(self.data[val][4])
			#if self.guiiminit:
				#self.guiim.optimally_resize()
				#self.guiiminit = False
			#self.guiim.updateGL()
		#self.update_plot()

#		print "self.data[val]=",self.data[val][0].split('#')[-1]


		self.guiim.qt_parent.setWindowTitle("e2ctfsim - 2D FFT - "+self.data[val][0])
#		self.guirealim.qt_parent.setWindowTitle("e2ctf - "+self.data[val][0].split('#')[-1])
		self.guiplot.qt_parent.setWindowTitle("e2ctfsim - Plot ")

		#n=EMUtil.get_image_count(self.data[val][0])
		#if n>1:
			#self.ptcldata=EMData.read_images(self.data[val][0],range(0,min(20,n)))
			#im=sum(self.ptcldata)
			#im.mult(1.0/len(self.ptcldata))
			#self.ptcldata.insert(0,im)
			#self.guirealim.set_data(self.ptcldata)
		#else : self.guirealim.set_data([EMData()])
		self.update_plot()

	def newPlotMode(self,mode):
		self.plotmode=mode
		self.update_plot()

	def newCTF(self) :
#		print traceback.print_stack()
		self.data[self.curset][1].defocus=self.sdefocus.value
		self.data[self.curset][1].bfactor=self.sbfactor.value
		self.data[self.curset][1].dfdiff=self.sdfdiff.value
		self.data[self.curset][1].dfang=self.sdfang.value
		self.data[self.curset][1].apix=self.sapix.value
		self.data[self.curset][1].ampcont=self.sampcont.value
		self.data[self.curset][1].voltage=self.svoltage.value
		self.data[self.curset][1].cs=self.scs.value
		self.data[self.curset][1].samples=self.ssamples.value
		
		if self.img==None or self.img["ny"]!=self.ssamples.value :
			self.img=EMData(self.ssamples.value+2,self.ssamples.value)
			self.img.to_zero()
			self.img.set_complex(1)
			self.guiim.set_data(self.img)
		self.update_plot()

	def realimgkey(self,event):
		"""Keypress in the image display window"""

		if event.key()==Qt.Key_I:			# if user presses I in this window we invert the stack on disk
			fsp=self.data[self.curset][0]
			n=EMUtil.get_image_count(fsp)
			print "Inverting images in %s"%fsp
			for i in xrange(n):
				img=EMData(fsp,i)
				img.mult(-1.0)
				img.write_image(fsp,i)

			#self.ptcldata=EMData.read_images(fsp,range(0,20))
			#self.guirealim.set_data(self.ptcldata)


	def imgmousedown(self,event) :
		m=self.guiim.scr_to_img((event.x(),event.y()))
		#self.guiim.add_shape("cen",["rect",.9,.9,.4,x0,y0,x0+2,y0+2,1.0])

	def imgmousedrag(self,event) :
		m=self.guiim.scr_to_img((event.x(),event.y()))

		# box deletion when shift held down
		#if event.modifiers()&Qt.ShiftModifier:
			#for i,j in enumerate(self.boxes):

	def imgmouseup(self,event) :
		m=self.guiim.scr_to_img((event.x(),event.y()))

	def plotmousedown(self,event) :
		m=self.guiim.scr_to_img((event.x(),event.y()))

	def run(self):
		"""If you make your own application outside of this object, you are free to use
		your own local app.exec_(). This is a convenience for ctf-only programs."""
		self.app.exec_()

#		E2saveappwin("boxer","imagegeom",self.guiim)
#		try:
#			E2setappval("boxer","imcontrol",self.guiim.inspector.isVisible())
#			if self.guiim.inspector.isVisible() : E2saveappwin("boxer","imcontrolgeom",self.guiim.inspector)
#		except : E2setappval("boxer","imcontrol",False)

		return
Exemplo n.º 9
0
class EMTransformPanel:
    def __init__(self, target, parent):
        self.target = weakref.ref(target)
        self.parent = weakref.ref(parent)

        self.label_src = QtGui.QLabel(parent)
        self.label_src.setText('Rotation Convention')

        self.src = QtGui.QComboBox(parent)
        self.load_src_options(self.src)

        self.x_label = QtGui.QLabel()
        self.x_label.setText('x')

        self.x_trans = QtGui.QDoubleSpinBox(parent)
        self.x_trans.setMinimum(-10000)
        self.x_trans.setMaximum(10000)
        self.x_trans.setValue(0.0)

        self.y_label = QtGui.QLabel()
        self.y_label.setText('y')

        self.y_trans = QtGui.QDoubleSpinBox(parent)
        self.y_trans.setMinimum(-10000)
        self.y_trans.setMaximum(10000)
        self.y_trans.setValue(0.0)

        self.z_label = QtGui.QLabel()
        self.z_label.setText('z')

        self.z_trans = QtGui.QDoubleSpinBox(parent)
        self.z_trans.setMinimum(-10000)
        self.z_trans.setMaximum(10000)
        self.z_trans.setValue(0.0)

        self.az = ValSlider(parent, (-360.0, 360.0), "az", -1)
        self.az.setObjectName("az")
        self.az.setValue(0.0)

        self.alt = ValSlider(parent, (-180.0, 180.0), "alt", -1)
        self.alt.setObjectName("alt")
        self.alt.setValue(0.0)

        self.phi = ValSlider(parent, (-360.0, 360.0), "phi", -1)
        self.phi.setObjectName("phi")
        self.phi.setValue(0.0)

        self.scale = ValSlider(parent, (0.01, 30.0), "Zoom:")
        self.scale.setObjectName("scale")
        self.scale.setValue(1.0)

        self.n3_showing = False

        self.current_src = "eman"

        QtCore.QObject.connect(self.az, QtCore.SIGNAL("valueChanged"),
                               self.slider_rotate)
        QtCore.QObject.connect(self.alt, QtCore.SIGNAL("valueChanged"),
                               self.slider_rotate)
        QtCore.QObject.connect(self.phi, QtCore.SIGNAL("valueChanged"),
                               self.slider_rotate)
        QtCore.QObject.connect(self.src,
                               QtCore.SIGNAL("currentIndexChanged(QString)"),
                               self.set_src)
        QtCore.QObject.connect(self.scale, QtCore.SIGNAL("valueChanged"),
                               self.target().set_scale)
        QtCore.QObject.connect(self.x_trans,
                               QtCore.SIGNAL("valueChanged(double)"),
                               self.target().set_cam_x)
        QtCore.QObject.connect(self.y_trans,
                               QtCore.SIGNAL("valueChanged(double)"),
                               self.target().set_cam_y)
        QtCore.QObject.connect(self.z_trans,
                               QtCore.SIGNAL("valueChanged(double)"),
                               self.target().set_cam_z)

    def set_defaults(self):
        self.x_trans.setValue(0.0)
        self.y_trans.setValue(0.0)
        self.z_trans.setValue(0.0)
        self.scale.setValue(1.0)
        self.az.setValue(0.0)
        self.alt.setValue(0.0)
        self.phi.setValue(0.0)

    def slider_rotate(self):
        self.target().load_rotation(self.get_current_rotation())

    def get_current_rotation(self):
        convention = self.src.currentText()
        rot = {}
        if (self.current_src == "spin"):
            rot[self.az.getLabel()] = self.az.getValue()

            n1 = self.alt.getValue()
            n2 = self.phi.getValue()
            n3 = self.n3.getValue()

            norm = sqrt(n1 * n1 + n2 * n2 + n3 * n3)

            n1 /= norm
            n2 /= norm
            n3 /= norm

            rot[self.alt.getLabel()] = n1
            rot[self.phi.getLabel()] = n2
            rot[self.n3.getLabel()] = n3

        else:
            rot[self.az.getLabel()] = self.az.getValue()
            rot[self.alt.getLabel()] = self.alt.getValue()
            rot[self.phi.getLabel()] = self.phi.getValue()

        rot["type"] = self.current_src

        return Transform(rot)

    def addWidgets(self, target):

        target.addWidget(self.scale)
        self.hbl_trans = QtGui.QHBoxLayout()
        self.hbl_trans.setMargin(0)
        self.hbl_trans.setSpacing(6)
        self.hbl_trans.setObjectName("Trans")
        self.hbl_trans.addWidget(self.x_label)
        self.hbl_trans.addWidget(self.x_trans)
        self.hbl_trans.addWidget(self.y_label)
        self.hbl_trans.addWidget(self.y_trans)
        self.hbl_trans.addWidget(self.z_label)
        self.hbl_trans.addWidget(self.z_trans)

        target.addLayout(self.hbl_trans)

        self.hbl_src = QtGui.QHBoxLayout()
        self.hbl_src.setMargin(0)
        self.hbl_src.setSpacing(6)
        self.hbl_src.setObjectName("hbl")
        self.hbl_src.addWidget(self.label_src)
        self.hbl_src.addWidget(self.src)

        target.addLayout(self.hbl_src)
        target.addWidget(self.az)
        target.addWidget(self.alt)
        target.addWidget(self.phi)

    def set_src(self, val):
        t3d = self.get_current_rotation()

        if (self.n3_showing):
            self.parent().get_transform_layout().removeWidget(self.n3)
            self.n3.deleteLater()
            self.n3_showing = False
            self.az.setRange(-360, 360)
            self.alt.setRange(-180, 180)
            self.phi.setRange(-360, 660)

        if (self.src_map[str(val)] == "spider"):
            self.az.setLabel('phi')
            self.alt.setLabel('theta')
            self.phi.setLabel('psi')
        elif (self.src_map[str(val)] == "eman"):
            self.az.setLabel('az')
            self.alt.setLabel('alt')
            self.phi.setLabel('phi')
        elif (self.src_map[str(val)] == "imagic"):
            self.az.setLabel('alpha')
            self.alt.setLabel('beta')
            self.phi.setLabel('gamma')
        elif (self.src_map[str(val)] == "xyz"):
            self.az.setLabel('xtilt')
            self.alt.setLabel('ytilt')
            self.phi.setLabel('ztilt')
        elif (self.src_map[str(val)] == "mrc"):
            self.az.setLabel('phi')
            self.alt.setLabel('theta')
            self.phi.setLabel('omega')
        elif (self.src_map[str(val)] == "spin"):
            self.az.setLabel('omega')
            self.alt.setRange(-1, 1)
            self.phi.setRange(-1, 1)

            self.alt.setLabel('n1')
            self.phi.setLabel('n2')

            self.n3 = ValSlider(self.parent(), (-360.0, 360.0), "n3", -1)
            self.n3.setRange(-1, 1)
            self.n3.setObjectName("n3")
            self.parent().get_transform_layout().addWidget(self.n3)
            QtCore.QObject.connect(self.n3, QtCore.SIGNAL("valueChanged"),
                                   self.slider_rotate)
            self.n3_showing = True

        self.current_src = self.src_map[str(val)]
        self.update_rotations(t3d)

    def load_src_options(self, widgit):
        self.load_src()
        for i in self.src_strings:
            widgit.addItem(i)

    def load_src(self):
        # supported_rot_conventions
        src_flags = []
        src_flags.append("eman")
        src_flags.append("spider")
        src_flags.append("imagic")
        src_flags.append("mrc")
        src_flags.append("spin")
        src_flags.append("xyz")

        self.src_strings = []
        self.src_map = {}
        for i in src_flags:
            self.src_strings.append(str(i))
            self.src_map[str(i)] = i

    def update_rotations(self, t3d):
        rot = t3d.get_rotation(self.src_map[str(
            self.src.itemText(self.src.currentIndex()))])

        convention = self.src.currentText()
        if (self.src_map[str(convention)] == "spin"):
            self.n3.setValue(rot[self.n3.getLabel()], True)

        self.az.setValue(rot[self.az.getLabel()], True)
        self.alt.setValue(rot[self.alt.getLabel()], True)
        self.phi.setValue(rot[self.phi.getLabel()], True)

    def set_scale(self, newscale):
        self.scale.setValue(newscale)

    def set_xy_trans(self, x, y):
        self.x_trans.setValue(x)
        self.y_trans.setValue(y)

    def set_xyz_trans(self, x, y, z):
        self.x_trans.setValue(x)
        self.y_trans.setValue(y)
        self.z_trans.setValue(z)
Exemplo n.º 10
0
class EMInspectorControlLine(EMInspectorControlShape):
	"""
	Class to make EMItem GUI SHAPE Line Inspector
	"""
	def __init__(self, name, item3d):
		EMInspectorControlShape.__init__(self, name, item3d)
		
	def updateItemControls(self):
		""" Updates this item inspector. Function is called by the item it observes"""
		super(EMInspectorControlLine, self).updateItemControls()
	
	def updateMetaData(self):
		""" Updates the items metadata, such as line length, width. Function is called by the item it observes when the items meta data changes """
		super(EMInspectorControlLine, self).updateMetaData()
		self.leftArrowSize.setValue(self.item3d().leftArrowSize, quiet=1)
		self.leftArrowLength.setValue(self.item3d().leftArrowLength, quiet=1)
		self.rightArrowSize.setValue(self.item3d().rightArrowSize, quiet=1)
		self.rightArrowLength.setValue(self.item3d().rightArrowLength, quiet=1)
		self.slice.setValue(self.item3d().slices, quiet=1)
		self.stack.setValue(self.item3d().stacks, quiet=1)
		self.linelength.setValue(int(self.item3d().length), quiet=1)
	
	def addTabs(self):
		""" Add a tab for each 'column' """
		super(EMInspectorControlLine, self).addTabs()
		tabwidget = QtGui.QWidget()
		gridbox = QtGui.QGridLayout()
		
		EMInspectorControlLine.addControls(self, gridbox)
		
		tabwidget.setLayout(gridbox)
		self.addTab(tabwidget, "line")
		
	def addControls(self, gridbox):
		""" Construct all the widgets in this Item Inspector """
		#frame to control properties of left/right arrows
		lineframe = QtGui.QFrame()
		lineframe.setFrameShape(QtGui.QFrame.StyledPanel)
		lfont = QtGui.QFont()
		lfont.setBold(True)
		linegridbox = QtGui.QGridLayout()
		
		leftlabel = QtGui.QLabel("Left arrow")
		leftlabel.setFont(lfont)
		leftlabel.setAlignment(QtCore.Qt.AlignCenter)
		linegridbox.addWidget(leftlabel, 0, 1, 1, 1)
		
		sidelabel1 = QtGui.QLabel("Size")
		sidelabel1.setFont(lfont)
		sidelabel1.setAlignment(QtCore.Qt.AlignVCenter)
		linegridbox.addWidget(sidelabel1, 2, 0, 1, 1)
		
		sidelabel2 = QtGui.QLabel("Length")
		sidelabel2.setFont(lfont)
		sidelabel2.setAlignment(QtCore.Qt.AlignVCenter)
		linegridbox.addWidget(sidelabel2, 3, 0, 1, 1)
		
		self.leftShowArrow = QtGui.QCheckBox("Show")
		self.leftShowArrow.setChecked(self.item3d().showLeftArrow)
		linegridbox.addWidget(self.leftShowArrow, 1, 1, 1, 1)
		
		self.leftArrowSize = EMSpinWidget(int(self.item3d().leftArrowSize), 1.0, rounding=0)
		self.leftArrowSize.setMinimumWidth(120)
		linegridbox.addWidget(self.leftArrowSize, 2, 1, 1, 1)
		
		self.leftArrowLength = EMSpinWidget(int(self.item3d().leftArrowLength), 1.0, rounding=0)
		self.leftArrowLength.setMinimumWidth(120)
		linegridbox.addWidget(self.leftArrowLength, 3, 1, 1, 1)
		
		rightlabel = QtGui.QLabel("Right arrow")
		rightlabel.setFont(lfont)
		rightlabel.setAlignment(QtCore.Qt.AlignCenter)
		linegridbox.addWidget(rightlabel, 0, 2, 1, 1)
		
		self.rightShowArrow = QtGui.QCheckBox("Show")
		self.rightShowArrow.setChecked(self.item3d().showRightArrow)
		linegridbox.addWidget(self.rightShowArrow, 1, 2, 1, 1)
		
		self.rightArrowSize = EMSpinWidget(int(self.item3d().rightArrowSize), 1.0, rounding=0)
		self.rightArrowSize.setMinimumWidth(120)
		linegridbox.addWidget(self.rightArrowSize, 2, 2, 1, 1)
		
		self.rightArrowLength = EMSpinWidget(int(self.item3d().rightArrowLength), 1.0, rounding=0)
		self.rightArrowLength.setMinimumWidth(120)
		linegridbox.addWidget(self.rightArrowLength, 3, 2, 1, 1)
		
		linelengthlabel = QtGui.QLabel("Line Length")
		linelengthlabel.setFont(lfont)
		linelengthlabel.setAlignment(QtCore.Qt.AlignCenter)
		linegridbox.addWidget(linelengthlabel, 4, 0, 2, 2)
		
		self.linelength = EMSpinWidget(int(self.item3d().length), 1.0, rounding=0)
		linegridbox.addWidget(self.linelength, 4, 2, 2, 2)
		
		linewidthlabel = QtGui.QLabel("Line Width")
		linewidthlabel.setFont(lfont)
		linewidthlabel.setAlignment(QtCore.Qt.AlignCenter)
		linegridbox.addWidget(linewidthlabel, 5, 0, 1, 2)
		
		self.linewidth = EMSpinWidget(int(self.item3d().width), 1.0, rounding=0)
		linegridbox.addWidget(self.linewidth, 5, 2, 1, 2)
		
		lineframe.setLayout(linegridbox)	
		gridbox.addWidget(lineframe, 2, 0)
		
		#frame to control slice/stack of the line
		lineframe2 = QtGui.QFrame()
		lineframe2.setFrameShape(QtGui.QFrame.StyledPanel)
		linehbox = QtGui.QVBoxLayout()
				
		self.slice = ValSlider(lineframe2, (1, 100), "Slice", rounding=0)
		self.slice.setValue(self.item3d().slices)
		
		self.stack = ValSlider(lineframe2, (1, 100), "Stack", rounding=0)
		self.slice.setValue(self.item3d().stacks)
		
		linehbox.addWidget(self.slice)
		linehbox.addWidget(self.stack)
		
		lineframe2.setLayout(linehbox)
		gridbox.addWidget(lineframe2, 3, 0)
		
		# set to default, but run only as a base class
		if type(self) == EMInspectorControl3DText: 
			self.updateItemControls()
			self.updateMetaData()
		
		QtCore.QObject.connect(self.leftShowArrow, QtCore.SIGNAL("stateChanged(int)"), self.redraw)
		QtCore.QObject.connect(self.rightShowArrow, QtCore.SIGNAL("stateChanged(int)"), self.redraw)
		QtCore.QObject.connect(self.leftArrowSize,QtCore.SIGNAL("valueChanged(int)"),self.redraw)
		QtCore.QObject.connect(self.leftArrowLength,QtCore.SIGNAL("valueChanged(int)"),self.redraw)
		QtCore.QObject.connect(self.rightArrowSize,QtCore.SIGNAL("valueChanged(int)"),self.redraw)
		QtCore.QObject.connect(self.rightArrowLength,QtCore.SIGNAL("valueChanged(int)"),self.redraw)
		QtCore.QObject.connect(self.linelength,QtCore.SIGNAL("valueChanged(int)"),self.redraw)
		QtCore.QObject.connect(self.linewidth,QtCore.SIGNAL("valueChanged(int)"),self.redraw)
		
		QtCore.QObject.connect(self.slice,QtCore.SIGNAL("valueChanged"),self.redraw)
		QtCore.QObject.connect(self.stack,QtCore.SIGNAL("valueChanged"),self.redraw)

	def redraw(self):
		self.item3d().setShowLeftArrow(self.leftShowArrow.isChecked())
		self.item3d().setShowRightArrow(self.rightShowArrow.isChecked())
		self.item3d().leftArrowSize = self.leftArrowSize.getValue()
		self.item3d().leftArrowLength = self.leftArrowLength.getValue()
		self.item3d().rightArrowSize = self.rightArrowSize.getValue()
		self.item3d().rightArrowLength = self.rightArrowLength.getValue()
		self.item3d().setLength(self.linelength.getValue())
		self.item3d().setWidth(self.linewidth.getValue())
		
		self.item3d().setSlices(self.slice.getValue())
		self.item3d().setStacks(self.stack.getValue())
		
		if self.inspector:
			self.inspector().updateSceneGraph()
Exemplo n.º 11
0
class EMHelloWorldInspector(QtGui.QWidget):
	def __init__(self,target) :
		QtGui.QWidget.__init__(self,None)
		self.target=target
		
		self.vbl = QtGui.QVBoxLayout(self)
		self.vbl.setMargin(0)
		self.vbl.setSpacing(6)
		self.vbl.setObjectName("vbl")
		
		self.hbl = QtGui.QHBoxLayout()
		self.hbl.setMargin(0)
		self.hbl.setSpacing(6)
		self.hbl.setObjectName("hbl")
		self.vbl.addLayout(self.hbl)
		
		self.vbl2 = QtGui.QVBoxLayout()
		self.vbl2.setMargin(0)
		self.vbl2.setSpacing(6)
		self.vbl2.setObjectName("vbl2")
		self.hbl.addLayout(self.vbl2)
		
		self.wiretog = QtGui.QPushButton("Wire")
		self.wiretog.setCheckable(1)
		self.vbl2.addWidget(self.wiretog)
		
		self.lighttog = QtGui.QPushButton("Light")
		self.lighttog.setCheckable(1)
		self.vbl2.addWidget(self.lighttog)
		
		self.tabwidget = QtGui.QTabWidget()
		self.maintab = None
		self.tabwidget.addTab(self.get_main_tab(), "Main")
		self.tabwidget.addTab(self.get_GL_tab(),"GL")
		self.vbl.addWidget(self.tabwidget)
		self.n3_showing = False
		
		QtCore.QObject.connect(self.scale, QtCore.SIGNAL("valueChanged"), target.set_scale)
		QtCore.QObject.connect(self.az, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.alt, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.phi, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
		QtCore.QObject.connect(self.cbb, QtCore.SIGNAL("currentIndexChanged(QString)"), target.setColor)
		QtCore.QObject.connect(self.src, QtCore.SIGNAL("currentIndexChanged(QString)"), self.set_src)
		QtCore.QObject.connect(self.x_trans, QtCore.SIGNAL("valueChanged(double)"), target.set_cam_x)
		QtCore.QObject.connect(self.y_trans, QtCore.SIGNAL("valueChanged(double)"), target.set_cam_y)
		QtCore.QObject.connect(self.z_trans, QtCore.SIGNAL("valueChanged(double)"), target.set_cam_z)
		QtCore.QObject.connect(self.wiretog, QtCore.SIGNAL("toggled(bool)"), target.toggle_wire)
		QtCore.QObject.connect(self.lighttog, QtCore.SIGNAL("toggled(bool)"), target.toggle_light)
		QtCore.QObject.connect(self.glcontrast, QtCore.SIGNAL("valueChanged"), target.set_GL_contrast)
		QtCore.QObject.connect(self.glbrightness, QtCore.SIGNAL("valueChanged"), target.set_GL_brightness)
	
	def get_GL_tab(self):
		self.gltab = QtGui.QWidget()
		gltab = self.gltab
		
		gltab.vbl = QtGui.QVBoxLayout(self.gltab )
		gltab.vbl.setMargin(0)
		gltab.vbl.setSpacing(6)
		gltab.vbl.setObjectName("Main")
		
		self.glcontrast = ValSlider(gltab,(1.0,5.0),"GLShd:")
		self.glcontrast.setObjectName("GLShade")
		self.glcontrast.setValue(1.0)
		gltab.vbl.addWidget(self.glcontrast)
		
		self.glbrightness = ValSlider(gltab,(-1.0,0.0),"GLBst:")
		self.glbrightness.setObjectName("GLBoost")
		self.glbrightness.setValue(0.1)
		self.glbrightness.setValue(0.0)
		gltab.vbl.addWidget(self.glbrightness)
	
		return gltab
	
	def get_main_tab(self):
		if ( self.maintab == None ):
			self.maintab = QtGui.QWidget()
			maintab = self.maintab
			maintab.vbl = QtGui.QVBoxLayout(self.maintab)
			maintab.vbl.setMargin(0)
			maintab.vbl.setSpacing(6)
			maintab.vbl.setObjectName("Main")
			
			self.scale = ValSlider(maintab,(0.01,30.0),"Zoom:")
			self.scale.setObjectName("scale")
			self.scale.setValue(1.0)
			maintab.vbl.addWidget(self.scale)
			
			self.hbl_color = QtGui.QHBoxLayout()
			self.hbl_color.setMargin(0)
			self.hbl_color.setSpacing(6)
			self.hbl_color.setObjectName("Material")
			maintab.vbl.addLayout(self.hbl_color)
			
			self.color_label = QtGui.QLabel()
			self.color_label.setText('Material')
			self.hbl_color.addWidget(self.color_label)
			
			self.cbb = QtGui.QComboBox(maintab)
			self.hbl_color.addWidget(self.cbb)
	
			self.hbl_trans = QtGui.QHBoxLayout()
			self.hbl_trans.setMargin(0)
			self.hbl_trans.setSpacing(6)
			self.hbl_trans.setObjectName("Trans")
			maintab.vbl.addLayout(self.hbl_trans)
			
			self.x_label = QtGui.QLabel()
			self.x_label.setText('x')
			self.hbl_trans.addWidget(self.x_label)
			
			self.x_trans = QtGui.QDoubleSpinBox(self)
			self.x_trans.setMinimum(-10000)
			self.x_trans.setMaximum(10000)
			self.x_trans.setValue(0.0)
			self.hbl_trans.addWidget(self.x_trans)
			
			self.y_label = QtGui.QLabel()
			self.y_label.setText('y')
			self.hbl_trans.addWidget(self.y_label)
			
			self.y_trans = QtGui.QDoubleSpinBox(maintab)
			self.y_trans.setMinimum(-10000)
			self.y_trans.setMaximum(10000)
			self.y_trans.setValue(0.0)
			self.hbl_trans.addWidget(self.y_trans)
			
			
			self.z_label = QtGui.QLabel()
			self.z_label.setText('z')
			self.hbl_trans.addWidget(self.z_label)
			
			self.z_trans = QtGui.QDoubleSpinBox(maintab)
			self.z_trans.setMinimum(-10000)
			self.z_trans.setMaximum(10000)
			self.z_trans.setValue(0.0)
			self.hbl_trans.addWidget(self.z_trans)
			
			self.hbl_src = QtGui.QHBoxLayout()
			self.hbl_src.setMargin(0)
			self.hbl_src.setSpacing(6)
			self.hbl_src.setObjectName("hbl")
			maintab.vbl.addLayout(self.hbl_src)
			
			self.label_src = QtGui.QLabel()
			self.label_src.setText('Rotation Convention')
			self.hbl_src.addWidget(self.label_src)
			
			self.src = QtGui.QComboBox(maintab)
			self.load_src_options(self.src)
			self.hbl_src.addWidget(self.src)
			
			# set default value -1 ensures that the val slider is updated the first time it is created
			self.az = ValSlider(self,(-360.0,360.0),"az",-1)
			self.az.setObjectName("az")
			maintab.vbl.addWidget(self.az)
			
			self.alt = ValSlider(self,(-180.0,180.0),"alt",-1)
			self.alt.setObjectName("alt")
			maintab.vbl.addWidget(self.alt)
			
			self.phi = ValSlider(self,(-360.0,360.0),"phi",-1)
			self.phi.setObjectName("phi")
			maintab.vbl.addWidget(self.phi)
		
			self.current_src = EULER_EMAN
		
		return self.maintab

	def set_xy_trans(self, x, y):
		self.x_trans.setValue(x)
		self.y_trans.setValue(y)
	
	def set_xyz_trans(self,x,y,z):
		self.x_trans.setValue(x)
		self.y_trans.setValue(y)
		self.z_trans.setValue(z)
		
	def set_translate_scale(self, xscale,yscale,zscale):
		self.x_trans.setSingleStep(xscale)
		self.y_trans.setSingleStep(yscale)
		self.z_trans.setSingleStep(zscale)

	def update_rotations(self,t3d):
		convention = str( self.src.currentText() )
		#FIXME: Transform.get_rotation() wants a string sometimes and a EulerType other times
		try:
			rot = t3d.get_rotation(str(self.src_map[convention]))
		except Exception as e: #doing a quick fix
			print(e)
			print("Developers: This catches a large range of exceptions... a better way surely exists")
			rot = t3d.get_rotation(self.src_map[convention])
		
		if ( self.src_map[convention] == EULER_SPIN ):
			self.n3.setValue(rot[self.n3.getLabel()],True)
		
		self.az.setValue(rot[self.az.getLabel()],True)
		self.alt.setValue(rot[self.alt.getLabel()],True)
		self.phi.setValue(rot[self.phi.getLabel()],True)
	
	def slider_rotate(self):
		self.target.load_rotation(self.get_current_rotation())
	
	def get_current_rotation(self):
		convention = self.src.currentText()
		rot = {}
		if ( self.current_src == EULER_SPIN ):
			rot[self.az.getLabel()] = self.az.getValue()
			
			n1 = self.alt.getValue()
			n2 = self.phi.getValue()
			n3 = self.n3.getValue()
			
			norm = sqrt(n1*n1 + n2*n2 + n3*n3)
			
			n1 /= norm
			n2 /= norm
			n3 /= norm
			
			rot[self.alt.getLabel()] = n1
			rot[self.phi.getLabel()] = n2
			rot[self.n3.getLabel()] = n3
			
		else:
			rot[self.az.getLabel()] = self.az.getValue()
			rot[self.alt.getLabel()] = self.alt.getValue()
			rot[self.phi.getLabel()] = self.phi.getValue()
		
		return Transform(self.current_src, rot)
	
	def set_src(self, val):
		t3d = self.get_current_rotation()
		
		if (self.n3_showing) :
			self.vbl.removeWidget(self.n3)
			self.n3.deleteLater()
			self.n3_showing = False
			self.az.setRange(-360,360)
			self.alt.setRange(-180,180)
			self.phi.setRange(-360,660)
		
		if ( self.src_map[str(val)] == EULER_SPIDER ):
			self.az.setLabel('phi')
			self.alt.setLabel('theta')
			self.phi.setLabel('psi')
		elif ( self.src_map[str(val)] == EULER_EMAN ):
			self.az.setLabel('az')
			self.alt.setLabel('alt')
			self.phi.setLabel('phi')
		elif ( self.src_map[str(val)] == EULER_IMAGIC ):
			self.az.setLabel('alpha')
			self.alt.setLabel('beta')
			self.phi.setLabel('gamma')
		elif ( self.src_map[str(val)] == EULER_XYZ ):
			self.az.setLabel('xtilt')
			self.alt.setLabel('ytilt')
			self.phi.setLabel('ztilt')
		elif ( self.src_map[str(val)] == EULER_MRC ):
			self.az.setLabel('phi')
			self.alt.setLabel('theta')
			self.phi.setLabel('omega')
		elif ( self.src_map[str(val)] == EULER_SPIN ):
			self.az.setLabel('omega')
			self.alt.setRange(-1,1)
			self.phi.setRange(-1,1)
			
			self.alt.setLabel('n1')
			self.phi.setLabel('n2')
			
			self.n3 = ValSlider(self,(-360.0,360.0),"n3",-1)
			self.n3.setRange(-1,1)
			self.n3.setObjectName("n3")
			self.vbl.addWidget(self.n3)
			QtCore.QObject.connect(self.n3, QtCore.SIGNAL("valueChanged"), self.slider_rotate)
			self.n3_showing = True
		
		self.current_src = self.src_map[str(val)]
		self.update_rotations(t3d)
	
	def load_src_options(self,widgit):
		self.load_src()
		for i in self.src_strings:
			widgit.addItem(i)
	
	# read src as 'supported rotation conventions'
	def load_src(self):
		# supported_rot_conventions
		src_flags = []
		src_flags.append(EULER_EMAN)
		src_flags.append(EULER_SPIDER)
		src_flags.append(EULER_IMAGIC)
		src_flags.append(EULER_MRC)
		src_flags.append(EULER_SPIN)
		src_flags.append(EULER_XYZ)
		
		self.src_strings = []
		self.src_map = {}
		for i in src_flags:
			self.src_strings.append(str(i))
			self.src_map[str(i)] = i
		
	
	def setColors(self,colors,current_color):
		a = 0
		for i in colors:
			self.cbb.addItem(i)
			if ( i == current_color):
				self.cbb.setCurrentIndex(a)
			a += 1

	def set_scale(self,newscale):
		self.scale.setValue(newscale)