def test_Vector_interface(): """Test various aspects of the Vector API.""" v = pg.Vector(-1, 2) # len assert len(v) == 3 # indexing assert v[0] == -1 assert v[2] == 0 with pytest.raises(IndexError): x = v[4] assert v[1] == 2 v[1] = 5 assert v[1] == 5 # iteration v2 = pg.Vector(*v) assert v2 == v assert abs(v).x() == 1 # angle v1 = pg.Vector(1, 0) v2 = pg.Vector(1, 1) assert abs(v1.angle(v2) - 45) < 0.001
def plot3d(self, dim = "z", point_size=1, cmap='Spectral_r', max_points=5e5, n_bin=8, plot_trees=False): """ Plots the three dimensional point cloud using a `Qt` backend. By default, if the point cloud exceeds 5e5 \ points, then it is downsampled using a uniform random distribution. This is for performance purposes. :param point_size: The size of the rendered points. :param dim: The dimension upon which to color (i.e. "z", "intensity", etc.) :param cmap: The matplotlib color map used to color the height distribution. :param max_points: The maximum number of points to render. """ from pyqtgraph.Qt import QtCore, QtGui import pyqtgraph as pg import pyqtgraph.opengl as gl # Randomly sample down if too large if dim == 'user_data' and plot_trees: dim = 'random_id' self._set_discrete_color(n_bin, self.data.points['user_data']) cmap = self._discrete_cmap(n_bin, base_cmap=cmap) if self.data.count > max_points: sample_mask = np.random.randint(self.data.count, size = int(max_points)) coordinates = np.stack([self.data.points.x, self.data.points.y, self.data.points.z], axis = 1)[sample_mask,:] color_dim = np.copy(self.data.points[dim].iloc[sample_mask].values) print("Too many points, down sampling for 3d plot performance.") else: coordinates = np.stack([self.data.points.x, self.data.points.y, self.data.points.z], axis = 1) color_dim = np.copy(self.data.points[dim].values) # If dim is user data (probably TREE ID or some such thing) then we want a discrete colormap if dim != 'random_id': color_dim = (color_dim - np.min(color_dim)) / (np.max(color_dim) - np.min(color_dim)) cmap = cm.get_cmap(cmap) colors = cmap(color_dim) else: colors = cmap(color_dim) # Start Qt app and widget pg.mkQApp() view = gl.GLViewWidget() # Create the points, change to opaque, set size to 1 points = gl.GLScatterPlotItem(pos = coordinates, color = colors) points.setGLOptions('opaque') points.setData(size = np.repeat(point_size, len(coordinates))) # Add points to the viewer view.addItem(points) # Center on the arithmetic mean of the point cloud and display center = np.mean(coordinates, axis = 0) view.opts['center'] = pg.Vector(center[0], center[1], center[2]) # Very ad-hoc view.opts['distance'] = (self.data.max[0] - self.data.min[0]) * 1.2 #return(view.opts) view.show()
def drawNewVehiclePosition(self, newPosition): """ Handles update of the plane in the window, NEVER CALLED directly. :param newPosition: new position as a list """ # print(newPosition) # we simply create a new set of vertices rawPoints = self.vehicleDrawInstance.getNewPoints(*newPosition) # print(rawPoints) newVertices = numpy.array([[y * metersToPixelRatio for y in x] for x in rawPoints]) # print(newVertices) self.vehicleMeshData.setVertexes( newVertices) # update our mesh with them self.openGLVehicle.setMeshData( meshdata=self.vehicleMeshData, smooth=False, computeNormals=False ) # and setMeshData automatically invokes a redraw self.lastPlanePos = pyqtgraph.Vector(newPosition[1], newPosition[0], -newPosition[2]) if self.trackPlane: self.openGLWindow.setCameraPosition(pos=self.lastPlanePos) if self.leavePlaneTrail: self.planeTrailPoints.append( [newPosition[1], newPosition[0], -newPosition[2]]) hmm = numpy.array(self.planeTrailPoints) tempColor = numpy.array([[1., 0., 0., 1]]) colors = numpy.tile(tempColor, (hmm.shape[0], 1)) self.planeTrailLine.setData(pos=numpy.array(self.planeTrailPoints), color=colors) return
def update(self): if(self.w.count >= len(self.cameras)): self.w.close() self.app.exit() return self.w.update() # get the camera cam = self.cameras[self.w.count] # set camera parameters self.w.opts["center"] = pg.Vector(cam["x"],cam["y"],cam["z"]) self.w.opts["distance"] = cam["distance"] self.w.opts["elevation"] = cam["elevation"] self.w.opts["azimuth"] = cam["azimuth"] self.w.update() # get image from window im = self.convertQImageToMat(self.w.readQImage()).astype(np.uint64) im = im[:,:,:3] # get only the first 3 channels im[:,:,2] *= 256*256 im[:,:,1] *= 256 im = im.sum(axis=2) im -= 1 #we added 1 to handle the background # save the matrix np.savez(os.path.join(self.dir_images,"views", self.filename+("_%04d" % self.w.count)), im) self.w.count+=1
def ManualButtonResponse(self): """ Sets camera to manual mode """ self.trackPlane = False self.__setCameraModeButtons() self.openGLWindow.setCameraPosition(pos=pyqtgraph.Vector(0, 0, 0)) return
def _default__widget(self, parent=None): """ Create a GLViewWidget and add plot, grid, and orientation axes. """ w = MyGLViewWidget(parent) self._grid = g = gl.GLGridItem() w.addItem(g) self._orientation_axes = ax = gl.GLAxisItem(size=pg.Vector(5, 5, 5)) w.addItem(ax) w.addItem(self.plot._plot) w.sigUpdate.connect(self._update_model) for attr in ['azimuth', 'distance', 'fov', 'center', 'elevation']: w.opts[attr] = getattr(self, attr) return w
def test_Vector_init(): """Test construction of Vector objects from a variety of source types.""" # separate values without z v = pg.Vector(0, 1) assert v.z() == 0 v = pg.Vector(0.0, 1.0) assert v.z() == 0 # separate values with 3 args v = pg.Vector(0, 1, 2) assert v.x() == 0 assert v.y() == 1 assert v.z() == 2 v = pg.Vector(0.0, 1.0, 2.0) assert v.x() == 0 assert v.y() == 1 assert v.z() == 2 # all in a list v = pg.Vector([0, 1]) assert v.z() == 0 v = pg.Vector([0, 1, 2]) # QSizeF v = pg.Vector(QtCore.QSizeF(1, 2)) assert v.x() == 1 assert v.z() == 0 # QPoint v = pg.Vector(QtCore.QPoint(0, 1)) assert v.z() == 0 v = pg.Vector(QtCore.QPointF(0, 1)) assert v.z() == 0 # QVector3D qv = QtGui.QVector3D(1, 2, 3) v = pg.Vector(qv) assert v == qv with pytest.raises(Exception): v = pg.Vector(1, 2, 3, 4)
def __init__(self, parent=None): super(brainView, self).__init__(parent) HVC_L_file = resource_path("zfbrain/data/HVC_L.surf") HVC_R_file = resource_path("zfbrain/data/HVC_R.surf") RA_L_file = resource_path("zfbrain/data/RA_L.surf") RA_R_file = resource_path("zfbrain/data/RA_R.surf") X_L_file = resource_path("zfbrain/data/AreaX_L.surf") X_R_file = resource_path("zfbrain/data/AreaX_R.surf") brain_L_file = resource_path("zfbrain/data/whole_brain_L.surf") brain_R_file = resource_path("zfbrain/data/whole_brain_R.surf") verts_HVC_L, faces_HVC_L = sp.read_surface(HVC_L_file) verts_HVC_R, faces_HVC_R = sp.read_surface(HVC_R_file) verts_RA_L, faces_RA_L = sp.read_surface(RA_L_file) verts_RA_R, faces_RA_R = sp.read_surface(RA_R_file) verts_X_L, faces_X_L = sp.read_surface(X_L_file) verts_X_R, faces_X_R = sp.read_surface(X_R_file) verts_brain_L, faces_brain_L = sp.read_surface(brain_L_file) verts_brain_R, faces_brain_R = sp.read_surface(brain_R_file) self.hvc_L = gl.GLMeshItem(vertexes=verts_HVC_L, faces=faces_HVC_L, color=(1, 0, 0, 0.2), smooth=True, drawEdges=False, shader='balloon', glOptions='additive') self.hvc_R = gl.GLMeshItem(vertexes=verts_HVC_R, faces=faces_HVC_R, color=(0.5, 0.5, 0, 0.2), smooth=True, drawEdges=False, shader='balloon', glOptions='additive') self.ra_L = gl.GLMeshItem(vertexes=verts_RA_L, faces=faces_RA_L, color=(0, 1, 0, 0.2), smooth=True, drawEdges=False, shader='balloon', glOptions='additive') self.ra_R = gl.GLMeshItem(vertexes=verts_RA_R, faces=faces_RA_R, color=(0.5, 1, 0.5, 0.2), smooth=True, drawEdges=False, shader='balloon', glOptions='additive') self.areaX_L = gl.GLMeshItem(vertexes=verts_X_L, faces=faces_X_L, color=(0, 0.5, 0.5, 0.2), smooth=True, drawEdges=False, shader='balloon', glOptions='additive') self.areaX_R = gl.GLMeshItem(vertexes=verts_X_R, faces=faces_X_R, color=(1, 0.5, 1, 0.2), smooth=True, drawEdges=False, shader='balloon', glOptions='additive') self.outer_L = gl.GLMeshItem(vertexes=verts_brain_L, faces=faces_brain_L, color=(200 / 255, 100 / 255, 100 / 255, 0.5), drawEdges=False, drawFaces=True, shader='shaded', glOptions='opaque') self.outer_R = gl.GLMeshItem(vertexes=verts_brain_R, faces=faces_brain_R, color=(200 / 255, 100 / 255, 100 / 255, 0.5), drawEdges=False, drawFaces=True, shader='shaded', glOptions='opaque') self.addItem(self.outer_L) self.addItem(self.outer_R) self.addItem(self.hvc_L) self.addItem(self.hvc_R) self.addItem(self.ra_L) self.addItem(self.ra_R) self.addItem(self.areaX_L) self.addItem(self.areaX_R) self.setBackgroundColor(50, 50, 50) # choose center of whole-brain x_center = np.average( np.concatenate((verts_brain_L[:, 0], verts_brain_R[:, 0]))) y_center = np.average( np.concatenate((verts_brain_L[:, 1], verts_brain_R[:, 1]))) z_center = np.average( np.concatenate((verts_brain_L[:, 2], verts_brain_R[:, 2]))) # set camera settings # sets center of rotation for field new_center = np.array([x_center, y_center, z_center]) self.opts['center'] = pg.Vector(new_center) self.setCameraPosition(distance=2400, elevation=20, azimuth=50)
def getTranslation(self): return pg.Vector(self._state['pos'])
def getRotation(self): """Return (angle, axis) of rotation""" return self._state['angle'], pg.Vector(self._state['axis'])
def getScale(self): return pg.Vector(self._state['scale'])
def track3D(state): ''' 描绘目标状态的3d轨迹 :param state: 【np.array】目标的状态 :return: ''' app = QtGui.QApplication([]) w = gl.GLViewWidget() # w.setWindowTitle('3d trajectory') w.resize(600, 500) # instance of Custom3DAxis axis = Custom3DAxis(w, color=(0.6, 0.6, 0.2, .6)) w.addItem(axis) w.opts['distance'] = 75 w.opts['center'] = pg.Vector(0, 0, 0) # add xy grid gx = gl.GLGridItem() gx.setSize(x=40, y=40, z=10) gx.setSpacing(x=5, y=5) w.addItem(gx) # trajectory line pos0 = np.array([[0, 0, 0]]) pos, q = np.array(state[:3]), state[3:7] uAxis, angle = q2ua(q) track0 = np.concatenate((pos0, pos.reshape(1, 3))) plt = gl.GLLinePlotItem(pos=track0, width=2, color=(1, 0, 0, 0.6)) w.addItem(plt) # orientation arrow sphereData = gl.MeshData.sphere(rows=20, cols=20, radius=0.6) sphereMesh = gl.GLMeshItem(meshdata=sphereData, smooth=True, shader='shaded', glOptions='opaque') w.addItem(sphereMesh) ArrowData = gl.MeshData.cylinder(rows=20, cols=20, radius=[0.5, 0], length=1.5) ArrowMesh = gl.GLMeshItem(meshdata=ArrowData, smooth=True, color=(1, 0, 0, 0.6), shader='balloon', glOptions='opaque') ArrowMesh.rotate(angle, uAxis[0], uAxis[1], uAxis[2]) w.addItem(ArrowMesh) w.setWindowTitle('position={}cm'.format(np.round(pos * 100, 1))) w.show() i = 1 pts = pos.reshape(1, 3) def update(): '''update position and orientation''' nonlocal i, pts, state pos, q = np.array(state[:3]) * 100, state[3:7] uAxis, angle = q2ua(q) pt = (pos).reshape(1, 3) if pts.size < 150: pts = np.concatenate((pts, pt)) else: pts = np.concatenate((pts[-50:, :], pt)) plt.setData(pos=pts) ArrowMesh.resetTransform() sphereMesh.resetTransform() ArrowMesh.rotate(angle, uAxis[0], uAxis[1], uAxis[2]) ArrowMesh.translate(*pos) sphereMesh.translate(*pos) w.setWindowTitle('position={}cm'.format(np.round(pos, 1))) i += 1 timer = QtCore.QTimer() timer.timeout.connect(update) timer.start(50) if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_()
def __init__(self, parent=None): """ sets up the full window with the plane along with a row of camera controls """ super().__init__(parent) self.usedLayout = QtWidgets.QVBoxLayout() self.setLayout(self.usedLayout) self.trackPlane = True self.leavePlaneTrail = True self.lastPlanePos = pyqtgraph.Vector(0, 0, 0) # we will always have the openGLBase Widget self.openGLWindow = pyqtgraph.opengl.GLViewWidget() self.usedLayout.addWidget(self.openGLWindow) # a random grid, will likely be changed afterwards self.openGLWindow.setGeometry(0, 0, 1000, 1000) self.grid = pyqtgraph.opengl.GLGridItem() self.grid.scale(200, 200, 200) self.grid.setSize(2000, 2000, 2000) self.openGLWindow.addItem(self.grid) # and an arbitrary camera starting position self.openGLWindow.setCameraPosition(distance=defaultZoom, elevation=defaultElevation, azimuth=defaultAzimuth) # a copy of the vehicle, we assume we will always want a vehicle self.vehicleDrawInstance = VehicleGeometry.VehicleGeometry() # we need to grab the vertices for the vehicle each update rawPoints = [[ y * metersToPixelRatio for y in x ] for x in self.vehicleDrawInstance.getNewPoints(0, 0, 0, 0, 0, 0)] newVertices = numpy.array(rawPoints) # faces and colors only need to be done once newFaces = numpy.array(self.vehicleDrawInstance.faces) newColors = numpy.array(self.vehicleDrawInstance.colors) # we convert the vertices to meshdata which allows us not to have to translate points every time self.vehicleMeshData = pyqtgraph.opengl.MeshData(vertexes=newVertices, faces=newFaces, faceColors=newColors) # and we create the meshItem, we do not smooth to make the triangles be clean colors self.openGLVehicle = pyqtgraph.opengl.GLMeshItem( meshdata=self.vehicleMeshData, drawEdges=True, smooth=False, computeNormals=False) # always add the vehicle to the display self.openGLWindow.addItem(self.openGLVehicle) # and add an axis self.Axis = pyqtgraph.opengl.GLAxisItem(glOptions='additive') self.Axis.setSize(2000, 2000, 2000) self.openGLWindow.addItem(self.Axis) self.updateVehiclePositionSignal.connect(self.drawNewVehiclePosition) # we are going to add a line for tracking the plane here, if not on it does nothing self.planeTrailLine = pyqtgraph.opengl.GLLinePlotItem() # self.planeTrailLine.setData(color=PyQt5.QtGui.QColor("red"), width=2) self.planeTrailLine.setData(color=(1, 0, 0, 1), width=1) self.openGLWindow.addItem(self.planeTrailLine) self.planeTrailLine.mode = 'line_strip' self.planeTrailPoints = list() self.aribtraryLines = list() # # and another line for supposed paths and the like # self.arbitraryLine = pyqtgraph.opengl.GLLinePlotItem() # # self.arbitraryLine.setData(color=PyQt5.QtGui.QColor("blue"), width=1) # self.arbitraryLine.setData(color=(0, 0, 1, .5), width=1) # self.arbitraryLine.mode = 'line_strip' # self.openGLWindow.addItem(self.arbitraryLine) # self.arbitraryLinePoints = list() # self.setAribtraryLine(testLine) # self.setAribtraryLine([[0,0,0],[10,10, 0]]) # self.clearAribtraryLine() # we add another hbox for camera controls cameraControlBox = QtWidgets.QHBoxLayout() self.usedLayout.addLayout(cameraControlBox) zoomInButton = QtWidgets.QPushButton("Zoom In") zoomInButton.clicked.connect(self.ZoomIn) zoomOutButton = QtWidgets.QPushButton("Zoom Out") zoomOutButton.clicked.connect(self.ZoomOut) cameraControlBox.addWidget(zoomInButton) cameraControlBox.addWidget(zoomOutButton) self.trackButton = QtWidgets.QPushButton("Track") self.trackButton.clicked.connect(self.TrackButtonResponse) cameraControlBox.addWidget(self.trackButton) self.manualButton = QtWidgets.QPushButton("Manual") self.manualButton.clicked.connect(self.ManualButtonResponse) cameraControlBox.addWidget(self.manualButton) self.resetCameraButton = QtWidgets.QPushButton("Reset") self.resetCameraButton.clicked.connect(self.resetCameraView) cameraControlBox.addWidget(self.resetCameraButton) self.__setCameraModeButtons() # self.setAribtraryLine(testLine) # self.drawLine(testLine) # print(self.buildRandomPoints()) # self.addAribtraryLine(self.buildRandomPoints()) # self.addAribtraryLine(self.buildRandomPoints()) # hmm = self.addAribtraryLine(self.buildRandomPoints()) # self.removeAribtraryLine(hmm) # self.removeAllAribtraryLines() return
class Scatter3DScene(Atom): """ A Scatter3D Scene Manager. Maintains a scatter plot and its scene. """ __slots__ = '__weakref__' #: Scatter3D Point manager plot = Typed(Scatter3DPlot, ()) #: Camera FOV center center = Value(pg.Vector(0, 0, 0)) #: Distance of camera from center distance = Float(100.) #: Horizontal field of view in degrees fov = Float(60.) #: Camera's angle of elevation in degrees. elevation = Coerced(float, (30.,)) #: Camera's azimuthal angle in degrees. azimuth = Float(45.) #: MyGLViewWidget instance. _widget = Typed(MyGLViewWidget, ()) #: GLGridItem instance _grid = Value() #: GLAxisItem instance. _orientation_axes = Value() #: Cyclic notification guard flags. _guard = Int(0) def _default__widget(self, parent=None): """ Create a GLViewWidget and add plot, grid, and orientation axes. """ w = MyGLViewWidget(parent) self._grid = g = gl.GLGridItem() w.addItem(g) self._orientation_axes = ax = gl.GLAxisItem(size=pg.Vector(5, 5, 5)) w.addItem(ax) w.addItem(self.plot._plot) w.sigUpdate.connect(self._update_model) for attr in ['azimuth', 'distance', 'fov', 'center', 'elevation']: w.opts[attr] = getattr(self, attr) return w def show(self, title=''): """ Show the view in a graphics window. """ if not title: title = 'pyqtgraph Atom example: GLScatterPlotItem' app = pg.mkQApp() self._widget.show() app.exec_() def _observe_plot(self, change): """ Synchronize plot changing with the scene. """ if change['type'] == 'create': return self._guard |= PLOT_CHANGE_FLAG self._widget.removeItem(change['oldvalue']._plot) self._widget.addItem(change['value']._plot) self._guard &= ~PLOT_CHANGE_FLAG @observe('azimuth', 'distance', 'fov', 'center', 'elevation') def _update_view(self, change): """ Synchronize model attributes to the view. """ if self._guard & (VIEW_SYNC_FLAG) or change['type'] == 'create': return self._widget.opts[change['name']] = change['value'] self._widget.update() def _update_model(self): """ Synchronize view attributes to the model. """ if self._guard & PLOT_CHANGE_FLAG: return self._guard &= VIEW_SYNC_FLAG for (key, value) in self._widget.opts.items(): setattr(self, key, value) self._guard &= ~VIEW_SYNC_FLAG