示例#1
0
    def __init__(self, viewer, parent, texture_file):
        QGLWidget.__init__(self)
        threading.Thread.__init__(self)

        self.texture_file = texture_file
        self.program_active = True
        self.mouse_origin = 0
        self.alpha = .2
        self.mouse_pos = None

        self.x_ticks = 0
        self.y_ticks = 0

        self.view = viewer.get_View()
        self.data_sets = viewer.get_Data()
        self.title = viewer.get_Title()
        self.tool_qb = ToolQB()
        self.rubberband = RectRubberband()
        self.setMouseTracking(True)
        self.prevView = None

        self.kd_tree = []
        self.kd_tree_active = False
        self.graphicsProxyWidget()
        self.scale_x = 0
        self.scale_y = 0
        self.width = 0
        self.height = 0
        self.ratio = 0
        self.orig_kd_tree = None
        self.lock = thread.allocate_lock()
        self.parent = parent

        # Starts the thread of anything inside of the run() method
        self.start()
示例#2
0
class GLPlotWidget(QGLWidget, threading.Thread):
    """
    Anything here is just for the plot objects
    """

    def __init__(self, viewer, parent, texture_file):
        QGLWidget.__init__(self)
        threading.Thread.__init__(self)

        self.texture_file = texture_file
        self.program_active = True
        self.mouse_origin = 0
        self.alpha = .2
        self.mouse_pos = None

        self.x_ticks = 0
        self.y_ticks = 0

        self.view = viewer.get_View()
        self.data_sets = viewer.get_Data()
        self.title = viewer.get_Title()
        self.tool_qb = ToolQB()
        self.rubberband = RectRubberband()
        self.setMouseTracking(True)
        self.prevView = None

        self.kd_tree = []
        self.kd_tree_active = False
        self.graphicsProxyWidget()
        self.scale_x = 0
        self.scale_y = 0
        self.width = 0
        self.height = 0
        self.ratio = 0
        self.orig_kd_tree = None
        self.lock = thread.allocate_lock()
        self.parent = parent

        # Starts the thread of anything inside of the run() method
        self.start()

    def initTexture(self):
        data = np.load(self.texture_file)
        data = rescale_data_to_image(data)
        w, h = data.shape

        # generate a texture id, make it current
        self.texture = gl.glGenTextures(1)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture)

        # texture mode and parameters controlling wrapping and scaling
        gl.glTexEnvf(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE)
        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT)
        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT)
        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)

        # map the image data to the texture. note that if the input
        # type is GL_FLOAT, the values must be in the range [0..1]
        gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, w, h, 0,
                        gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, data)

    def recreate_kd_tree(self):
        if (self.width == 0) or (self.height == 0):
            return
        with self.lock:
            self.ratio = float(self.height) / float(self.width)
            self.scale_x = float(self.view.width())
            self.scale_y = float(self.view.height())

            # highlighting using the kd_tree method being iterated over time
            for dset in self.data_sets:
                _data = np.array(dset.getFilteredDataSet(self.view.view()), copy=True)
                # In case the data-size is empty after filtering
                if _data.size == 0:
                    continue

                _data[:, 0] /= (self.scale_x * self.ratio)
                _data[:, 1] /= self.scale_y

                self.kd_tree.append(
                    KDTreeWritable(dset.getTitle(), _data[:, 0:2], leafsize=100, use_cache_data=False).load()
                )

            if self.orig_kd_tree is None:
                self.orig_kd_tree = self.kd_tree

            print "kd_tree complete for " + self.title
            self.kd_tree_active = True

    def run(self):
        while self.program_active:

            if not self.kd_tree_active:
                self.kd_tree = []
                print "Creating kd_tree for " + self.title
                self.recreate_kd_tree()

            time.sleep(.25)

    def setAlpha(self):
        print "Setting alpha--TODO"

    def event(self, QEvent):
        if QEvent.type() == QtCore.QEvent.Leave:
            self.mouse_pos = None
            self.repaint()

        return QGLWidget.event(self, QEvent)

    def setOrtho(self, viewArray):
        # paint within the whole window
        gl.glViewport(0, 0, self.width, self.height)
        # set orthographic projection (2D only)
        gl.glLoadIdentity()

        self.prevView = [viewArray[0], viewArray[1], viewArray[2], viewArray[3]]
        gl.glOrtho(viewArray[0], viewArray[1], viewArray[2], viewArray[3], -100, 100)
        self.repaint()

    def scaleOrtho(self, delta):
        mouse_pos = self.tool_qb.get_scale_anchor()
        scale = 1 - delta

        orig_view_scale = self.tool_qb.get_orig_view_scale()
        # Normalizes the vector, scales it, then puts it back into world coordinates
        l = (orig_view_scale[0] - mouse_pos[0]) * scale + mouse_pos[0]
        r = (orig_view_scale[1] - mouse_pos[0]) * scale + mouse_pos[0]
        b = (orig_view_scale[2] - mouse_pos[1]) * scale + mouse_pos[1]
        t = (orig_view_scale[3] - mouse_pos[1]) * scale + mouse_pos[1]

        self.view.set_view((l, r, b, t))
        self.setOrtho((l, r, b, t))

    # flesh this out- want to have it dynamically resize
    def draw_axes_markings(self):
        gl.glLineWidth(2.5)
        self.qglColor(QtCore.Qt.black)
        left, bottom, z_ = glu.gluUnProject(0, 0, 0)
        right, top, z_ = glu.gluUnProject(self.width, self.height, 0)
        gl.glBegin(gl.GL_LINES)
        # Bottom
        gl.glVertex2f(left, bottom)
        gl.glVertex2f(right, bottom)
        # Right
        gl.glVertex2f(right, bottom)
        gl.glVertex2f(right, top)
        # Top
        gl.glVertex2f(left, top)
        gl.glVertex2f(right, top)
        # Left
        gl.glVertex2f(left, bottom)
        gl.glVertex2f(left, top)
        gl.glEnd()

        self.draw_axes_ticks(left, right, bottom, top, self.x_ticks, self.y_ticks)

    def draw_axes_ticks(self, left, right, bottom, top, num_ticks_x, num_ticks_y):
        tick_width = 5
        x_, y_, z_ = glu.gluUnProject(tick_width, tick_width, 0)
        dx = (right - left) / (num_ticks_x - 1)
        dy = (top - bottom) / (num_ticks_y - 1)

        gl.glLineWidth(1)
        gl.glBegin(gl.GL_LINES)
        # Draw number ticks in x direction
        for x in range(num_ticks_x):
            gl.glVertex3f(x * dx + left, bottom, 0)
            gl.glVertex3f(x * dx + left, y_, 0)
        for y in range(num_ticks_y):
            gl.glVertex3f(left, y * dy + bottom, 0)
            gl.glVertex3f(x_, y * dy + bottom, 0)
        gl.glEnd()

    def initializeGL(self):
        """
        Initialize OpenGL, VBOs, upload data on the GPU, etc.
        """
        # background color
        gl.glClearColor(1, 1, 1, 1)
        if self.texture_file is not None and path.isfile(self.texture_file):
            self.initTexture()
        else:
            print "texture_file not found: ", self.texture_file

        #print "Open GL Version: " + gl.glGetString(gl.GL_VERSION)
        #print "Open GLSL Version: " + gl.glGetString(gl.GL_SHADING_LANGUAGE_VERSION)

    def mouseMoveEvent(self, event):
        self.mouse_pos = event.pos()
        QGLWidget.mouseMoveEvent(self, event)

    def find_data_pos(self):
        """
        Looks at mouse position and calculates data position of data point closest to cursor
        Returns: (tree number, point number, distance from cursor, x-position in view, y-position in view
        """
        x_, y_, z_ = glu.gluUnProject(self.mouse_pos.x(), self.height - self.mouse_pos.y(), 0)

        x_ /= (self.scale_x * self.ratio)
        y_ /= self.scale_y

        d = 99999999999
        pt_num = -1
        tree_num = -1
        for i in range(0, len(self.kd_tree)):
            _d, _pt_num = self.kd_tree[i].query([x_, y_])
            if _d < d:
                tree_num = i
                pt_num = _pt_num
                d = _d
        if pt_num == -1 or tree_num == -1:
            raise KeyError("Unable to get information")
        focus_x, focus_y = self.kd_tree[tree_num].data[pt_num]
        return tree_num, pt_num, d, focus_x * self.scale_x * self.ratio, focus_y * self.scale_y

    def draw_kd_tree_point(self):
        if not self.kd_tree_active:
            return

        gl.glEnable(gl.GL_POINT_SMOOTH)

        tree_num, pt_num, distance, x, y = self.find_data_pos()

        self.data_sets[tree_num].getHighlightColor()

        gl.glPushMatrix()
        gl.glPointSize(10)
        gl.glBegin(gl.GL_POINTS)

        gl.glColor3f(0.7, 0, 0)
        positionThreshold = 6
        for time in self.data_sets[tree_num].getAllTimesForPosition(round(y,positionThreshold)):
            gl.glVertex2f(time, y)

        gl.glColor3f(1, 0, 0)
        gl.glVertex2f(x, y)

        gl.glEnd()
        gl.glPointSize(self.view.point_size())
        gl.glPopMatrix()
        gl.glDisable(gl.GL_POINT_SMOOTH)

    def drawDataPoints(self):
        gl.glEnable(gl.GL_BLEND)

        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glMatrixMode(gl.GL_MODELVIEW)
        for dSet in self.data_sets:
            # set blue color for subsequent drawing rendering calls
            dSet.getColor(self.alpha)
            gl.glPushMatrix()
            dSet.getTranslation()
            # bind the VBO
            vbo = dSet.getVBO()
            vbo.bind()
            # tell OpenGL that the VBO contains an array of vertices
            gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
            # these vertices contain 2 single precision coordinates
            gl.glVertexPointer(2, gl.GL_FLOAT, 0, vbo)
            # draw "count" points from the VBO
            gl.glDrawArrays(gl.GL_POINTS, 0, dSet.count)
            vbo.unbind()
            gl.glPopMatrix()

        gl.glDisable(gl.GL_BLEND)

    def drawHeightMap(self):
        view = self.view.orig_view
        gl.glPushMatrix()
        gl.glColor3f(1, 1, 1)

        # enable textures, bind to our texture
        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture)

        gl.glBegin(gl.GL_QUADS)
        gl.glTexCoord2f(0, 0)
        gl.glVertex2f(view[0], view[2])

        gl.glTexCoord2f(1, 0)
        gl.glVertex2f(view[1], view[2])

        gl.glTexCoord2f(1, 1)
        gl.glVertex2f(view[1], view[3])

        gl.glTexCoord2f(0, 1)
        gl.glVertex2f(view[0], view[3])
        gl.glEnd()

        gl.glDisable(gl.GL_TEXTURE_2D)

        gl.glPopMatrix()

    def paintGL(self):
        """
        Paint the scene.
        """
        # clear the buffer
        gl.glClear(gl.GL_COLOR_BUFFER_BIT)
        if self.parent.show_height_map and self.texture_file is not None:
            self.drawHeightMap()
        else:
            self.drawDataPoints()

        if self.mouse_pos is not None and not self.rubberband.isVisible():
            self.draw_kd_tree_point()

        if self.rubberband.isVisible():
            self.rubberband.restrictBoundaries(self.width, self.height)
            self.rubberband.draw()

        self.draw_axes_markings()

        gl.glFlush()

    def resizeGL(self, width, height):
        """
        Called upon window resizing: reinitialize the viewport.
        """
        # update the window size
        self.width, self.height = width, height
        self.x_ticks = int(self.width / 80)
        self.y_ticks = int(self.height / 14)
        if self.y_ticks > 6:
            self.y_ticks = int(self.y_ticks / 1.5)
        self.setOrtho(self.view.view())
        #print "Resizing"
        QGLWidget.resizeGL(self, width, height)

    def resetToOriginalView(self):
        print "Resetting to original view: " + str(self.view.orig_view)
        self.setOrtho(self.view.orig_view)
        self.view.set_view(self.view.orig_view)
        self.resetToOriginalKdTree()

    def resetToOriginalKdTree(self):
        with self.lock:
            self.kd_tree = self.orig_kd_tree
            self.ratio = float(self.height) / float(self.width)
            self.scale_x = float(self.view.width())
            self.scale_y = float(self.view.height())

    def closeEvent(self, QCloseEvent):
        #print "closeEvent called for " + self.title
        self.program_active = False

        QGLWidget.closeEvent(self, QCloseEvent)