def testExpressionContext(self): req = QgsFeatureRequest() self.assertEqual(req.expressionContext().scopeCount(), 0) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('a', 6) context.appendScope(scope) req.setExpressionContext(context) self.assertEqual(req.expressionContext().scopeCount(), 1) self.assertEqual(req.expressionContext().variable('a'), 6)
def testAssignment(self): req = QgsFeatureRequest().setFilterFids([8, 9]).setFilterRect( QgsRectangle(1, 2, 3, 4)).setInvalidGeometryCheck( QgsFeatureRequest.GeometrySkipInvalid).setLimit(6).setFlags( QgsFeatureRequest.ExactIntersect).setSubsetOfAttributes( [1, 4]).setTimeout(6).setRequestMayBeNested(True) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('a', 6) context.appendScope(scope) req.setExpressionContext(context) method = QgsSimplifyMethod() method.setMethodType(QgsSimplifyMethod.PreserveTopology) req.setSimplifyMethod(method) context = QgsCoordinateTransformContext() req.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857'), context) req2 = QgsFeatureRequest(req) self.assertEqual(req2.limit(), 6) self.assertCountEqual(req2.filterFids(), [8, 9]) self.assertEqual(req2.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertEqual(req2.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req2.invalidGeometryCheck(), QgsFeatureRequest.GeometrySkipInvalid) self.assertEqual(req2.expressionContext().scopeCount(), 1) self.assertEqual(req2.expressionContext().variable('a'), 6) self.assertEqual( req2.flags(), QgsFeatureRequest.ExactIntersect | QgsFeatureRequest.SubsetOfAttributes) self.assertEqual(req2.subsetOfAttributes(), [1, 4]) self.assertEqual(req2.simplifyMethod().methodType(), QgsSimplifyMethod.PreserveTopology) self.assertEqual(req2.destinationCrs().authid(), 'EPSG:3857') self.assertEqual(req2.timeout(), 6) self.assertTrue(req2.requestMayBeNested()) # copy distance within request req = QgsFeatureRequest().setDistanceWithin( QgsGeometry.fromWkt('LineString( 0 0, 10 0, 11 2)'), 1.2) req2 = QgsFeatureRequest(req) self.assertEqual(req2.spatialFilterType(), Qgis.SpatialFilterType.DistanceWithin) self.assertEqual(req2.referenceGeometry().asWkt(), 'LineString (0 0, 10 0, 11 2)') self.assertEqual(req2.distanceWithin(), 1.2) self.assertEqual(req2.filterRect(), QgsRectangle(-1.2, -1.2, 12.2, 3.2))
def doStart(self): # first see if we can pull data from the predictions layer startTime = self.datetime endTime = self.datetime.addDays(1) featureRequest = QgsFeatureRequest() stationPt = QgsPointXY(self.stationFeature.geometry().vertexAt(0)) searchRect = QgsRectangle(stationPt, stationPt) searchRect.grow( 0.01 / 60 ) # in the neighborhood of .01 nm as 1/60 = 1 arc minute in this proj. featureRequest.setFilterRect(searchRect) # Create a time based query ctx = featureRequest.expressionContext() scope = QgsExpressionContextScope() scope.setVariable('startTime', startTime) scope.setVariable('endTime', endTime) scope.setVariable('station', self.stationFeature['station']) ctx.appendScope(scope) featureRequest.setFilterExpression( "station = @station and time >= @startTime and time < @endTime") featureRequest.addOrderBy('time') savedFeatureIterator = self.manager.predictionsLayer.getFeatures( featureRequest) savedFeatures = list(savedFeatureIterator) if len(savedFeatures) > 0: # We have some features, so go ahead and stash them in the layer and resolve this promise print('{}: retrieved {} features from layer'.format( self.stationFeature['station'], len(savedFeatures))) self.predictions = savedFeatures self.resolve() else: # The layer didn't have what we wanted, so we must request the data we need. # At this point, the situation falls into several possible cases. # Case 1: A Harmonic station with known flood/ebb directions. Here # we need two requests which can simply be combined and sorted: # 1a: EventType, i.e. slack, flood and ebb # 1b: SpeedDirType, as velocity can be calculated by projecting along flood/ebb # # Case 2: A Harmonic station with unknown flood and/or ebb. # We actually need to combine 3 requests: # 2a: EventType # 2b: SpeedDirType, which only provides vector magnitude/angle # 2c: VelocityMajorType, which only provides current velocity (but for same times as 2b) # Here we set up requests for cases 1 and 2 if self.stationFeature['type'] == 'H': self.speedDirRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.SpeedDirectionType) self.addDependency(self.speedDirRequest) self.eventRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.EventType) self.addDependency(self.eventRequest) floodDir = self.stationFeature['meanFloodDir'] ebbDir = self.stationFeature['meanEbbDir'] if floodDir == NULL or ebbDir == NULL: self.velocityRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.VelocityMajorType) self.addDependency(self.velocityRequest) else: self.velocityRequest = None # Case 3: A Subordinate station which only knows its events. Here we need the following: # 3a: PredictionEventPromises for this station in a 3-day window surrounding the date of interest # 3b: PredictionDataPromises for the reference station in the same 3-day window. else: self.eventPromises = [] self.refPromises = [] refStation = self.manager.getStation( self.stationFeature['refStation']) if refStation is None: print("Could not find ref station {} for {}".format( self.stationFeature['refStation'], self.stationFeature['station'])) else: for dayOffset in [-1, 0, 1]: windowDate = self.localDate.addDays(dayOffset) dataPromise = self.manager.getDataPromise( refStation, windowDate) self.refPromises.append(dataPromise) self.addDependency(dataPromise) eventPromise = self.manager.getEventPromise( self.stationFeature, windowDate) self.eventPromises.append(eventPromise) self.addDependency(eventPromise)