This question is back to basics; I looked around for an answer or a clue and I can't find what I'm looking for. I'm stuck.
I've got 3 variables with assigned string values (shapefile paths) and I am running them through a loop to check that their projected coordinate systems (PCS) are the same as my DEM's PCS. I want the code to check if they're the same, and if not, I want to project the file and reassign the projected file path to the original variable.
This is my code:
print("Verifying that coordinate systems are the same...") InSHP = [outline, DA, soil] DEMSR = arcpy.Describe(DEM).spatialReference.PCSCode for i, l in enumerate(InSHP): print InSHP sr = arcpy.Describe(l).spatialReference.PCScode if sr != DEMSR: l = arcpy.Project_management(l, l[:-4] + "PRJ.shp", DEMSR) InSHP = l print InSHP print outline
print InSHP produces the modified file path but print outline does not.
So, l = the projected shapefile but the l doesn't automatically connect the original variable name (outline) to the new path. I was initially expecting the program to automatically deduce that l = new path = outline, which was kind of stupid of me to think in retrospect. Now I explicitly know that l only refers to the entry in the list and is in no way connected to the original variable aside from having the same starting values. Is there a way to automate this sort of assignment or am I doomed to adding the following at the end of my code?
outline = InSHP[0] DA = InSHP[1] soil = InSHP[2]
I guess it's not a big deal because there's only 3 of them but what if I need to check more inputs?
As a side question, this loop tells me that my soils file does not have a PCS, but when I look at the file properties in GIS or Catalog, it does have a PCS. Any idea why that's happening?
EDIT: Ugh. Adding those next 3 lines at the end didn't actually accomplish what I wanted it to accomplish. I'm so used to working with cursors and GIS tables that my plain list skills are lacking. :S
EDIT 2: Okay I got my list to update using the enumerate function and I updated my code accordingly. My original question(s) still stand, though. Is there a way to assign the new values to the original variables names without having to explicitly type the variable names again? I'm starting to think there isn't but I already posted this and I'm going to keep it here in case any other novice has this same problem.
You are assigning the projected shapefile to l, this doesn't modify the original variable in your list. When you assign a variable to another variable you are actually making a copy of the original. Somewhere in your code you are assigning a path name to outline. You then create a list that contains variables. You run that list through a for loop that takes the contents of that list one at a time and makes a copy of its contents in l. Changing l doesn't change the original variable. In fact if you change InSHP[0], it won't change the original contents in the outline variable.
>>> a = "This" >>> b = "That" >>> c = "The Other" >>> these = [a, b, c] >>> print these ['This', 'That', 'The Other'] >>> these[0] = "Now This" >>> print these ['Now This', 'That', 'The Other'] >>> print a This >>> for x in range(0, 3): print x 0 1 2 >>> print x 2
It might be better to make a for loop like:
for x in range(0, len(InSHP)): sr = arcpy.Describe(InShP).spatialReference.PCScode print(InSHP, sr) if sr != DEMSR: InSHP= arcpy.Project_management(InSHP print InSHP[0], InSHP [:-4] + "PRJ.shp", DEMSR)
Is that code you posted preferable to my current code using enumerate? Your code still requires me to update the variables manually outside of the loop, correct?
I'm sure this is do-able but it's a little difficult to make a recommendation without seeing your whole code. In particular, it would be useful to see the original definitions for your three variables and a little more information about how you intend to use them later in the script. (One approach may be to have "before" and "after" variables, or something like that.)
I would be careful about trying to re-assign l while inside that loop (and in any case, just working off the top of my head, I'm not sure Project_management returns a value you can or would want to use that way anyway, though I'd be grateful to stand corrected on that).
These are my original inputs:
outline = r"K:\GradWork\GIS\CollegePark\CP_outline.shp" DA = r"K:\GradWork\GIS\CollegePark\CPDrainage.shp" DAID = "Id" # field in DA shapefile where unique DA values exist soil = r"C:\Users\Rachael Johnson\Documents\GradWork\Project Files\BMPGIS\soils\VB_Soils.shp" WTin = r"K:\GradWork\GIS\CollegePark\CPGW_adj1" DEMin = r"K:\GradWork\GIS\CollegePark\cpelev" MapLoc = r"K:\GradWork\GIS\CollegePark\CP.mxd" WT = arcpy.Raster(WTin) DEM = arcpy.Raster(DEMin)
My code uses these inputs in the context of other arcpy functions to create new variables or set environments. The outline variable, for example, is used here and then isn't used again:
### _____________SET PROCESSING EXTENTS____________ ### # Set cell size description = arcpy.Describe(DEM) cellsize = description.children[0].meanCellHeight print("Setting cell size to DEM cell size: " + str(cellsize) + " ft...") arcpy.env.cellSize = cellsize # Create buffer around outline to use as mask # Buffer distance is in feet print("Creating an environment mask from the site outline shapefile...") maskshp = arcpy.Buffer_analysis(outline, ScratchPath + r"\outline_buff", "50 Feet", "", "", "ALL",) # Convert buffer to raster mask = arcpy.Raster(arcpy.PolygonToRaster_conversion(maskshp, "Id", ScratchPath + r"\rastermask")) mask.save(ScratchPath + r"\rastermask") # Set raster mask and snap raster print("Setting raster mask and snap raster for project...") arcpy.env.mask = mask arcpy.env.snapRaster = mask arcpy.env.extent = mask.extent
Here's an example of using one of the inputs to create a new variable and how that new variable is later transformed.
# Convert soils shapefile to raster and assign integer values to HSG. # A=1, B=2, C=3, 4=D and dual groups A/D=14, B/D=24, C/D=34 # "---" is treated as a D soil print("Converting dual group soils to single groups...") SoilUnclass = arcpy.PolygonToRaster_conversion(soil, "HSG", ScratchPath + r"\SoilUnclass", "MAXIMUM_COMBINED_AREA") SoilClass = arcpy.sa.Reclassify(SoilUnclass, "HSG", arcpy.sa.RemapValue([["A", 1], ["B", 2], ["C", 3], ["D", 4], ["A/D", 14], ["B/D", 24], ["C/D", 34], ["---", 4]]), "NODATA") SoilClass.save(ScratchPath + r"\HSGraster")
Project_management does return a variable that I can use in that way; with most of these arcpy functions, setting a variable to them and then calling the variable prints the file path of the resulting shapefile or grid. So, in the context of the above code, "print SoilClass" returns the path "K:\GradWork\GIS\CollegePark\CP\scratch\HSGraster".
Would this kind of construct be useful?
my_layers = [ \ ['outline','K:\GradWork\GIS\CollegePark\CP_outline.shp'],\ ['DA','K:\GradWork\GIS\CollegePark\CPDrainage.shp'],\ ['soil','C:\Users\Rachael\VB_Soils.shp']\ ] for layer in my_layers: print 'debug 1 key: ' + layer[0] + ' value: ' + layer[1] # this is just an arbitrary test; you might test for PCS equivalency here if layer[1] == 'C:\Users\Rachael\VB_Soils.shp': layer[1] = 'C:\Users\Rachel\New_File_Name.shp' print 'debug 2 key: ' + layer[0] + ' value: ' + layer[1] for resulting_layer in my_layers: print 'debug 3 key: ' + resulting_layer[0] + ' value: ' + resulting_layer[1]
Output:
debug 1 key: outline value: K:\GradWork\GIS\CollegePark\CP_outline.shp debug 2 key: outline value: K:\GradWork\GIS\CollegePark\CP_outline.shp debug 1 key: DA value: K:\GradWork\GIS\CollegePark\CPDrainage.shp debug 2 key: DA value: K:\GradWork\GIS\CollegePark\CPDrainage.shp debug 1 key: soil value: C:\Users\Rachael\VB_Soils.shp debug 2 key: soil value: C:\Users\Rachel\New_File_Name.shp debug 3 key: outline value: K:\GradWork\GIS\CollegePark\CP_outline.shp debug 3 key: DA value: K:\GradWork\GIS\CollegePark\CPDrainage.shp debug 3 key: soil value: C:\Users\Rachel\New_File_Name.shp
You could use a dict instead of a list
print("Verifying that coordinate systems are the same...") InSHP = {'outline':outline, 'DA':DA, 'soil':soil} DEMSR = arcpy.Describe(DEM).spatialReference.PCSCode for l in InSHP: print l, InSHPsr = arcpy.Describe(InSHP ).spatialReference.PCScode if sr != DEMSR: InSHP = arcpy.Project_management(InSHP , InSHP [:-4] + "PRJ.shp", DEMSR) print InSHP print InSHP['outline']
Of course! I can't try this out yet but I bet this is the solution!
Good call, Luke. I was going to recommend the same but didn't have time to get back to replying.
PS - You need a curly brace instead of a square bracket at the end of your dictionary assignment.