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