def netmiles_in_buffer(fc_project, fc_network, project_type):

    # if project is polygon, then use polygon. If line or point, then make polygon as buffer around line/point.
    if project_type == p.ptype_area_agg:
        fc_poly_buff = fc_project
    else:
        fc_poly_buff = r"memory\temp_buff_qmi"
        arcpy.Buffer_analysis(fc_project, fc_poly_buff, p.bikeway_buff)

    fl_poly = "fl_buff"
    if not arcpy.Exists(fl_poly):
        utils.make_fl_conditional(fc_poly_buff, fl_poly)

    temp_intersect_fc = r"memory\temp_intersect_fc"

    #run intersect of network lines against buffer
    arcpy.Intersect_analysis([fc_network, fc_poly_buff], temp_intersect_fc)

    # get total mileage of network lines-buffer intersection fc
    net_len = 0
    with arcpy.da.SearchCursor(temp_intersect_fc, "SHAPE@LENGTH") as cur:
        for row in cur:
            net_len += row[0]

    arcpy.Delete_management(temp_intersect_fc)

    if fc_poly_buff != fc_project:
        arcpy.Delete_management(fc_poly_buff)
    return net_len
def create_tripshed_poly(in_poly_fc, out_poly_fc, poly_id_field, in_df,
                         df_grouby_field):

    # convert numpy (pandas) datatypes to ESRI data types {numpy type: ESRI type}
    dtype_conv_dict = {
        'float64': 'FLOAT',
        'object': 'TEXT',
        'int64': 'LONG',
        'String': 'TEXT',
        'OID': 'LONG',
        'Single': 'DOUBLE',
        'Integer': 'LONG'
    }

    #make copy of base input poly fc that only has features whose IDs are in the dataframe
    fl_input_polys = 'fl_input_polys'
    utils.make_fl_conditional(in_poly_fc, fl_input_polys)

    df_ids = tuple(in_df[df_grouby_field])

    sql = "{} IN {}".format(poly_id_field, df_ids)
    arcpy.SelectLayerByAttribute_management(fl_input_polys, "NEW_SELECTION",
                                            sql)

    arcpy.CopyFeatures_management(fl_input_polys, out_poly_fc)

    # add dataframe fields to the trip shed polygon set

    #dict of {field: field data type} for input dataframe
    fields_dtype_dict = {col: str(in_df[col].dtype) for col in in_df.columns}

    # populate those fields with the dataframe data
    for field in fields_dtype_dict.keys():
        print("adding {} column and data...".format(field))
        field_vals = list(in_df[field])  # get list of values for desired field
        fld_dict = dict(zip(df_ids, field_vals))

        fdtype_numpy = fields_dtype_dict[field]
        fdtype_esri = dtype_conv_dict[fdtype_numpy]

        # add a field, if needed, to the polygon feature class for the values being added
        if utils.esri_field_exists(out_poly_fc, field):
            pass
        else:
            arcpy.AddField_management(out_poly_fc, field, fdtype_esri)

        # populate the field with the appropriate values
        with arcpy.da.UpdateCursor(out_poly_fc, [poly_id_field, field]) as cur:
            for row in cur:
                join_id = row[0]
                if fld_dict.get(join_id) is None:
                    pass
                else:
                    row[1] = fld_dict[join_id]
                    cur.updateRow(row)
Exemple #3
0
def get_acc_data(fc_project, fc_accdata, project_type, get_ej=False):
    arcpy.AddMessage("calculating accessibility metrics...")

    out_dict = {}
    try:
        fl_accdata = "fl_accdata"
        fl_project = "fl_project"

        utils.make_fl_conditional(fc_project, fl_project)
        utils.make_fl_conditional(fc_accdata, fl_accdata)

        # select polygons that intersect with the project line
        searchdist = 0 if project_type == p.ptype_area_agg else p.bg_search_dist
        arcpy.SelectLayerByLocation_management(fl_accdata, "INTERSECT",
                                               fl_project, searchdist,
                                               "NEW_SELECTION")

        # read accessibility data from selected polygons into a dataframe
        accdata_fields = [p.col_geoid, p.col_acc_ej_ind, p.col_pop
                          ] + p.acc_cols_ej
        accdata_df = utils.esri_object_to_df(fl_accdata, accdata_fields)

        # get pop-weighted accessibility values for all accessibility columns
        if get_ej:
            for col in p.acc_cols_ej:
                col_wtd = "{}_wtd".format(col)
                col_ej_pop = "{}_EJ".format(p.col_pop)
                accdata_df[col_wtd] = accdata_df[col] * accdata_df[
                    p.col_pop] * accdata_df[p.col_acc_ej_ind]
                accdata_df[col_ej_pop] = accdata_df[p.col_pop] * accdata_df[
                    p.col_acc_ej_ind]

                tot_ej_pop = accdata_df[col_ej_pop].sum()

                out_wtd_acc = accdata_df[col_wtd].sum(
                ) / tot_ej_pop if tot_ej_pop > 0 else 0
                col_out_ej = "{}_EJ".format(col)
                out_dict[col_out_ej] = out_wtd_acc
        else:
            for col in p.acc_cols:
                col_wtd = "{}_wtd".format(col)
                accdata_df[col_wtd] = accdata_df[col] * accdata_df[p.col_pop]
                out_wtd_acc = accdata_df[col_wtd].sum() / accdata_df[
                    p.col_pop].sum()
                out_dict[col] = out_wtd_acc
    except:
        msg = "{} {}".format(arcpy.GetMessages(2), trace())
        arcpy.AddMessage(msg)

    return out_dict
Exemple #4
0
def point_sum(fc_pclpt,
              fc_project,
              project_type,
              val_fields,
              buffdist,
              case_field=None,
              case_excs_list=[]):
    arcpy.AddMessage("aggregating land use data...")

    scratch_gdb = arcpy.env.scratchGDB
    fl_parcel = "{}/fl_parcel".format(scratch_gdb)
    fl_project = "{}/fl_project".format(scratch_gdb)

    utils.make_fl_conditional(fc_pclpt, fl_parcel)
    utils.make_fl_conditional(fc_project, fl_project)

    buff_dist = 0 if project_type == p.ptype_area_agg else buffdist
    arcpy.SelectLayerByLocation_management(fl_parcel, "WITHIN_A_DISTANCE",
                                           fl_project, buff_dist)

    # If there are no points in the buffer (e.g., no collisions on segment, no parcels, etc.),
    # still add those columns, but make them = 0
    file_len = arcpy.GetCount_management(fl_parcel)
    file_len = int(file_len.getOutput(0))

    if case_field is not None:
        val_fields.append(case_field)

    # load parcel data into dataframe
    rows_pcldata = []
    with arcpy.da.SearchCursor(fl_parcel, val_fields) as cur:
        for row in cur:
            df_row = list(row)
            rows_pcldata.append(df_row)

    parcel_df = pd.DataFrame(rows_pcldata, columns=val_fields)

    if case_field is not None:
        parcel_df = parcel_df.loc[~parcel_df[case_field].isin(
            case_excs_list)]  #exclude specified categories
        out_df = parcel_df.groupby(
            case_field).sum().T  # get sum by category (case field)
        # NEXT ISSUE - need to figure out how to show all case types, even if no parcels with that case type within the buffer
    else:
        out_df = pd.DataFrame(parcel_df[val_fields].sum(axis=0)).T

    out_dict = out_df.to_dict('records')[0]

    return out_dict
Exemple #5
0
def get_centerline_miles(selection_poly_fc, centerline_fc):
    fl_selection_poly = "fl_selection_poly"
    fl_centerline = "fl_centerline"

    utils.make_fl_conditional(selection_poly_fc, fl_selection_poly)
    utils.make_fl_conditional(centerline_fc, fl_centerline)

    arcpy.SelectLayerByLocation_management(fl_centerline, "HAVE_THEIR_CENTER_IN", fl_selection_poly)

    cline_miles = 0
    with arcpy.da.SearchCursor(fl_centerline, "SHAPE@LENGTH") as cur:
        for row in cur:
            cline_miles += row[0]

    return cline_miles / p.ft2mile
Exemple #6
0
def get_model_link_sums(fc_polygon, fc_model_links):

    fl_polygon = "fl_polygon"
    fl_model_links = "fl_model_links"
    utils.make_fl_conditional(fc_polygon, fl_polygon)
    utils.make_fl_conditional(fc_model_links, fl_model_links)

    # select model links whose centroid is within the polygon area
    arcpy.SelectLayerByLocation_management(fl_model_links, "HAVE_THEIR_CENTER_IN", fl_polygon)

    link_data_cols = [p.col_capclass, p.col_distance, p.col_lanemi, p.col_dayvmt]
    output_data_cols = [p.col_dayvmt, p.col_distance]

    # load model links, selected to be near project, into a dataframe
    df_linkdata = utils.esri_object_to_df(fl_model_links, link_data_cols)

    # get total VMT for links within the area
    out_dict = {col: df_linkdata[col].sum() for col in output_data_cols}
    return out_dict
def get_mix_idx(fc_parcel, fc_project, project_type):
    arcpy.AddMessage("calculating mix index...")

    fl_parcel = "fl_parcel"
    fl_project = "fl_project"

    utils.make_fl_conditional(fc_parcel, fl_parcel)
    utils.make_fl_conditional(fc_project, fl_project)

    in_cols = [
        p.col_parcelid, p.col_hh, p.col_k12_enr, p.col_emptot, p.col_empfood,
        p.col_empret, p.col_empsvc, p.col_area_ac, p.col_lutype
    ]

    lu_fac_cols = [
        p.col_k12_enr, p.col_emptot, p.col_empfood, p.col_empret, p.col_empsvc,
        p.col_parkac
    ]
    # make parcel feature layer

    buffer_dist = 0 if project_type == p.ptype_area_agg else p.mix_index_buffdist
    arcpy.SelectLayerByLocation_management(fl_parcel, "WITHIN_A_DISTANCE",
                                           fl_project, buffer_dist,
                                           "NEW_SELECTION")

    summ_df = make_summary_df(fl_parcel, in_cols, lu_fac_cols, p.col_hh,
                              p.park_calc_dict)

    out_df = calc_mix_index(summ_df, p.params_df, p.col_hh, lu_fac_cols,
                            p.mix_idx_col)

    # if you want to make CSV.
    #out_df[[col_hh, mix_idx_col]].to_csv(out_csv, index = False)
    #print("Done! Output CSV: {}".format(out_csv))

    out_val = out_df[p.mix_idx_col][0]
    return {p.mix_idx_col: out_val}
Exemple #8
0
def intersection_density(fc_project, fc_intersxns, project_type):
    arcpy.AddMessage("calculating intersection density...")

    fl_project = "fl_projline"
    fl_intersxns = "fl_trnstp"

    utils.make_fl_conditional(fc_project, fl_project)
    utils.make_fl_conditional(fc_intersxns, fl_intersxns)

    # analysis area. If project is line or point, then it's a buffer around the line/point.
    # If it's a polygon (e.g. ctype or region), then no buffer and analysis area is that within the input polygon
    if project_type == p.ptype_area_agg:
        fc_buff = fc_project
    else:
        p.intersxn_dens_buff
        fc_buff = r"memory\temp_buff_qmi"
        arcpy.Buffer_analysis(fl_project, fc_buff, p.intersxn_dens_buff)

    fl_buff = "fl_buff"
    utils.make_fl_conditional(fc_buff, fl_buff)

    buff_acres = get_poly_area(fl_buff)

    # get count of transit stops within buffer
    arcpy.SelectLayerByLocation_management(fl_intersxns, "INTERSECT", fl_buff,
                                           0, "NEW_SELECTION")

    intsxn_34 = 0
    col_link_cnt = "LINKS"

    with arcpy.da.SearchCursor(fl_intersxns, [col_link_cnt]) as cur:
        for row in cur:
            if row[0] > 2:
                intsxn_34 += 1

    intersxns_per_acre = intsxn_34 / buff_acres if buff_acres > 0 else 0

    return {"Intersxn_34_per_acre": intersxns_per_acre}
Exemple #9
0
def transit_svc_density(fc_project, fc_trnstops, project_type):

    arcpy.AddMessage("calculating transit service density...")
    fl_project = "fl_projline"
    fl_trnstops = "fl_trnstp"

    utils.make_fl_conditional(fc_project, fl_project)
    utils.make_fl_conditional(fc_trnstops, fl_trnstops)
    # analysis area. If project is line or point, then it's a buffer around the line/point.
    # If it's a polygon (e.g. ctype or region), then no buffer and analysis area is that within the input polygon
    if project_type == p.ptype_area_agg:
        fc_buff = fc_project
    else:
        p.intersxn_dens_buff
        fc_buff = r"memory\temp_buff_qmi"
        arcpy.Buffer_analysis(fl_project, fc_buff, p.trn_buff_dist)

    fl_buff = "fl_buff"
    utils.make_fl_conditional(fc_buff, fl_buff)

    # calculate buffer area
    buff_acres = get_poly_area(fl_buff)

    # get count of transit stops within buffer
    arcpy.SelectLayerByLocation_management(fl_trnstops, "INTERSECT", fl_buff,
                                           0, "NEW_SELECTION")

    transit_veh_events = 0

    with arcpy.da.SearchCursor(fl_trnstops, [p.col_transit_events]) as cur:
        for row in cur:
            vehstops = row[0] if row[0] is not None else 0
            transit_veh_events += vehstops

    trnstops_per_acre = transit_veh_events / buff_acres if buff_acres > 0 else 0

    return {"TrnVehStop_Acre": trnstops_per_acre}
Exemple #10
0
def get_collision_data(fc_project, project_type, fc_colln_pts, project_adt):

    arcpy.AddMessage("Aggregating collision data...")
    fc_model_links = p.model_links_fc()
    
    fl_project = 'proj_fl'
    fl_colln_pts = 'collision_fl'

    utils.make_fl_conditional(fc_project, fl_project)
    utils.make_fl_conditional(fc_colln_pts, fl_colln_pts)

    # if for project segment, get annual VMT for project segment based on user input and segment length
    df_projlen = utils.esri_object_to_df(fl_project, ["SHAPE@LENGTH"])
    proj_len_mi = df_projlen.iloc[0][0] / p.ft2mile  # return project length in miles

    # for aggregate, polygon-based avgs (e.g., community type, whole region), use model for VMT; for
    # project, the VMT will be based on combo of project length and user-entered ADT for project
    # approximate annual project VMT, assuming ADT is reflective of weekdays only, but assumes
    if project_type == p.ptype_area_agg:
        vmt_dict = get_model_link_sums(fc_project, fc_model_links)
        dayvmt = vmt_dict[p.col_dayvmt]
        ann_proj_vmt = dayvmt * 320
        proj_len_mi = get_centerline_miles(fc_project, p.reg_centerline_fc)
    else:
        ann_proj_vmt = project_adt * proj_len_mi * 320

    # get collision totals
    searchdist = 0 if project_type == p.ptype_area_agg else p.colln_searchdist
    arcpy.SelectLayerByLocation_management(fl_colln_pts, 'WITHIN_A_DISTANCE', fl_project, searchdist)
    colln_cols = [p.col_fwytag, p.col_nkilled, p.col_bike_ind, p.col_ped_ind]

    df_collndata = utils.esri_object_to_df(fl_colln_pts, colln_cols)

    # filter so that fwy collisions don't get tagged to non-freeway projects, and vice-versa
    if project_type == p.ptype_fwy:
        df_collndata = df_collndata.loc[df_collndata[p.col_fwytag] == 1]
    elif project_type == p.ptype_area_agg:
        pass  # for aggregating at polygon level, like region or community type, we want all collisions on all roads
    else:
        df_collndata = df_collndata.loc[df_collndata[p.col_fwytag] == 0]

    total_collns = df_collndata.shape[0]
    fatal_collns = df_collndata.loc[df_collndata[p.col_nkilled] > 0].shape[0]
    bikeped_collns = df_collndata.loc[(df_collndata[p.col_bike_ind] == p.ind_val_true)
                                      | (df_collndata[p.col_ped_ind] == p.ind_val_true)].shape[0]
    pct_bikeped_collns = bikeped_collns / total_collns if total_collns > 0 else 0

    bikeped_colln_clmile = bikeped_collns / proj_len_mi

    # collisions per million VMT (MVMT) = avg annual collisions / (modeled daily VMT * 320 days) * 1,000,000
    avg_ann_collisions = total_collns / p.years_of_collndata
    avg_ann_fatalcolln = fatal_collns / p.years_of_collndata

    colln_rate_per_vmt = avg_ann_collisions / ann_proj_vmt * 100000000 if ann_proj_vmt > 0 else 0
    fatalcolln_per_vmt = avg_ann_fatalcolln / ann_proj_vmt * 100000000 if ann_proj_vmt > 0 else 0
    pct_fatal_collns = avg_ann_fatalcolln / avg_ann_collisions if ann_proj_vmt > 0 else 0

    out_dict = {"TOT_COLLISNS": total_collns, "TOT_COLLISNS_PER_100MVMT": colln_rate_per_vmt,
                "FATAL_COLLISNS": fatal_collns, "FATAL_COLLISNS_PER_100MVMT": fatalcolln_per_vmt,
                "PCT_FATAL_COLLISNS": pct_fatal_collns, "BIKEPED_COLLISNS": bikeped_collns, 
                "BIKEPED_COLLISNS_PER_CLMILE": bikeped_colln_clmile, "PCT_BIKEPED_COLLISNS": pct_bikeped_collns}

    return out_dict
def get_lutype_acreage(fc_project, projtyp, fc_poly_parcels, lutype):
    arcpy.AddMessage("Estimating {} acres near project...".format(lutype))

    fl_parcels = "fl_parcel"
    fl_project = "fl_project"

    for fc, fl in {
            fc_project: fl_project,
            fc_poly_parcels: fl_parcels
    }.items():
        utils.make_fl_conditional(fc, fl)
        # if arcpy.Exists(fl):
        #     arcpy.Delete_management(fl)
        #     arcpy.MakeFeatureLayer_management(fc, fl)
        # else:
        #     arcpy.MakeFeatureLayer_management(fc, fl)

    # create temporary buffer IF the input project fc is a line. If it's a polygon, then don't make separate buffer
    if projtyp == p.ptype_area_agg:
        fc_buff = fc_project
    else:
        buff_dist = p.ilut_sum_buffdist  # distance in feet
        fc_buff = r"memory\temp_buff_qmi"
        arcpy.Buffer_analysis(fl_project, fc_buff, buff_dist)

    fl_buff = "fl_buff"
    arcpy.MakeFeatureLayer_management(fc_buff, fl_buff)
    """
    # calculate buffer area, inclusive of water bodies and rights of way
    buff_area_ft2 = 0
    with arcpy.da.SearchCursor(fl_buff, ["SHAPE@AREA"]) as cur:
        for row in cur:
            buff_area_ft2 += row[0]
    buff_acre = buff_area_ft2 / p.ft2acre  # convert from ft2 to acres. may need to adjust for projection-related issues. See PPA1 for more info
    """

    # create intersect layer of buffer with parcels of selected LUTYPE
    fc_intersect = r"memory\temp_intersect"
    arcpy.Intersect_analysis([fl_buff, fl_parcels], fc_intersect, "ALL", "",
                             "INPUT")

    # calculate total area on parcels within buffer (excluding water and rights of way)
    fl_intersect = "fl_intersect"
    arcpy.MakeFeatureLayer_management(fc_intersect, fl_intersect)

    # get total acres within intersect polygons
    pclarea_inbuff_ft2 = 0  # total on-parcel acres within buffer
    lutype_intersect_ft2 = 0  # total acres of specified land use type within buffer
    with arcpy.da.SearchCursor(fl_intersect,
                               ["SHAPE@AREA", p.col_lutype]) as cur:
        for row in cur:
            pclarea_inbuff_ft2 += row[0]
            if row[1] == lutype:
                lutype_intersect_ft2 += row[0]

    # get share of on-parcel land within buffer that is of specified land use type
    pct_lutype = lutype_intersect_ft2 / pclarea_inbuff_ft2 if pclarea_inbuff_ft2 > 0 else 0

    # convert to acres
    buff_acre = pclarea_inbuff_ft2 / p.ft2acre
    lutype_intersect_acres = lutype_intersect_ft2 / p.ft2acre

    [
        arcpy.Delete_management(item) for item in
        [fl_parcels, fl_project, fl_buff, fc_intersect, fl_intersect]
    ]

    # delete temp buffer feature class only if it's not the same as the project FC
    if fc_buff != fc_project:
        arcpy.Delete_management(fc_buff)

    return {
        'total_net_pcl_acres': buff_acre,
        'net_{}_acres'.format(lutype): lutype_intersect_acres,
        'pct_{}_inbuff'.format(lutype): pct_lutype
    }