# Python scripting for making rings from the city center

Problem description:

I have two layers: 1) [Polygon] city blocks, and 2) [Point] the city center. The City blocks layer has 110,681 records. And The city center layer has just one record because there is only one city center in this city.

``````arcpy.SelectLayerByLocation_management("CityBlocks","WITHIN_A_DISTANCE","CityCenter","1 Kilometers","ADD_TO_SELECTION")
``````

The code above selects census blocks that are 1 kilometer away from the city center in ArcMap.

Question:

Now, I have to add a field called "ring" onto the city blocks layer. And, I have to write a code that does:

``````ring = 1 if city blocks are 1km away from the city center.
ring = 2 if city blocks are in the ring of 1km to 2km from the city center.
ring = 3 if city blocks are in the ring of 2km to 3km from the city center.
...
It stops if there are no city blocks in the ring of (N-1)km to (N)km from the center.
``````

How do we write a code for that selection process using arcpy?

• I think you should focus this question on ArcGIS for Desktop and ask separate questions for PySal and QGIS if they are your preferred software.
– PolyGeo
Oct 30, 2013 at 12:58
• Do you want a higher ring value to outweigh lower ones or vice versa? Because if you have square city blocks and circle buffers from the city center, some blocks will have multiple rings going through them. Oct 30, 2013 at 13:23
• @Baltok. Right. We can pick blocks completely within the 1st circle. Then, the 1st donut takes the blocks that have the boundary of the 1st circle and the blocks completely within the donut. And this applies to the remaining rings. Oct 30, 2013 at 13:41
• Huh? I'm talking about what final value do you want placed in your "ring" field. E.g., if a city block falls within ring 1 & ring 2, what value should get priority, or overwrite the other? Oct 30, 2013 at 13:48
• I think it's ring 2..?? I think I don't fully understand what you're talking about. Oct 30, 2013 at 14:37

Something like this should work for what you are trying to get at or get you close at least. A few things to keep in mind:

• This expects the `ring` field on CityBlocks to a numeric type (long, short, float, etc), and it's empty (NULL).
• This won't find the blocks that are completely within N km. It looks for blocks that are at least partially within N km.
• If a block is only partially within N km, ring will be set to N, not N+1
• I set this up for layers that are in a FGDB. You'll need to change the select by attribute syntax slightly if you have shapefiles.

``````ring = 1
while(True):
# Select all of the blocks within <ring> km
arcpy.SelectLayerByLocation_management("CityBlocks","WITHIN_A_DISTANCE",
"CityCenter",
"{0} Kilometers".format(ring),
"NEW_SELECTION")
# remove the blocks that already have a value for ring
arcpy.SelectLayerByAttribute_management("CityBlocks","REMOVE_FROM_SELECTION",
'"ring" IS NOT NULL')
# How many blocks are selcted?
count = int(arcpy.GetCount_management("CityBlocks").getOutput(0))
if count == 0: break # Nothing selected, so exit the while loop
# Set the value of ring (only on selected records)
arcpy.CalculateField_management("CityBlocks","ring",str(ring),
"PYTHON_9.3")
ring += 1
``````
• It does not do the job so far. I think the first part of the code does not produce the "ring" variable, so '"ring" IS NOT NULL' produces an error. I will continue to test it. Oct 31, 2013 at 18:59
• Another thing: I had to MakeFeatureLayer_management(CityBlocks, "CityBlocks_layer") first. Then, the SelectLayerByLocation_management("CityBlocks_layer", ...) works. Oct 31, 2013 at 19:01
• @BillTP Exactly, in the bullet list I said that I expected the ring field to already exist. If it doesn't already you can add it easily with `arcpy.AddField_management`. Also, you are correct in that `SelectLayerByLocation` requires a feature layer instead of a feature class. Oct 31, 2013 at 19:26