def nhd_merge(gdb_list, example_feature_class_name, out_fc, selection = ''):
    arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(102039) # USA_Contiguous_Albers_Equal_Area_Conic_USGS_version
    arcpy.env.workspace = 'in_memory'

    gdb_list = [os.path.join(gdb, os.path.basename(example_feature_class_name)) for gdb in gdb_list]
    gdb0 = gdb_list.pop(0)
    desc = arcpy.Describe(gdb0)
    cu.multi_msg('Merging all features together...')
    arcpy.CopyFeatures_management(gdb0, 'temp_merged')
    cu.lengthen_field('temp_merged', 'Permanent_Identifier', 255)
    cu.merge_many(gdb_list, 'in_memory/the_rest_merged')
    arcpy.Append_management('in_memory/the_rest_merged', 'temp_merged', 'NO_TEST')
    # use in_memory explicitly here because i haven't figured out how to pass arcgis environments to my functions :(
    fc_temp = 'in_memory/temp_merged'
    fcount1 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('Before selection and cleaning, feature count is {0}'.format(fcount1))
    if selection:
        cu.multi_msg('Selecting features...')
        arcpy.Select_analysis('temp_merged', 'in_memory/merged_select', selection)
        fc_temp = 'in_memory/merged_select'

    fcount2 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('After selection and before cleaning, feature count is {0}'.format(fcount2))

    arcpy.CopyFeatures_management(fc_temp, out_fc)
Beispiel #2
0
def nhd_merge(gdb_list, example_feature_class_name, out_fc, selection=''):
    arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(
        102039)  # USA_Contiguous_Albers_Equal_Area_Conic_USGS_version
    arcpy.env.workspace = 'in_memory'

    gdb_list = [
        os.path.join(gdb, os.path.basename(example_feature_class_name))
        for gdb in gdb_list
    ]
    gdb0 = gdb_list.pop(0)
    desc = arcpy.Describe(gdb0)
    cu.multi_msg('Merging all features together...')
    arcpy.CopyFeatures_management(gdb0, 'temp_merged')
    cu.lengthen_field('temp_merged', 'Permanent_Identifier', 255)
    cu.merge_many(gdb_list, 'in_memory/the_rest_merged')
    arcpy.Append_management('in_memory/the_rest_merged', 'temp_merged',
                            'NO_TEST')
    # use in_memory explicitly here because i haven't figured out how to pass arcgis environments to my functions :(
    fc_temp = 'in_memory/temp_merged'
    fcount1 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg(
        'Before selection and cleaning, feature count is {0}'.format(fcount1))
    if selection:
        cu.multi_msg('Selecting features...')
        arcpy.Select_analysis('temp_merged', 'in_memory/merged_select',
                              selection)
        fc_temp = 'in_memory/merged_select'

    fcount2 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg(
        'After selection and before cleaning, feature count is {0}'.format(
            fcount2))

    arcpy.CopyFeatures_management(fc_temp, out_fc)
Beispiel #3
0
def nhd_merge(gdb_list, example_feature_class_name, out_fc, selection = ''):
    arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(102039) # USA_Contiguous_Albers_Equal_Area_Conic_USGS_version
    arcpy.env.workspace = 'in_memory'

    gdb_list = [os.path.join(gdb, os.path.basename(example_feature_class_name)) for gdb in gdb_list]
    gdb0 = gdb_list.pop(0)
    desc = arcpy.Describe(gdb0)
    cu.multi_msg('Merging all features together...')
    arcpy.CopyFeatures_management(gdb0, 'temp_merged')
    cu.lengthen_field('temp_merged', 'Permanent_Identifier', 255)
    cu.merge_many(gdb_list, 'in_memory/the_rest_merged')
    arcpy.Append_management('in_memory/the_rest_merged', 'temp_merged', 'NO_TEST')
    # use in_memory explicitly here because i haven't figured out how to pass arcgis environments to my functions :(
    fc_temp = 'in_memory/temp_merged'
    fcount1 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('Before selection and cleaning, feature count is {0}'.format(fcount1))
    if selection:
        cu.multi_msg('Selecting features...')
        arcpy.Select_analysis('temp_merged', 'in_memory/merged_select', selection)
        fc_temp = 'in_memory/merged_select'

    fcount2 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('After selection and before cleaning, feature count is {0}'.format(fcount2))

    cu.multi_msg('Removing complete duplicates...')
    fc_temp_fields = [f.name for f in arcpy.ListFields(fc_temp) if f.type <> 'OID']
    arcpy.DeleteIdentical_management(fc_temp, fields = [f.name for f in arcpy.ListFields(fc_temp) if f.type <> 'OID'])

    fcount3 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('After removing complete duplicates only, feature count is {0}'.format(fcount3))

    cu.multi_msg('Removing remaining ID duplicates...')
    assumptions.remove_nhd_duplicates(fc_temp, 'Permanent_Identifier', 'in_memory/no_id_dupes')

    fcount4 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('After removing all ID duplicates, feature count is {0}'.format(fcount4))

    if desc.shapeType == 'Polygon':
        cu.multi_msg('Removing geographic duplicates and substantially overlapping features...')
        assumptions.remove_geographic_doubles('in_memory/no_id_dupes', out_fc, 'Permanent_Identifier', percent_overlap_allowed = 10)
    cu.multi_msg('nhd_merge complete.')

    fcount5 = int(arcpy.GetCount_management(fc_temp).getOutput(0))
    cu.multi_msg('Final feature count is {0}'.format(fcount5))
def merge_watersheds(watershed_fcs_list, nhd_gdb, out_fc):
    """Merges watershed fcs that are at HU8 level to subregion level. Checks
    whether there are as many feature classes being merged as there are HU8s
    in the subregion and issues an error, warning, or okay message accordingly."""
    arcpy.env.workspace = 'in_memory'
    # get this hu4 boundary
    huc4_code = re.search('\d{4}', os.path.basename(nhd_gdb)).group()
    wbd_hu4 = os.path.join(nhd_gdb, "WBD_HU4")
    field_name = (arcpy.ListFields(wbd_hu4, "HU*4"))[0].name
    whereClause4 = """{0} = '{1}'""".format(
        arcpy.AddFieldDelimiters(nhd_gdb, field_name), huc4_code)
    arcpy.Select_analysis(wbd_hu4, "hu4", whereClause4)

    hu8 = os.path.join(nhd_gdb, 'WBD_HU8')
    field_name_8 = (arcpy.ListFields(hu8, "HU*8"))[0].name
    arcpy.MakeFeatureLayer_management(hu8, 'HU8_lyr')
    whereClause = """"{0}" LIKE '{1}%'""".format(field_name_8, huc4_code)
    arcpy.SelectLayerByAttribute_management('HU8_lyr', 'NEW_SELECTION',
                                            whereClause)
    arcpy.CopyFeatures_management('HU8_lyr', 'HU8_selected')
    hu8s_selected = [
        row[0] for row in arcpy.da.SearchCursor('HU8_selected', field_name_8)
    ]

    if len(hu8s_selected) < len(watershed_fcs_list):
        arcpy.AddError(
            "Number of feature classes in input list exceeds number of HU8s in subregion. Check list and try again."
        )
    elif len(hu8s_selected) > len(watershed_fcs_list):
        arcpy.AddWarning(
            "Number of features classes in input list is fewer than number of HU8s in subregion. Tool will proceed. Check that result matches your expectations."
        )
    elif len(hu8s_selected) == len(watershed_fcs_list):
        arcpy.AddMessage(
            "There are as many inputs as there are HU8s in the subregion.")

    # This typically works out faster than merging when there are LOTS of features
    first_fc = watershed_fcs_list.pop(0)
    arcpy.CopyFeatures_management(first_fc, out_fc)
    cu.lengthen_field(out_fc, 'Permanent_Identifier', 255)
    for fc in watershed_fcs_list:
        arcpy.Append_management(watershed_fcs_list, out_fc, 'NO_TEST')
def nhd_merge(gdb_list, example_feature_class_name, out_fc, selection = ''):
    arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(102039)
    arcpy.env.workspace = 'in_memory'

    gdb_list = [os.path.join(gdb, os.path.basename(example_feature_class_name)) for gdb in gdb_list]
    gdb0 = gdb_list.pop(0)
    desc = arcpy.Describe(gdb0)
    cu.multi_msg('Merging all features together...')
    arcpy.CopyFeatures_management(gdb0, 'temp_merged')
    cu.lengthen_field('temp_merged', 'Permanent_Identifier', 255)
    arcpy.Append_management(gdb_list, 'temp_merged', 'NO_TEST')
    # use in_memory explicitly here because i haven't figured out how to pass arcgis environments to my functions :(
    if selection:
        cu.multi_msg('Selecting features...')
        arcpy.Select_analysis('temp_merged', 'in_memory/merged_select', selection)
    cu.multi_msg('Removing ID duplicates...')
    assumptions.remove_nhd_duplicates('in_memory/merged_select', 'Permanent_Identifier', 'in_memory/no_id_dupes')

    if desc.shapeType == 'Polygon':
        cu.multi_msg('Removing geographic duplicates and substantially overlapping features...')
        assumptions.remove_geographic_doubles('in_memory/no_id_dupes', out_fc, 'Permanent_Identifier', percent_overlap_allowed = 10)
    cu.multi_msg('nhd_merge complete.')
def aggregate_watersheds(watersheds_fc,
                         nhd_gdb,
                         eligible_lakes,
                         output_fc,
                         mode=['interlake', 'cumulative']):
    """Creates a feature class with all the aggregated upstream watersheds for all
    eligible lakes (>4ha and certain FCodes) in this subregion."""
    arcpy.env.workspace = 'in_memory'

    # names
    huc4_code = re.search('\d{4}', os.path.basename(nhd_gdb)).group()
    nhd_waterbody = os.path.join(nhd_gdb, 'NHDWaterbody')
    hydro_net_junctions = os.path.join(nhd_gdb, 'Hydrography',
                                       'HYDRO_NET_Junctions')
    hydro_net = os.path.join(nhd_gdb, 'Hydrography', 'HYDRO_NET')

    # get this hu4
    wbd_hu4 = os.path.join(nhd_gdb, "WBD_HU4")
    field_name = (arcpy.ListFields(wbd_hu4, "HU*4"))[0].name
    whereClause4 = """{0} = '{1}'""".format(
        arcpy.AddFieldDelimiters(nhd_gdb, field_name), huc4_code)
    arcpy.Select_analysis(wbd_hu4, "hu4", whereClause4)

    # make layers for upcoming spatial selections
    # and fcs in memory
    arcpy.MakeFeatureLayer_management(hydro_net_junctions, "junctions")
    arcpy.MakeFeatureLayer_management(watersheds_fc, 'watersheds')

    all_lakes = eligible_lakes
    arcpy.MakeFeatureLayer_management(all_lakes, "all_lakes_lyr")
    ##    arcpy.SelectLayerByLocation_management("all_lakes_lyr", "INTERSECT", "hu8")
    arcpy.CopyFeatures_management("all_lakes_lyr", 'eligible_lakes')

    # ten ha lakes and junctions
    if mode == 'interlake':
        tenha_where_clause = """"AreaSqKm" >= .1"""
        arcpy.Select_analysis("eligible_lakes", 'tenha_lakes',
                              tenha_where_clause)
        arcpy.MakeFeatureLayer_management('tenha_lakes', 'tenha_lakes_lyr')
        arcpy.SelectLayerByLocation_management('junctions',
                                               'INTERSECT',
                                               'tenha_lakes',
                                               search_distance="1 Meters")
        arcpy.CopyFeatures_management('junctions', 'tenha_junctions')
        arcpy.MakeFeatureLayer_management('tenha_junctions',
                                          'tenha_junctions_lyr')
    # for each lake, calculate its interlake watershed in the upcoming block
    prog_count = int(arcpy.GetCount_management('eligible_lakes').getOutput(0))
    counter = 0

    with arcpy.da.SearchCursor('eligible_lakes',
                               ["Permanent_Identifier"]) as cursor:
        for row in cursor:
            counter += 1
            if counter % 50 == 0:
                print("{0} out of {1} lakes completed.".format(
                    counter, prog_count))
            id = row[0]
            where_clause = """"{0}" = '{1}'""".format("Permanent_Identifier",
                                                      id)
            arcpy.MakeFeatureLayer_management('eligible_lakes', "this_lake",
                                              where_clause)
            arcpy.SelectLayerByLocation_management("junctions",
                                                   "INTERSECT",
                                                   "this_lake",
                                                   search_distance="1 Meters")
            count_jxns = int(
                arcpy.GetCount_management('junctions').getOutput(0))
            if count_jxns == 0:
                arcpy.SelectLayerByLocation_management('watersheds',
                                                       'CONTAINS', 'this_lake')
            else:
                arcpy.CopyFeatures_management("junctions", 'this_lake_jxns')
                if mode == 'interlake':
                    arcpy.SelectLayerByLocation_management(
                        'tenha_junctions_lyr', 'ARE_IDENTICAL_TO',
                        'this_lake_jxns')
                    arcpy.SelectLayerByAttribute_management(
                        'tenha_junctions_lyr', 'SWITCH_SELECTION')
                    arcpy.CopyFeatures_management('tenha_junctions_lyr',
                                                  'other_tenha_junctions')
                    arcpy.SelectLayerByLocation_management(
                        'tenha_lakes_lyr',
                        'INTERSECT',
                        'other_tenha_junctions',
                        search_distance='1 Meters')
                    arcpy.TraceGeometricNetwork_management(
                        hydro_net,
                        "upstream",
                        'this_lake_jxns',
                        "TRACE_UPSTREAM",
                        in_barriers='other_tenha_junctions')
                elif mode == 'cumulative':
                    arcpy.TraceGeometricNetwork_management(
                        hydro_net, "upstream", 'this_lake_jxns',
                        "TRACE_UPSTREAM")
                arcpy.SelectLayerByLocation_management("watersheds",
                                                       "CONTAINS",
                                                       "upstream/NHDFlowline")
                arcpy.SelectLayerByLocation_management(
                    "watersheds",
                    'CROSSED_BY_THE_OUTLINE_OF',
                    'upstream/NHDFLowline',
                    selection_type="ADD_TO_SELECTION")
                watersheds_count = int(
                    arcpy.GetCount_management("watersheds").getOutput(0))
                if watersheds_count == 0:
                    arcpy.SelectLayerByLocation_management(
                        'watersheds', 'CONTAINS', 'this_lake')

            # Sometimes when the trace stops at 10-ha lake, that shed(s)
            # gets selected. Remove them with the tenha_lakes_lyr
            # that already has only OTHER lakes selected
            # using other_tenha_junctions causes some stuff to be picked up
            # that shouldn't be when junctions are right on boundaries
            if mode == 'interlake':
                arcpy.SelectLayerByLocation_management(
                    "watersheds",
                    "CONTAINS",
                    "tenha_lakes_lyr",
                    selection_type="REMOVE_FROM_SELECTION")
            arcpy.Dissolve_management("watersheds", "this_watershed")
            arcpy.AddField_management("this_watershed",
                                      'Permanent_Identifier',
                                      'TEXT',
                                      field_length=255)
            arcpy.CalculateField_management("this_watershed",
                                            "Permanent_Identifier",
                                            """'{}'""".format(id), "PYTHON")
            arcpy.Erase_analysis('this_watershed', 'this_lake',
                                 'lakeless_watershed')

            if not arcpy.Exists("output_fc"):
                arcpy.CopyFeatures_management('lakeless_watershed',
                                              "output_fc")
                # to avoid append mismatch due to permanent_identifier
                cu.lengthen_field("output_fc", 'Permanent_Identifier', 255)
            else:
                arcpy.Append_management('lakeless_watershed', "output_fc",
                                        'NO_TEST')
            for item in [
                    'this_lake', 'this_watershed', 'this_lake_jxns',
                    'upstream', 'lakeless_watershed', 'other_tenha_junctions'
            ]:
                try:
                    arcpy.Delete_management(item)
                except:
                    continue

    arcpy.EliminatePolygonPart_management("output_fc", "output_hole_remove",
                                          "AREA", "3.9 Hectares", "0",
                                          "CONTAINED_ONLY")
    arcpy.Clip_analysis("output_hole_remove", "hu4", output_fc)
    arcpy.Delete_management('output_fc')
    arcpy.ResetEnvironments()
def aggregate_watersheds(watersheds_fc, nhd_gdb, eligible_lakes,
                            output_fc, mode = ['interlake', 'cumulative']):
    """Creates a feature class with all the aggregated upstream watersheds for all
    eligible lakes (>4ha and certain FCodes) in this subregion."""
    arcpy.env.workspace = 'in_memory'

    # names
    huc4_code = re.search('\d{4}', os.path.basename(nhd_gdb)).group()
    nhd_waterbody = os.path.join(nhd_gdb, 'NHDWaterbody')
    hydro_net_junctions = os.path.join(nhd_gdb, 'Hydrography', 'HYDRO_NET_Junctions')
    hydro_net = os.path.join(nhd_gdb, 'Hydrography', 'HYDRO_NET')

    # get this hu4
    wbd_hu4 = os.path.join(nhd_gdb, "WBD_HU4")
    field_name = (arcpy.ListFields(wbd_hu4, "HU*4"))[0].name
    whereClause4 =  """{0} = '{1}'""".format(arcpy.AddFieldDelimiters(nhd_gdb, field_name), huc4_code)
    arcpy.Select_analysis(wbd_hu4, "hu4", whereClause4)

    # make layers for upcoming spatial selections
    # and fcs in memory
    arcpy.MakeFeatureLayer_management(hydro_net_junctions, "junctions")
    arcpy.MakeFeatureLayer_management(watersheds_fc, 'watersheds')

    all_lakes = eligible_lakes
    arcpy.MakeFeatureLayer_management(all_lakes, "all_lakes_lyr")
##    arcpy.SelectLayerByLocation_management("all_lakes_lyr", "INTERSECT", "hu8")
    arcpy.CopyFeatures_management("all_lakes_lyr", 'eligible_lakes')

    # ten ha lakes and junctions
    if mode == 'interlake':
        tenha_where_clause = """"AreaSqKm" >= .1"""
        arcpy.Select_analysis("eligible_lakes", 'tenha_lakes', tenha_where_clause)
        arcpy.MakeFeatureLayer_management('tenha_lakes', 'tenha_lakes_lyr')
        arcpy.SelectLayerByLocation_management('junctions', 'INTERSECT', 'tenha_lakes', search_distance = "1 Meters")
        arcpy.CopyFeatures_management('junctions', 'tenha_junctions')
        arcpy.MakeFeatureLayer_management('tenha_junctions', 'tenha_junctions_lyr')
    # for each lake, calculate its interlake watershed in the upcoming block
    prog_count = int(arcpy.GetCount_management('eligible_lakes').getOutput(0))
    counter = 0

    with arcpy.da.SearchCursor('eligible_lakes', ["Permanent_Identifier"]) as cursor:
        for row in cursor:
            counter += 1
            if counter % 50 == 0:
                print("{0} out of {1} lakes completed.".format(counter, prog_count))
            id = row[0]
            where_clause = """"{0}" = '{1}'""".format("Permanent_Identifier", id)
            arcpy.MakeFeatureLayer_management('eligible_lakes', "this_lake",
                                                where_clause)
            arcpy.SelectLayerByLocation_management("junctions", "INTERSECT",
                                            "this_lake", search_distance = "1 Meters")
            count_jxns = int(arcpy.GetCount_management('junctions').getOutput(0))
            if count_jxns == 0:
                arcpy.SelectLayerByLocation_management('watersheds', 'CONTAINS', 'this_lake')
            else:
                arcpy.CopyFeatures_management("junctions", 'this_lake_jxns')
                if mode == 'interlake':
                    arcpy.SelectLayerByLocation_management('tenha_junctions_lyr', 'ARE_IDENTICAL_TO', 'this_lake_jxns')
                    arcpy.SelectLayerByAttribute_management('tenha_junctions_lyr', 'SWITCH_SELECTION')
                    arcpy.CopyFeatures_management('tenha_junctions_lyr', 'other_tenha_junctions')
                    arcpy.SelectLayerByLocation_management('tenha_lakes_lyr', 'INTERSECT', 'other_tenha_junctions', search_distance = '1 Meters')
                    arcpy.TraceGeometricNetwork_management(hydro_net, "upstream",
                                    'this_lake_jxns', "TRACE_UPSTREAM", in_barriers = 'other_tenha_junctions')
                elif mode == 'cumulative':
                    arcpy.TraceGeometricNetwork_management(hydro_net, "upstream",
                                    'this_lake_jxns', "TRACE_UPSTREAM")
                arcpy.SelectLayerByLocation_management("watersheds", "CONTAINS",
                                    "upstream/NHDFlowline")
                arcpy.SelectLayerByLocation_management("watersheds", 'CROSSED_BY_THE_OUTLINE_OF', 'upstream/NHDFLowline', selection_type = "ADD_TO_SELECTION")
                watersheds_count = int(arcpy.GetCount_management("watersheds").getOutput(0))
                if watersheds_count == 0:
                    arcpy.SelectLayerByLocation_management('watersheds', 'CONTAINS', 'this_lake')

            # Sometimes when the trace stops at 10-ha lake, that shed(s)
            # gets selected. Remove them with the tenha_lakes_lyr
            # that already has only OTHER lakes selected
            # using other_tenha_junctions causes some stuff to be picked up
            # that shouldn't be when junctions are right on boundaries
            if mode == 'interlake':
                arcpy.SelectLayerByLocation_management("watersheds", "CONTAINS", "tenha_lakes_lyr", selection_type = "REMOVE_FROM_SELECTION")
            arcpy.Dissolve_management("watersheds", "this_watershed")
            arcpy.AddField_management("this_watershed", 'Permanent_Identifier', 'TEXT', field_length = 255)
            arcpy.CalculateField_management("this_watershed", "Permanent_Identifier", """'{}'""".format(id), "PYTHON")
            arcpy.Erase_analysis('this_watershed', 'this_lake',
                                'lakeless_watershed')

            if not arcpy.Exists("output_fc"):
                arcpy.CopyFeatures_management('lakeless_watershed', "output_fc")
                # to avoid append mismatch due to permanent_identifier
                cu.lengthen_field("output_fc", 'Permanent_Identifier', 255)
            else:
                arcpy.Append_management('lakeless_watershed', "output_fc", 'NO_TEST')
            for item in ['this_lake', 'this_watershed', 'this_lake_jxns', 'upstream', 'lakeless_watershed', 'other_tenha_junctions']:
                try:
                    arcpy.Delete_management(item)
                except:
                    continue

    arcpy.EliminatePolygonPart_management("output_fc", "output_hole_remove", "AREA", "3.9 Hectares", "0", "CONTAINED_ONLY")
    arcpy.Clip_analysis("output_hole_remove", "hu4", output_fc)
    arcpy.Delete_management('output_fc')
    arcpy.ResetEnvironments()