Beispiel #1
0
def clean_up():
  """
  Removes all auxiliary files
  """
  auxiliary_dir = join(inputs[OUTPUT_LOCATION], AUXILIARY_DIR_NAME)
  od_cost_matrix_layer = join(auxiliary_dir, OD_COST_MATRIX_LAYER_NAME)
  od_cost_matrix_lines = join(auxiliary_dir, OD_COST_MATRIX_LINES)
  temp_adj_dbf_name = "%s~.dbf" % adj_dbf_name[-4]
  temp_adj_dbf = join(inputs[OUTPUT_LOCATION], temp_adj_dbf_name)
  partial_adj_dbf = join(auxiliary_dir, PARTIAL_ADJACENCY_LIST_NAME)
  polygons = join(auxiliary_dir, POLYGONS_SHAPEFILE_NAME)
  raster = join(auxiliary_dir, RASTER_NAME)
  polygons_layer = join(auxiliary_dir, POLYGONS_LAYER_NAME)
  input_points_layer = join(auxiliary_dir, INPUT_POINTS_LAYER_NAME)
  for delete_path in [input_points_layer, polygons_layer, raster, polygons,
      partial_adj_dbf, temp_adj_dbf, od_cost_matrix_lines, od_cost_matrix_layer,
      auxiliary_dir]:
    delete(delete_path)
def clean_up():
  """
  Removes all auxiliary files
  """
  auxiliary_dir = join(inputs[OUTPUT_LOCATION], AUXILIARY_DIR_NAME)
  od_cost_matrix_layer = join(auxiliary_dir, OD_COST_MATRIX_LAYER_NAME)
  od_cost_matrix_lines = join(auxiliary_dir, OD_COST_MATRIX_LINES)
  temp_adj_dbf_name = "%s~.dbf" % adj_dbf_name[-4]
  temp_adj_dbf = join(inputs[OUTPUT_LOCATION], temp_adj_dbf_name)
  partial_adj_dbf = join(auxiliary_dir, PARTIAL_ADJACENCY_LIST_NAME)
  polygons = join(auxiliary_dir, POLYGONS_SHAPEFILE_NAME)
  raster = join(auxiliary_dir, RASTER_NAME)
  polygons_layer = join(auxiliary_dir, POLYGONS_LAYER_NAME)
  input_points_layer = join(auxiliary_dir, INPUT_POINTS_LAYER_NAME)
  for delete_path in [input_points_layer, polygons_layer, raster, polygons,
      partial_adj_dbf, temp_adj_dbf, od_cost_matrix_lines, od_cost_matrix_layer,
      auxiliary_dir]:
    delete(delete_path)
Beispiel #3
0
def compute_adjacency_list(input_points, input_network, id_attribute,
                           impedance_attribute, accumulator_attributes,
                           search_radius, output_location, adj_dbf_name):
    """
  |input_points|: point shape file marking entity (e.g. building) locations
  |input_network|: street network in which |input_points| is located
  |id_attribute|: the name of attribute that distinguishes between input points
  |impedance_attribute|: distance between neighboring nodes will be based on
      this attribute
  |accumulator_attributes|: distance between neighboring nodes will also be
      recorded for these attributes
  |search_radius|: the maximum extent for centrality computation
  |output_location|: adjacency list dbf will be saved here
  |adj_dbf_name|: the name of the adjacency list dbf
  """

    # Number of points in |input_points|
    input_point_count = int(GetCount_management(input_points).getOutput(0))

    # Make a directory to store all auxiliary files
    auxiliary_dir = join(output_location, AUXILIARY_DIR_NAME)
    if not Exists(auxiliary_dir):
        mkdir(auxiliary_dir)

    # Record the edge and junction source names of |input_network|
    junction_feature, edge_feature = network_features(input_network)

    # Calculate network locations if not already calculated
    test_input_point = UpdateCursor(input_points).next()
    locations_calculated = all(
        row_has_field(test_input_point, field)
        for field in NETWORK_LOCATION_FIELDS)
    if not locations_calculated:
        calculate_network_locations(input_points, input_network)

    # Calculate barrier cost per input point if not already calculated
    barrier_costs_calculated = row_has_field(test_input_point,
                                             trim(BARRIER_COST_FIELD))
    if not barrier_costs_calculated:
        AddMessage(BARRIER_COST_COMPUTATION_STARTED)
        # Add |BARRIER_COST_FIELD| column in |input_points|
        AddField_management(in_table=input_points,
                            field_name=trim(BARRIER_COST_FIELD),
                            field_type="DOUBLE",
                            field_is_nullable="NON_NULLABLE")

        # Initialize a dictionary to store the frequencies of (SnapX, SnapY) values
        xy_count = {}
        # A method to retrieve a (SnapX, SnapY) pair for a row in |input_points|
        get_xy = lambda row: (row.getValue(trim("SnapX")),
                              row.getValue(trim("SnapY")))

        barrier_pre_progress = Progress_Bar(input_point_count, 1,
                                            BARRIER_COST_PRE_PROCESSING)
        rows = UpdateCursor(input_points)
        for row in rows:
            snap_xy = get_xy(row)
            if snap_xy in xy_count:
                xy_count[snap_xy] += 1
            else:
                xy_count[snap_xy] = 1
            barrier_pre_progress.step()

        # Populate |BARRIER_COST_FIELD|, this will be used in OD matrix computation
        barrier_progress = Progress_Bar(input_point_count, 1,
                                        BARRIER_COST_COMPUTATION)
        rows = UpdateCursor(input_points)
        for row in rows:
            barrier_cost = BARRIER_COST / xy_count[get_xy(row)]
            row.setValue(trim(BARRIER_COST_FIELD), barrier_cost)
            rows.updateRow(row)
            barrier_progress.step()
        AddMessage(BARRIER_COST_COMPUTATION_FINISHED)

    # Necessary files
    od_cost_matrix_layer = join(auxiliary_dir, OD_COST_MATRIX_LAYER_NAME)
    od_cost_matrix_lines = join(od_cost_matrix_layer, OD_COST_MATRIX_LINES)
    temp_adj_dbf_name = TEMP_ADJACENCY_DBF_NAME(adj_dbf_name)
    temp_adj_dbf = join(output_location, temp_adj_dbf_name)
    adj_dbf = join(output_location, adj_dbf_name)
    partial_adj_dbf = join(auxiliary_dir, PARTIAL_ADJACENCY_LIST_NAME)
    polygons = join(auxiliary_dir, POLYGONS_SHAPEFILE_NAME)
    raster = join(auxiliary_dir, RASTER_NAME)
    polygons_layer = join(auxiliary_dir, POLYGONS_LAYER_NAME)
    input_points_layer = join(auxiliary_dir, INPUT_POINTS_LAYER_NAME)

    # Make sure none of these files already exists
    for path in [
            od_cost_matrix_layer, temp_adj_dbf, adj_dbf, partial_adj_dbf,
            polygons, raster, polygons_layer, input_points_layer,
            od_cost_matrix_lines
    ]:
        delete(path)

    # Cutoff radius for OD matrix computation
    cutoff_radius = 2 * BARRIER_COST + min(search_radius, BARRIER_COST / 2)

    # Compute OD matrix
    MakeODCostMatrixLayer_na(in_network_dataset=input_network,
                             out_network_analysis_layer=od_cost_matrix_layer,
                             impedance_attribute=impedance_attribute,
                             default_cutoff=str(cutoff_radius),
                             accumulate_attribute_name=accumulator_attributes,
                             UTurn_policy="ALLOW_UTURNS",
                             hierarchy="NO_HIERARCHY",
                             output_path_shape="NO_LINES")

    # Determine raster cell size
    points_per_raster_cell = OD_MATRIX_ENTRIES / input_point_count
    raster_cell_count = max(1, input_point_count / points_per_raster_cell)
    input_points_extent = Describe(input_points).Extent
    raster_cell_area = (input_points_extent.width *
                        input_points_extent.height / raster_cell_count)
    raster_cell_size = int(sqrt(raster_cell_area))

    # Construct |raster| from |input_points|
    PointToRaster_conversion(in_features=input_points,
                             value_field=id_attribute,
                             out_rasterdataset=raster,
                             cell_assignment="MOST_FREQUENT",
                             priority_field="NONE",
                             cellsize=str(raster_cell_size))

    # Construct |polygons| from |raster|
    RasterToPolygon_conversion(in_raster=raster,
                               out_polygon_features=polygons,
                               simplify="NO_SIMPLIFY",
                               raster_field="VALUE")

    # Export empty |od_cost_matrix_lines| to |temp_dbf| to start adjacency list
    TableToTable_conversion(in_rows=od_cost_matrix_lines,
                            out_path=output_location,
                            out_name=temp_adj_dbf_name)

    # Construct |polygons_layer| and |input_points_layer|
    for (feature, layer) in [(polygons, polygons_layer),
                             (input_points, input_points_layer)]:
        MakeFeatureLayer_management(in_features=feature, out_layer=layer)

    def add_locations(sub_layer, field_mappings=""):
        """
    |sub_layer|: one of "Origins", "Destinations", "Barrier Points"
    |field_mappings|: field mappings in addition to those for "Name" and
        "CurbApproach"
    """
        AddLocations_na(in_network_analysis_layer=od_cost_matrix_layer,
                        sub_layer=sub_layer,
                        in_table=input_points_layer,
                        field_mappings=("Name %s #; CurbApproach # 0; %s" %
                                        (id_attribute, field_mappings)),
                        search_tolerance=SEARCH_TOLERANCE,
                        search_criteria=("%s SHAPE; %s SHAPE;" %
                                         (junction_feature, edge_feature)),
                        append="CLEAR",
                        snap_to_position_along_network="SNAP",
                        snap_offset=SNAP_OFFSET)

    # OD cost matrix destinations
    AddMessage(ADDING_DESTINATIONS_STARTED)
    SelectLayerByLocation_management(in_layer=input_points_layer)
    add_locations("Destinations")
    AddMessage(ADDING_DESTINATIONS_FINISHED)

    # OD cost matrix point barriers
    AddMessage(ADDING_BARRIERS_STARTED)
    add_locations("Point Barriers",
                  ("FullEdge # 0; BarrierType # 2;"
                   "Attr_%s %s #;" %
                   (impedance_attribute, trim(BARRIER_COST_FIELD))))
    AddMessage(ADDING_BARRIERS_FINISHED)

    # Compute adjacency list, one raster cell at a time
    progress = Progress_Bar(raster_cell_count, 1, STEP_1)
    rows = UpdateCursor(polygons)
    for row in rows:
        # Select the current polygon
        SelectLayerByAttribute_management(in_layer_or_view=polygons_layer,
                                          selection_type="NEW_SELECTION",
                                          where_clause="FID = %s" %
                                          str(row.FID))

        # Origins
        SelectLayerByLocation_management(in_layer=input_points_layer,
                                         select_features=polygons_layer)
        add_locations("Origins")

        # Solve OD Cost matrix
        Solve_na(in_network_analysis_layer=od_cost_matrix_layer,
                 ignore_invalids="SKIP")

        # Add origin and destination fields to the adjacency list dbf
        for (index, field) in [(0, ORIGIN_ID_FIELD_NAME),
                               (1, DESTINATION_ID_FIELD_NAME)]:
            CalculateField_management(in_table=od_cost_matrix_lines,
                                      field=field,
                                      expression="!Name!.split(' - ')[%d]" %
                                      index,
                                      expression_type="PYTHON")

        # Record actual distance between neighboring nodes
        distance_field = "Total_%s" % impedance_attribute
        CalculateField_management(in_table=od_cost_matrix_lines,
                                  field=distance_field,
                                  expression="!%s! - 2 * %d" %
                                  (distance_field, BARRIER_COST),
                                  expression_type="PYTHON")

        # Append result to |temp_adj_dbf|
        TableToTable_conversion(in_rows=od_cost_matrix_lines,
                                out_path=auxiliary_dir,
                                out_name=PARTIAL_ADJACENCY_LIST_NAME)
        Append_management(inputs=partial_adj_dbf,
                          target=temp_adj_dbf,
                          schema_type="TEST")

        progress.step()

    # Copy data from |temp_adj_dbf| to |adj_dbf|
    Rename_management(in_data=temp_adj_dbf, out_data=adj_dbf)

    # Clean up
    for path in [
            od_cost_matrix_layer, partial_adj_dbf, polygons, raster,
            polygons_layer, input_points_layer, auxiliary_dir
    ]:
        delete(path)
def compute_adjacency_list(input_points, input_network, id_attribute,
    impedance_attribute, accumulator_attributes, search_radius, output_location,
    adj_dbf_name):
  """
  |input_points|: point shape file marking entity (e.g. building) locations
  |input_network|: street network in which |input_points| is located
  |id_attribute|: the name of attribute that distinguishes between input points
  |impedance_attribute|: distance between neighboring nodes will be based on
      this attribute
  |accumulator_attributes|: distance between neighboring nodes will also be
      recorded for these attributes
  |search_radius|: the maximum extent for centrality computation
  |output_location|: adjacency list dbf will be saved here
  |adj_dbf_name|: the name of the adjacency list dbf
  """

  # Number of points in |input_points|
  input_point_count = int(GetCount_management(input_points).getOutput(0))

  # Make a directory to store all auxiliary files
  auxiliary_dir = join(output_location, AUXILIARY_DIR_NAME)
  if not Exists(auxiliary_dir):
    mkdir(auxiliary_dir)

  # Record the edge and junction source names of |input_network|
  edge_feature = None
  junction_feature = None
  for source in Describe(input_network).sources:
    if source.sourceType == EDGE_FEATURE:
      edge_feature = source.name
    elif source.sourceType in JUNCTION_FEATURE:
      junction_feature = source.name
  if edge_feature == None:
    AddWarning(WARNING_NO_EDGE_FEATURE(input_network))
    raise Invalid_Input_Exception("Input Network")
  if junction_feature == None:
    AddWarning(WARNING_NO_JUNCTION_FEATURE(input_network))
    raise Invalid_Input_Exception("Input Network")

  # Calculate network locations if not already calculated
  test_input_point = UpdateCursor(input_points).next()
  locations_calculated = all(row_has_field(test_input_point, field)
      for field in NETWORK_LOCATION_FIELDS)
  if not locations_calculated:
    AddMessage(CALCULATE_LOCATIONS_STARTED)
    CalculateLocations_na(in_point_features=input_points,
        in_network_dataset=input_network,
        search_tolerance=SEARCH_TOLERANCE,
        search_criteria=("%s SHAPE; %s SHAPE;" %
            (junction_feature, edge_feature)),
        exclude_restricted_elements="INCLUDE")
    AddMessage(CALCULATE_LOCATIONS_FINISHED)

  # Calculate barrier cost per input point if not already calculated
  barrier_costs_calculated = row_has_field(test_input_point,
      trim(BARRIER_COST_FIELD))
  if not barrier_costs_calculated:
    AddMessage(BARRIER_COST_COMPUTATION_STARTED)
    # Add |BARRIER_COST_FIELD| column in |input_points|
    AddField_management(in_table=input_points,
        field_name=trim(BARRIER_COST_FIELD), field_type="DOUBLE",
        field_is_nullable="NON_NULLABLE")

    # Initialize a dictionary to store the frequencies of (SnapX, SnapY) values
    xy_count = {}
    # A method to retrieve a (SnapX, SnapY) pair for a row in |input_points|
    get_xy = lambda row: (row.getValue(trim("SnapX")),
        row.getValue(trim("SnapY")))

    barrier_pre_progress = Progress_Bar(input_point_count, 1,
        BARRIER_COST_PRE_PROCESSING)
    rows = UpdateCursor(input_points)
    for row in rows:
      snap_xy = get_xy(row)
      if snap_xy in xy_count:
        xy_count[snap_xy] += 1
      else:
        xy_count[snap_xy] = 1
      barrier_pre_progress.step()

    # Populate |BARRIER_COST_FIELD|, this will be used in OD matrix computation
    barrier_progress = Progress_Bar(input_point_count, 1,
        BARRIER_COST_COMPUTATION)
    rows = UpdateCursor(input_points)
    for row in rows:
      barrier_cost = BARRIER_COST / xy_count[get_xy(row)]
      row.setValue(trim(BARRIER_COST_FIELD), barrier_cost)
      rows.updateRow(row)
      barrier_progress.step()
    AddMessage(BARRIER_COST_COMPUTATION_FINISHED)

  # Necessary files
  od_cost_matrix_layer = join(auxiliary_dir, OD_COST_MATRIX_LAYER_NAME)
  od_cost_matrix_lines = join(od_cost_matrix_layer, OD_COST_MATRIX_LINES)
  temp_adj_dbf_name = "%s~.dbf" % adj_dbf_name[:-4]
  temp_adj_dbf = join(output_location, temp_adj_dbf_name)
  adj_dbf = join(output_location, adj_dbf_name)
  partial_adj_dbf = join(auxiliary_dir, PARTIAL_ADJACENCY_LIST_NAME)
  polygons = join(auxiliary_dir, POLYGONS_SHAPEFILE_NAME)
  raster = join(auxiliary_dir, RASTER_NAME)
  polygons_layer = join(auxiliary_dir, POLYGONS_LAYER_NAME)
  input_points_layer = join(auxiliary_dir, INPUT_POINTS_LAYER_NAME)

  # Make sure none of these files already exists
  for path in [od_cost_matrix_layer, temp_adj_dbf, adj_dbf, partial_adj_dbf,
      polygons, raster, polygons_layer, input_points_layer,
      od_cost_matrix_lines]:
    delete(path)

  # Cutoff radius for OD matrix computation
  cutoff_radius = 2 * BARRIER_COST + min(search_radius, BARRIER_COST / 2)

  # Compute OD matrix
  MakeODCostMatrixLayer_na(in_network_dataset=input_network,
      out_network_analysis_layer=od_cost_matrix_layer,
      impedance_attribute=impedance_attribute,
      default_cutoff=str(cutoff_radius),
      accumulate_attribute_name=accumulator_attributes,
      UTurn_policy="ALLOW_UTURNS", hierarchy="NO_HIERARCHY",
      output_path_shape="NO_LINES")

  # Determine raster cell size
  points_per_raster_cell = OD_MATRIX_ENTRIES / input_point_count
  raster_cell_count = max(1, input_point_count / points_per_raster_cell)
  input_points_extent = Describe(input_points).Extent
  raster_cell_area = (input_points_extent.width * input_points_extent.height /
      raster_cell_count)
  raster_cell_size = int(sqrt(raster_cell_area))

  # Construct |raster| from |input_points|
  PointToRaster_conversion(in_features=input_points,
      value_field=id_attribute, out_rasterdataset=raster,
      cell_assignment="MOST_FREQUENT", priority_field="NONE",
      cellsize=str(raster_cell_size))

  # Construct |polygons| from |raster|
  RasterToPolygon_conversion(in_raster=raster,
      out_polygon_features=polygons, simplify="NO_SIMPLIFY",
      raster_field="VALUE")

  # Export empty |od_cost_matrix_lines| to |temp_dbf| to start adjacency list
  TableToTable_conversion(in_rows=od_cost_matrix_lines,
      out_path=output_location, out_name=temp_adj_dbf_name)

  # Construct |polygons_layer| and |input_points_layer|
  for (feature, layer) in [(polygons, polygons_layer),
      (input_points, input_points_layer)]:
    MakeFeatureLayer_management(in_features=feature, out_layer=layer)

  def add_locations(sub_layer, field_mappings=""):
    """
    |sub_layer|: one of "Origins", "Destinations", "Barrier Points"
    |field_mappings|: field mappings in addition to those for "Name" and
        "CurbApproach"
    """
    AddLocations_na(in_network_analysis_layer=od_cost_matrix_layer,
        sub_layer=sub_layer, in_table=input_points_layer,
        field_mappings=("Name %s #; CurbApproach # 0; %s" %
            (id_attribute, field_mappings)),
        search_tolerance=SEARCH_TOLERANCE,
        search_criteria=("%s SHAPE; %s SHAPE;" %
            (junction_feature, edge_feature)),
        append="CLEAR", snap_to_position_along_network="SNAP",
        snap_offset=SNAP_OFFSET)

  # OD cost matrix destinations
  AddMessage(ADDING_DESTINATIONS_STARTED)
  SelectLayerByLocation_management(in_layer=input_points_layer)
  add_locations("Destinations")
  AddMessage(ADDING_DESTINATIONS_FINISHED)

  # OD cost matrix point barriers
  AddMessage(ADDING_BARRIERS_STARTED)
  add_locations("Point Barriers", ("FullEdge # 0; BarrierType # 2;"
      "Attr_%s %s #;" % (impedance_attribute, trim(BARRIER_COST_FIELD))))
  AddMessage(ADDING_BARRIERS_FINISHED)

  # Compute adjacency list, one raster cell at a time
  progress = Progress_Bar(raster_cell_count, 1, STEP_1)
  rows = UpdateCursor(polygons)
  for row in rows:
    # Select the current polygon
    SelectLayerByAttribute_management(in_layer_or_view=polygons_layer,
        selection_type="NEW_SELECTION", where_clause="FID = %s" % str(row.FID))

    # Origins
    SelectLayerByLocation_management(in_layer=input_points_layer,
        select_features=polygons_layer)
    add_locations("Origins")

    # Solve OD Cost matrix
    Solve_na(in_network_analysis_layer=od_cost_matrix_layer,
        ignore_invalids="SKIP")

    # Add origin and destination fields to the adjacency list dbf
    for (index, field) in [(0, ORIGIN_ID_FIELD_NAME),
        (1, DESTINATION_ID_FIELD_NAME)]:
      CalculateField_management(in_table=od_cost_matrix_lines,
          field=field, expression="!Name!.split(' - ')[%d]" % index,
          expression_type="PYTHON")

    # Record actual distance between neighboring nodes
    distance_field = "Total_%s" % impedance_attribute
    CalculateField_management(in_table=od_cost_matrix_lines,
        field=distance_field,
        expression="!%s! - 2 * %d" % (distance_field, BARRIER_COST),
        expression_type="PYTHON")

    # Append result to |temp_adj_dbf|
    TableToTable_conversion(in_rows=od_cost_matrix_lines,
        out_path=auxiliary_dir, out_name=PARTIAL_ADJACENCY_LIST_NAME)
    Append_management(inputs=partial_adj_dbf, target=temp_adj_dbf,
        schema_type="TEST")

    progress.step()

  # Copy data from |temp_adj_dbf| to |adj_dbf|
  Rename_management(in_data=temp_adj_dbf, out_data=adj_dbf)

  # Clean up
  for path in [od_cost_matrix_layer, partial_adj_dbf, polygons, raster,
      polygons_layer, input_points_layer, auxiliary_dir]:
    delete(path)