def test_creategraph(self): # | # --|-- # |__ line_coords = array.array('d', [0, 0, 2, 0, 1, 1, 1, -1, 2, -1]) line_indices = array.array('I', [0, 1, 2, 3, 3, 4]) unlinks = array.array('d', [1, 0]) points = array.array('d', [-1, 0]) graph_handle = pstalgo.CreateGraph(line_coords, line_indices, unlinks, points, None) self.assertIsNotNone(graph_handle) graph_info = pstalgo.GetGraphInfo(graph_handle) self.assertEqual(graph_info.m_LineCount, 3) self.assertEqual(graph_info.m_CrossingCount, 1) # One of the 2 crossings was unlinked self.assertEqual(graph_info.m_PointCount, 1) lengths = array.array('f', [0]) * 3 pstalgo.GetGraphLineLengths(graph_handle, lengths) IsArrayRoughlyEqual(lengths, [2, 2, 1]) crossings = array.array('d', [0]) * 2 pstalgo.GetGraphCrossingCoords(graph_handle, crossings) IsArrayRoughlyEqual(crossings, [1, -1]) pstalgo.FreeGraph(graph_handle)
def test_NInt_single(self): line_count = 1 line_length = 3 graph = CreateChainGraph(line_count, line_length) tests = [ (Radii(), [-1], [1], [0]), ] self.runTests(graph, tests, line_count) pstalgo.FreeGraph(graph)
def test_arch_region_origin(self): count = 5 length = 3 g = CreateRegionOriginChainGraph(count, length) attraction_points = array.array('d', [-1, 0, length*count+1, 0]) # One point left of and another right of graph attraction_values = array.array('f', [4, 3]) collect_func = pstalgo.AttractionCollectionFunc.AVARAGE distr_func = pstalgo.AttractionDistributionFunc.DIVIDE # Redundant here self.doTest(g, count, OriginType.POINT_GROUPS, DistanceType.UNDEFINED, Radii(), AttractionWeightFunction.CONSTANT, 0, attraction_points, None, 0, attraction_values, distr_func, collect_func, [4+3]*count) pstalgo.FreeGraph(g)
def test_five_chain(self): graph = self.create_chain_graph(5) betweenness = array.array('f', [0])*5 # Fastest way of allocating arrays of array.array-type pstalgo.SegmentBetweenness( graph_handle = graph, distance_type = DistanceType.STEPS, radius = pstalgo.Radii(steps=4), out_betweenness = betweenness) pstalgo.FreeGraph(graph) self.assertEqual(betweenness, array.array('f', [0, 3, 4, 3, 0]))
def test_split2(self): graph = self.create_split_graph2() betweenness = array.array('f', [0])*6 # Fastest way of allocating arrays of array.array-type pstalgo.SegmentBetweenness( graph_handle = graph, distance_type = DistanceType.ANGULAR, radius = pstalgo.Radii(angular=45), out_betweenness = betweenness) pstalgo.FreeGraph(graph) self.assertEqual(betweenness, array.array('f', [0, 1, 1, 2, 2, 0]))
def test_odb_closest(self): g = CreateTestGraph() self.doTest( graph_handle=g, origin_points=array.array('d', [-0.5, 0]), origin_weights=None, destination_weights=None, destination_mode=ODBDestinationMode.CLOSEST_DESTINATION_ONLY, distance_type=DistanceType.WALKING, radius=Radii(), scores_check=[1, 1, 0]) pstalgo.FreeGraph(g)
def test_odb_dest_weights(self): g = CreateTestGraph() self.doTest( graph_handle=g, origin_points=array.array('d', [-0.5, 0]), origin_weights=array.array('f', [10]), destination_weights=array.array('f', [4, 1]), destination_mode=ODBDestinationMode.ALL_REACHABLE_DESTINATIONS, distance_type=DistanceType.WALKING, radius=Radii(), scores_check=[10, 10, 2]) pstalgo.FreeGraph(g)
def test_arch_region_attr(self): count = 5 length = 3 g = CreateRegionOriginChainGraph(count, length) attraction_points = array.array('d', [-2, 0, -1, 0, -1, -1, -2, -1, length*count+1, 0, length*count+2, 0, length*count+2, -1, length*count+1, -1]) # One region left of and another right of graph points_per_attraction_polygon = array.array('I', [4, 4]) attraction_polygon_point_interval = 0.5 attraction_values = array.array('f', [4, 3]) collect_func = pstalgo.AttractionCollectionFunc.AVARAGE distr_func = pstalgo.AttractionDistributionFunc.DIVIDE self.doTest(g, count, OriginType.POINT_GROUPS, DistanceType.UNDEFINED, Radii(), AttractionWeightFunction.CONSTANT, 0, attraction_points, points_per_attraction_polygon, attraction_polygon_point_interval, attraction_values, distr_func, collect_func, [4+3]*count) distr_func = pstalgo.AttractionDistributionFunc.COPY self.doTest(g, count, OriginType.POINT_GROUPS, DistanceType.UNDEFINED, Radii(), AttractionWeightFunction.CONSTANT, 0, attraction_points, points_per_attraction_polygon, attraction_polygon_point_interval, attraction_values, distr_func, collect_func, [4+3]*count) pstalgo.FreeGraph(g)
def test_arch_point_origin(self): count = 5 length = 3 g = CreatePointOriginChainGraph(count, length) attraction_points = array.array('d', [-1, 0, length*count+1, 0]) # One point left of and another right of graph attraction_values = array.array('f', [4, 3]) collect_func = pstalgo.AttractionCollectionFunc.AVARAGE # Redundant here distr_func = pstalgo.AttractionDistributionFunc.DIVIDE # Redundant here self.doTest(g, count, OriginType.POINTS, DistanceType.UNDEFINED, Radii(), AttractionWeightFunction.CONSTANT, 0, attraction_points, None, 0, attraction_values, distr_func, collect_func, [4+3]*count) self.doTest(g, count, OriginType.LINES, DistanceType.UNDEFINED, Radii(), AttractionWeightFunction.CONSTANT, 0, attraction_points, None, 0, attraction_values, distr_func, collect_func, [4+3]*count) self.doTest(g, count, OriginType.JUNCTIONS, DistanceType.UNDEFINED, Radii(), AttractionWeightFunction.CONSTANT, 0, attraction_points, None, 0, attraction_values, distr_func, collect_func, [4+3]*(count-1)) self.doTest(g, count, OriginType.POINTS, DistanceType.UNDEFINED, Radii(steps=2), AttractionWeightFunction.CONSTANT, 0, attraction_points, None, 0, attraction_values, distr_func, collect_func, [4,4,4+3,3,3]) self.doTest(g, count, OriginType.POINTS, DistanceType.STEPS, Radii(steps=2), AttractionWeightFunction.DIVIDE, 1, attraction_points, None, 0, attraction_values, distr_func, collect_func, [4,2,4.0/3+1,1.5,3]) pstalgo.FreeGraph(g)
def test_reach_square(self): line_count = 4 line_length = 3 graph = CreateSquareGraph(line_length) tests = [ (Radii(), [4, 4, 4, 4], [line_length*line_count]*line_count, [line_length*line_length]*line_count), (Radii(angular=80), [1, 1, 1, 1], [line_length*1]*line_count, [0]*line_count), (Radii(angular=100), [3, 3, 3, 3], [line_length*3]*line_count, [line_length*line_length]*line_count), (Radii(angular=190), [4, 4, 4, 4], [line_length*line_count]*line_count, [line_length*line_length]*line_count), ] self.runTests(graph, tests, line_count) pstalgo.FreeGraph(graph)
def test_NInt_chain(self): line_count = 5 line_length = 3 graph = CreateChainGraph(line_count, line_length) tests = [ (Radii(), [0.352, 0.704, 1.056, 0.704, 0.352], [line_count]*line_count, [10, 7, 6, 7, 10]), (Radii(straight=0), None, [1]*line_count, None), (Radii(straight=1), None, [1]*line_count, None), (Radii(straight=line_length), None, [2, 3, 3, 3, 2], None), (Radii(walking=0), None, [1]*line_count, None), (Radii(walking=1), None, [1]*line_count, None), (Radii(walking=3), None, [2, 3, 3, 3, 2], None), (Radii(steps=0), None, [1]*line_count, None), (Radii(steps=1), None, [2, 3, 3, 3, 2], None), (Radii(steps=2), None, [3, 4, 5, 4, 3], None), (Radii(angular=1), None, [line_count]*line_count, None), ] self.runTests(graph, tests, line_count) pstalgo.FreeGraph(graph)
def test_odb_radius(self): g = CreateTestGraph() self.doTest( graph_handle=g, origin_points=array.array('d', [-0.5, 0]), origin_weights=None, destination_weights=None, destination_mode=ODBDestinationMode.ALL_REACHABLE_DESTINATIONS, distance_type=DistanceType.WALKING, radius=Radii(walking=3.9), scores_check=[1, 1, 0]) self.doTest( graph_handle=g, origin_points=array.array('d', [-0.5, 0]), origin_weights=None, destination_weights=None, destination_mode=ODBDestinationMode.ALL_REACHABLE_DESTINATIONS, distance_type=DistanceType.WALKING, radius=Radii(walking=4.1), scores_check=[1, 1, .5]) pstalgo.FreeGraph(g)
def test_reach_chain(self): line_count = 3 line_length = 3 graph = CreateChainGraph(line_count, line_length) tests = [ (Radii(), [3, 3, 3], [9, 9, 9], [0, 0, 0]), (Radii(straight=0), [1, 1, 1], [3, 3, 3], [0, 0, 0]), (Radii(straight=1), [1, 1, 1], [3, 3, 3], [math.pi]*3), (Radii(straight=3), [2, 3, 2], [6, 9, 6], [3*3*math.pi]*3), (Radii(walking=0), [1, 1, 1], [3, 3, 3], [0, 0, 0]), (Radii(walking=1), [1, 1, 1], [3, 3, 3], [0, 0, 0]), (Radii(walking=3), [2, 3, 2], [6, 9, 6], [0, 0, 0]), (Radii(steps=0), [1, 1, 1], [3, 3, 3], [0, 0, 0]), (Radii(steps=1), [2, 3, 2], [6, 9, 6], [0, 0, 0]), (Radii(steps=2), [3, 3, 3], [9, 9, 9], [0, 0, 0]), (Radii(angular=1), [3, 3, 3], [9, 9, 9], [0, 0, 0]), ] self.runTests(graph, tests, line_count) pstalgo.FreeGraph(graph)
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load Vector = pstalgo.Vector props = self._props model = self._model radii_list = RadiiFromSettings(pstalgo, self._props).split() # Distance modes distance_modes = DistanceTypesFromSettings(pstalgo, props) def GenerateColumnName(attr_name, distance_mode, radii, norm): return GenColName(ColName.ATTRACTION_BETWEENNESS, weight=attr_name, pst_distance_type=distance_mode, radii=radii, normalization=norm) # Attraction columns (None = use value 1 for every attraction) attraction_columns = props['dest_data'] if props[ 'dest_data_enabled'] else [None] # Number of analyses analysis_count = len(attraction_columns) * len(radii_list) * len( distance_modes) # Tasks class Tasks(object): READ_ATTRACTIONS = 1 BUILD_GRAPH = 2 ANALYSIS = 3 WRITE_RESULTS = 4 progress = MultiTaskProgressDelegate(delegate) progress.addTask(Tasks.READ_ATTRACTIONS, 1, None) progress.addTask(Tasks.BUILD_GRAPH, 1, None) progress.addTask(Tasks.ANALYSIS, 10 * analysis_count, None) initial_alloc_state = stack_allocator.state() graph = None try: # Attraction points progress.setCurrentTask(Tasks.READ_ATTRACTIONS) (attr_table, attr_rows, attr_points, attr_points_per_polygon) = ReadAttractionPoints( model, pstalgo, stack_allocator, props, progress) # Graph progress.setCurrentTask(Tasks.BUILD_GRAPH) (graph, line_rows, _) = BuildAxialGraph( self._model, pstalgo, stack_allocator, self._props['in_network'], self._props['in_unlinks'] if self._props['in_unlinks_enabled'] else None, None, progress) line_count = line_rows.size() # Allocate output arrays scores = Vector(ctypes.c_float, line_count, stack_allocator, line_count) scores_std = Vector(ctypes.c_float, line_count, stack_allocator, line_count) if props['norm_standard'] else None # Analyses attr_values = None progress.setCurrentTask(Tasks.ANALYSIS) analysis_progress = TaskSplitProgressDelegate( analysis_count, "Performing analysis", progress) for attr_col in attraction_columns: # Attraction values if attr_col is not None: if attr_values is None: attr_values = Vector(ctypes.c_float, attr_rows.size(), stack_allocator) attr_values.clear() for value in AttractionValueGen(model, attr_table, attr_rows, [attr_col], progress): attr_values.append(value) attr_title = GenerateAttractionDataName( props['in_destinations'], attr_col, props['dest_name']) for radii in radii_list: for distance_mode in distance_modes: # Analysis sub progress analysis_sub_progress = MultiTaskProgressDelegate( analysis_progress) analysis_sub_progress.addTask(Tasks.ANALYSIS, 1, "Calculating") analysis_sub_progress.addTask(Tasks.WRITE_RESULTS, 0, "Writing line results") # Analysis analysis_sub_progress.setCurrentTask(Tasks.ANALYSIS) pstalgo.SegmentBetweenness( graph_handle=graph, distance_type=distance_mode, radius=radii, weights=None if attr_col is None else attr_values, attraction_points=attr_points, progress_callback=pstalgo. CreateAnalysisDelegateCallbackWrapper( analysis_sub_progress), out_betweenness=scores) # Write analysis_sub_progress.setCurrentTask( Tasks.WRITE_RESULTS) columns = [] if props['norm_none']: columns.append( (GenerateColumnName(attr_title, distance_mode, radii, ColName.NORM_NONE), 'float', scores.values())) if props['norm_standard']: pstalgo.StandardNormalize(scores, scores.size(), scores_std) columns.append( (GenerateColumnName(attr_title, distance_mode, radii, ColName.NORM_STANDARD), 'float', scores_std.values())) self._model.writeColumns(self._props['in_network'], line_rows, columns, analysis_sub_progress) # Progress analysis_progress.nextTask() finally: stack_allocator.restore(initial_alloc_state) if graph: pstalgo.FreeGraph(graph) delegate.setStatus("Attraction Betweenness done") delegate.setProgress(1)
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load Vector = pstalgo.Vector props = self._props model = self._model # Radius radii = RadiiFromSettings(pstalgo, self._props) # Origin type origin_type = OriginTypeFromProps(pstalgo, props) # Distance types distance_types = DistanceTypesFromSettings(pstalgo, props) # Attraction columns (None = use value 1 for every attraction) attraction_columns = props['dest_data'] if props[ 'dest_data_enabled'] else [None] # Number of analyses analysis_count = len(attraction_columns) * len(distance_types) def GenerateColumnName(dest_name, distance_type, radii): return GenColName(ColName.ATTRACTION_DISTANCE, weight=dest_name, pst_distance_type=distance_type, radii=radii) # Tasks class Tasks(object): READ_ATTRACTIONS = 1 BUILD_GRAPH = 2 ANALYSIS = 3 WRITE_RESULTS = 4 progress = MultiTaskProgressDelegate(delegate) progress.addTask(Tasks.READ_ATTRACTIONS, 1, None) progress.addTask(Tasks.BUILD_GRAPH, 1, None) progress.addTask(Tasks.ANALYSIS, 5 * analysis_count, None) progress.addTask(Tasks.WRITE_RESULTS, 1, None) initial_alloc_state = stack_allocator.state() graph = None try: # Attraction points progress.setCurrentTask(Tasks.READ_ATTRACTIONS) (attr_table, attr_rows, attr_points, attr_points_per_polygon) = ReadAttractionPoints( model, pstalgo, stack_allocator, props, progress) # Graph progress.setCurrentTask(Tasks.BUILD_GRAPH) (graph, line_rows, origin_rows) = BuildAxialGraph( model, pstalgo, stack_allocator, self._props['in_network'], self._props['in_unlinks'] if self._props['in_unlinks_enabled'] else None, self._props['in_origin_points'] if origin_type in [ pstalgo.OriginType.POINTS, pstalgo.OriginType.POINT_GROUPS ] else None, progress, poly_edge_point_interval=props[ 'origin_poly_edge_point_interval'] if (origin_type == pstalgo.OriginType.POINT_GROUPS) else 0) # Output count output_count = 0 junction_coords = None if origin_type in [ pstalgo.OriginType.POINTS, pstalgo.OriginType.POINT_GROUPS ]: output_count = origin_rows.size() elif origin_type == pstalgo.OriginType.LINES: output_count = line_rows.size() elif origin_type == pstalgo.OriginType.JUNCTIONS: output_count = pstalgo.GetGraphInfo(graph).m_CrossingCount junction_coords = Vector(ctypes.c_double, output_count * 2, stack_allocator, output_count * 2) pstalgo.GetGraphCrossingCoords(graph, junction_coords) else: assert (False) columns = [] attr_points_temp = None attr_points_per_polygon_temp = None progress.setCurrentTask(Tasks.ANALYSIS) analysis_progress = TaskSplitProgressDelegate( analysis_count, "Performing analysis", progress) for attr_col in attraction_columns: # Attraction values if attr_col is None: attr_points_filtered = attr_points attr_points_per_polygon_filtered = attr_points_per_polygon else: attr_values = AttractionValueGen(model, attr_table, attr_rows, [attr_col], progress) (attr_points_temp, attr_points_per_polygon_temp) = FilterZeroAttractions( attr_points, attr_points_per_polygon, attr_values, stack_allocator, attr_points_temp, attr_points_per_polygon_temp) attr_points_filtered = attr_points_temp attr_points_per_polygon_filtered = attr_points_per_polygon_temp # Distance types for distance_type in distance_types: # Allocate output array scores = Vector(ctypes.c_float, output_count, stack_allocator, output_count) # Analysis pstalgo.AttractionDistance( graph_handle=graph, origin_type=origin_type, distance_type=distance_type, radius=radii, attraction_points=attr_points_filtered, points_per_polygon=attr_points_per_polygon_filtered, polygon_point_interval=props[ 'dest_poly_edge_point_interval'], progress_callback=pstalgo. CreateAnalysisDelegateCallbackWrapper( analysis_progress), out_min_distances=scores) # Output column attr_title = GenerateAttractionDataName( props['in_destinations'], attr_col, props['dest_name']) columns.append( (GenerateColumnName(attr_title, distance_type, radii), 'float', scores.values())) # Progress analysis_progress.nextTask() # Write progress.setCurrentTask(Tasks.WRITE_RESULTS) if origin_type in [ pstalgo.OriginType.POINTS, pstalgo.OriginType.POINT_GROUPS ]: model.writeColumns(self._props['in_origin_points'], origin_rows, columns, progress) elif origin_type == pstalgo.OriginType.LINES: model.writeColumns(self._props['in_network'], line_rows, columns, progress) elif origin_type == pstalgo.OriginType.JUNCTIONS: model.createTable(props['in_network'] + '_junctions', model.coordinateReferenceSystem( self._props['in_network']), columns, PointGen(junction_coords, model), int(junction_coords.size() / 2), progress, geo_type=GeometryType.POINT) pass else: assert (False) finally: stack_allocator.restore(initial_alloc_state) if graph: pstalgo.FreeGraph(graph) delegate.setStatus("Attraction Distance done") delegate.setProgress(1)
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load Vector = pstalgo.Vector origins_enabled = self._props['in_origins_enabled'] radii_list = RadiiFromSettings(pstalgo, self._props).split() analysis_count = len(radii_list) # Tasks class Tasks(object): BUILD_GRAPH = 1 READ_POINTS = 2 ANALYSIS = 3 WRITE_RESULTS = 4 progress = MultiTaskProgressDelegate(delegate) progress.addTask(Tasks.BUILD_GRAPH, 1, None) if origins_enabled: progress.addTask(Tasks.READ_POINTS, 1, "Reading points") progress.addTask(Tasks.ANALYSIS, 10*analysis_count, None) initial_alloc_state = stack_allocator.state() graph = None try: # Graph progress.setCurrentTask(Tasks.BUILD_GRAPH) (graph, line_rows, _) = BuildAxialGraph( self._model, pstalgo, stack_allocator, self._props['in_network'], self._props['in_unlinks'] if self._props['in_unlinks_enabled'] else None, None, progress) line_count = line_rows.size() # Origins origins = None origin_rows = None if origins_enabled: progress.setCurrentTask(Tasks.READ_POINTS) max_origin_count = self._model.rowCount(self._props['in_origins']) origin_rows = Vector(ctypes.c_uint, max_origin_count, stack_allocator) origins = Vector(ctypes.c_double, max_origin_count*2, stack_allocator) self._model.readPoints(self._props['in_origins'], origins, origin_rows, progress) # Allocate output arrays output_count = origin_rows.size() if origins_enabled else line_count reached_count = Vector(ctypes.c_uint, output_count, stack_allocator, output_count) if self._props['calc_count'] else None reached_length = Vector(ctypes.c_float, output_count, stack_allocator, output_count) if self._props['calc_length'] else None reached_area = Vector(ctypes.c_float, output_count, stack_allocator, output_count) if self._props['calc_area'] else None # Radius progress.setCurrentTask(Tasks.ANALYSIS) analysis_progress = TaskSplitProgressDelegate(analysis_count, "Performing analysis", progress) for radii in radii_list: # Analysis sub progress analysis_sub_progress = MultiTaskProgressDelegate(analysis_progress) analysis_sub_progress.addTask(Tasks.ANALYSIS, 1, "Calculating") analysis_sub_progress.addTask(Tasks.WRITE_RESULTS, 0, "Writing line results") # Analysis analysis_sub_progress.setCurrentTask(Tasks.ANALYSIS) pstalgo.Reach( graph_handle = graph, radius = radii, origin_points = origins, progress_callback = pstalgo.CreateAnalysisDelegateCallbackWrapper(analysis_sub_progress), out_reached_count = reached_count, out_reached_length = reached_length, out_reached_area = reached_area) # Area unit conversion area_unit = self._props['area_unit'] if reached_area is not None: if area_unit != 'm2': factor = {'km2' : 0.000001, 'ha' : 0.0001}[area_unit] ptr = reached_area.ptr() for i in range(reached_area.size()): ptr[i] = ptr[i] * factor # Output columns columns = [] if reached_count is not None: columns.append((GenColName(ColName.REACH, radii=radii, extra=ColName.EXTRA_NODE_COUNT), 'integer', reached_count.values())) if reached_length is not None: columns.append((GenColName(ColName.REACH, radii=radii, extra=ColName.EXTRA_LENGTH), 'float', reached_length.values())) if reached_area is not None: columns.append((GenColName(ColName.REACH, radii=radii, extra=ColName.EXTRA_AREA_CONVEX_HULL, unit=ColNameUnitFromPropAreaUnit(area_unit)), 'float', reached_area.values())) # Write analysis_sub_progress.setCurrentTask(Tasks.WRITE_RESULTS) self._model.writeColumns( self._props['in_origins'] if origins_enabled else self._props['in_network'], origin_rows if origins_enabled else line_rows, columns, analysis_sub_progress) # Progress analysis_progress.nextTask() finally: stack_allocator.restore(initial_alloc_state) if graph: pstalgo.FreeGraph(graph) graph = None delegate.setStatus("Reach done") delegate.setProgress(1)
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load Vector = pstalgo.Vector props = self._props model = self._model origin_weights_column = props['in_origin_weights'] network_table = props['in_network'] destination_weights_column = props['in_destination_weights'] if props['in_destination_weights_enabled'] else None destination_mode = { "all" : pstalgo.ODBDestinationMode.ALL_REACHABLE_DESTINATIONS, "closest" : pstalgo.ODBDestinationMode.CLOSEST_DESTINATION_ONLY, }[props["destination_mode"]] distance_type = { "walking" : pstalgo.DistanceType.WALKING, "angular" : pstalgo.DistanceType.ANGULAR, }[props["route_choice"]] # Radii radii_list = RadiiFromSettings(pstalgo, props).split() # Only applicable in non-weight mode column_suffix = props['column_suffix'] if props['column_suffix_enabled'] else None def GenerateColumnName(distance_type, radii, suffix=None): # NOTE: Distance mode will be implicit since it will always be the same as radius type name = GenColName( analysis = ColName.ODBETWEENNESS, pst_distance_type = distance_type, radii = radii) if suffix is not None: name += '_' + suffix return name # Number of analyses analysis_count = len(radii_list) # Tasks class Tasks(object): READ_ORIGIN_POINTS = 1 READ_ORIGIN_WEIGHTS = 2 BUILD_GRAPH = 3 READ_DESTINATION_WEIGHTS = 4 ANALYSIS = 5 WRITE_RESULTS = 6 progress = MultiTaskProgressDelegate(delegate) progress.addTask(Tasks.READ_ORIGIN_POINTS, 1, None) progress.addTask(Tasks.READ_ORIGIN_WEIGHTS, 1, None) progress.addTask(Tasks.BUILD_GRAPH, 3, None) progress.addTask(Tasks.READ_DESTINATION_WEIGHTS, 1, None) progress.addTask(Tasks.ANALYSIS, 10*analysis_count, None) progress.addTask(Tasks.WRITE_RESULTS, 1, None) initial_alloc_state = stack_allocator.state() graph_handle = None try: # Origins progress.setCurrentTask(Tasks.READ_ORIGIN_POINTS) origins_table = props['in_origins'] origin_max_count = model.rowCount(origins_table) origin_ids = Vector(ctypes.c_longlong, origin_max_count, stack_allocator) origin_points = Vector(ctypes.c_double, origin_max_count*2, stack_allocator) model.readPoints(origins_table, origin_points, origin_ids, progress) progress.setCurrentTask(Tasks.READ_ORIGIN_WEIGHTS) origin_weights = Vector(ctypes.c_float, origin_ids.size(), stack_allocator) for value in AttractionValueGen(model, origins_table, origin_ids, [origin_weights_column], progress): origin_weights.append(value) # Graph progress.setCurrentTask(Tasks.BUILD_GRAPH) destinations_table = props['in_destinations'] (graph_handle, line_rows, destination_rows) = BuildAxialGraph( model, pstalgo, stack_allocator, network_table, self._props['in_unlinks'] if self._props['in_unlinks_enabled'] else None, destinations_table, progress) # Destination weights if destination_weights_column: progress.setCurrentTask(Tasks.READ_DESTINATION_WEIGHTS) destination_weights = Vector(ctypes.c_float, destination_rows.size(), stack_allocator) for value in AttractionValueGen(model, destinations_table, destination_rows, [destination_weights_column], progress): destination_weights.append(value) else: destination_weights = None output_count = line_rows.size() output_columns = [] # Analyses progress.setCurrentTask(Tasks.ANALYSIS) analysis_progress = TaskSplitProgressDelegate(analysis_count, "Performing analysis", progress) for radii in radii_list: # Allocate output array scores = Vector(ctypes.c_float, output_count, stack_allocator, output_count) # Analysis pstalgo.ODBetweenness( graph_handle = graph_handle, origin_points = origin_points, origin_weights = origin_weights, destination_weights = destination_weights, destination_mode = destination_mode, distance_type = distance_type, radius = radii, progress_callback = pstalgo.CreateAnalysisDelegateCallbackWrapper(analysis_progress), out_scores = scores) output_columns.append((GenerateColumnName(distance_type=distance_type, radii=radii, suffix=column_suffix), 'float', scores.values())) analysis_progress.nextTask() # Write progress.setCurrentTask(Tasks.WRITE_RESULTS) model.writeColumns(network_table, line_rows, output_columns, progress) finally: stack_allocator.restore(initial_alloc_state) if graph_handle: pstalgo.FreeGraph(graph_handle) delegate.setStatus("Origin-Destination Betweenness done") delegate.setProgress(1)
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load Vector = pstalgo.Vector junctions_enabled = self._props['output_at_junctions'] radii_list = RadiiFromSettings(pstalgo, self._props).split() # Tasks class Tasks(object): BUILD_GRAPH = 1 ANALYSIS = 2 WRITE_LINE_RESULTS = 3 WRITE_JUNCTION_RESULTS = 4 progress = MultiTaskProgressDelegate(delegate) progress.addTask(Tasks.BUILD_GRAPH, 1, None) progress.addTask(Tasks.ANALYSIS, 2 * len(radii_list), None) initial_alloc_state = stack_allocator.state() graph = None try: # Graph progress.setCurrentTask(Tasks.BUILD_GRAPH) (graph, line_rows, _) = BuildAxialGraph( self._model, pstalgo, stack_allocator, self._props['in_network'], self._props['in_unlinks'] if self._props['in_unlinks_enabled'] else None, None, progress) line_count = line_rows.size() # Allocate output arrays scores = Vector(ctypes.c_float, line_count, stack_allocator, line_count) total_counts = Vector( ctypes.c_uint, line_count, stack_allocator, line_count ) if self._props['output_N'] or self._props['output_MD'] else None total_depths = Vector( ctypes.c_float, line_count, stack_allocator, line_count ) if self._props['output_TD'] or self._props['output_MD'] else None # Junction output junction_count = pstalgo.GetGraphInfo( graph).m_CrossingCount if junctions_enabled else 0 junction_coords = Vector(ctypes.c_double, junction_count * 2, stack_allocator, junction_count * 2) if junctions_enabled else None junction_scores = Vector( ctypes.c_float, junction_count, stack_allocator, junction_count) if junctions_enabled else None progress.setCurrentTask(Tasks.ANALYSIS) radii_progress = TaskSplitProgressDelegate(len(radii_list), "Performing analysis", progress) for radii in radii_list: radii_sub_progress = MultiTaskProgressDelegate(radii_progress) radii_sub_progress.addTask(Tasks.ANALYSIS, 3, "Calculating") radii_sub_progress.addTask(Tasks.WRITE_LINE_RESULTS, 1, "Writing line results") if junctions_enabled: radii_sub_progress.addTask(Tasks.WRITE_JUNCTION_RESULTS, 1, "Writing junction results") # Analysis radii_sub_progress.setCurrentTask(Tasks.ANALYSIS) pstalgo.NetworkIntegration( graph_handle=graph, radius=radii, progress_callback=pstalgo. CreateAnalysisDelegateCallbackWrapper(radii_sub_progress), out_junction_coords=junction_coords, out_junction_scores=junction_scores, out_line_integration=scores, out_line_node_count=total_counts, out_line_total_depth=total_depths) # Line outputs radii_sub_progress.setCurrentTask(Tasks.WRITE_LINE_RESULTS) columns = [] if scores is not None: columns.append( (GenColName(ColName.NETWORK_INTEGRATION, radii=radii), 'float', scores.values())) if total_counts is not None: columns.append( (GenColName(ColName.NETWORK_INTEGRATION, radii=radii, extra=ColName.EXTRA_NODE_COUNT), 'integer', total_counts.values())) if total_depths is not None: columns.append( (GenColName(ColName.NETWORK_INTEGRATION, radii=radii, extra=ColName.EXTRA_TOTAL_DEPTH), 'float', total_depths.values())) if self._props['output_MD']: columns.append( (GenColName(ColName.NETWORK_INTEGRATION, radii=radii, extra=ColName.EXTRA_MEAN_DEPTH), 'float', MeanDepthGen(total_depths, total_counts))) self._model.writeColumns(self._props['in_network'], line_rows, columns, radii_sub_progress) # Junction output if junctions_enabled: radii_sub_progress.setCurrentTask( Tasks.WRITE_JUNCTION_RESULTS) columns = [] columns.append( (column_base_name, 'float', junction_scores.values())) self._model.createTable( self._props['in_network'] + '_junctions', self._model.coordinateReferenceSystem( self._props['in_network']), columns, PointGen(junction_coords, self._model), junction_count, radii_sub_progress, geo_type=GeometryType.POINT) radii_progress.nextTask() # Free graph pstalgo.FreeGraph(graph) graph = None finally: stack_allocator.restore(initial_alloc_state) if graph: pstalgo.FreeGraph(graph) graph = None delegate.setStatus("Network Integration done") delegate.setProgress(1)
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load Vector = pstalgo.Vector props = self._props radii_list = RadiiFromSettings(pstalgo, self._props).split() # Distance modes distance_modes = DistanceTypesFromSettings(pstalgo, props) # Weight modes class WeightMode(object): NONE = 0 LENGTH = 1 weight_modes = [] if props['weight_none']: weight_modes.append(WeightMode.NONE) if props['weight_length']: weight_modes.append(WeightMode.LENGTH) if props['weight_data']: for name in props['weight_data_cols']: weight_modes.append(name) def GenerateScoreColumnName(distance_mode, weight, radii, norm): if weight == WeightMode.NONE: weight = ColName.WEIGHT_NONE elif weight == WeightMode.LENGTH: weight = ColName.WEIGHT_LENGTH return GenColName(ColName.NETWORK_BETWEENNESS, pst_distance_type=distance_mode, weight=weight, radii=radii, normalization=norm) def GenerateStatColumnName(stat, distance_mode, radii): name = GenColName(ColName.NETWORK_BETWEENNESS, pst_distance_type=distance_mode, radii=radii, extra=stat) print(name) return name # Number of analyses analysis_count = len(radii_list) * len(distance_modes) * len( weight_modes) # Tasks class Tasks(object): BUILD_GRAPH = 1 ANALYSIS = 2 WRITE_RESULTS = 3 progress = MultiTaskProgressDelegate(delegate) progress.addTask(Tasks.BUILD_GRAPH, 1, None) progress.addTask(Tasks.ANALYSIS, 5 * analysis_count, None) initial_alloc_state = stack_allocator.state() graph = None try: # Graph progress.setCurrentTask(Tasks.BUILD_GRAPH) (graph, line_rows, _) = BuildAxialGraph( self._model, pstalgo, stack_allocator, self._props['in_network'], self._props['in_unlinks'] if self._props['in_unlinks_enabled'] else None, None, progress) line_count = line_rows.size() # Allocate output arrays weights = None scores = Vector(ctypes.c_float, line_count, stack_allocator, line_count) scores_std = Vector(ctypes.c_float, line_count, stack_allocator, line_count) if props['norm_standard'] else None total_counts = Vector(ctypes.c_uint, line_count, stack_allocator, line_count) total_depths = Vector(ctypes.c_float, line_count, stack_allocator, line_count) output_N = (False != props['output_N']) output_TD = (False != props['output_TD']) output_MD = (False != props['output_MD']) progress.setCurrentTask(Tasks.ANALYSIS) analysis_progress = TaskSplitProgressDelegate( analysis_count, "Performing analysis", progress) for weight_mode in weight_modes: # Get weights if weight_mode == WeightMode.NONE: pass elif weight_mode == WeightMode.LENGTH: if weights is None: weights = Vector(ctypes.c_float, line_count, stack_allocator) weights.resize(line_count) pstalgo.GetGraphLineLengths(graph, weights) else: if weights is None: weights = Vector(ctypes.c_float, line_count, stack_allocator) column_name = weight_mode analysis_progress.setStatus("Reading weight data '%s'" % column_name) weights.resize(0) self._model.readValues(self._props['in_network'], column_name, line_rows, weights) # These metrics are independent of weight mode, and should therefore only be outputted for first weight mode if weight_mode != weight_modes[0]: output_N = False output_TD = False output_MD = False for radii in radii_list: for distance_mode in distance_modes: # Analysis sub progress analysis_sub_progress = MultiTaskProgressDelegate( analysis_progress) analysis_sub_progress.addTask(Tasks.ANALYSIS, 3, "Calculating") analysis_sub_progress.addTask(Tasks.WRITE_RESULTS, 1, "Writing line results") # Analysis analysis_sub_progress.setCurrentTask(Tasks.ANALYSIS) pstalgo.SegmentBetweenness( graph_handle=graph, distance_type=distance_mode, radius=radii, weights=None if weight_mode == WeightMode.NONE else weights, attraction_points=None, progress_callback=pstalgo. CreateAnalysisDelegateCallbackWrapper( analysis_sub_progress), out_betweenness=scores, out_node_count=total_counts, out_total_depth=total_depths) # Output analysis_sub_progress.setCurrentTask( Tasks.WRITE_RESULTS) columns = [] # No normalization if props['norm_none']: columns.append((GenerateScoreColumnName( distance_mode, weight_mode, radii, ColName.NORM_NONE), 'float', scores.values())) # Standard normalization if scores_std is not None: pstalgo.StandardNormalize(scores, scores.size(), scores_std) columns.append((GenerateScoreColumnName( distance_mode, weight_mode, radii, ColName.NORM_STANDARD), 'float', scores_std.values())) # Node counts if output_N: columns.append((GenerateStatColumnName( ColName.EXTRA_NODE_COUNT, distance_mode, radii), 'integer', total_counts.values())) # Total depths if output_TD: columns.append((GenerateStatColumnName( ColName.EXTRA_TOTAL_DEPTH, distance_mode, radii), 'float', total_depths.values())) # Mean depths if output_MD: columns.append( (GenerateStatColumnName( ColName.EXTRA_MEAN_DEPTH, distance_mode, radii), 'float', MeanDepthGen(total_depths, total_counts))) # Write self._model.writeColumns(self._props['in_network'], line_rows, columns, analysis_sub_progress) analysis_progress.nextTask() finally: stack_allocator.restore(initial_alloc_state) if graph: pstalgo.FreeGraph(graph) delegate.setStatus("Network Betweenness done") delegate.setProgress(1)