Arcpy -- Edit Spatial Reference Object Properties

5800
17
Jump to solution
11-05-2015 04:41 AM
TrilliumLevine1
Occasional Contributor

Hello All,

I'm trying to develop a python script  to edit the name property of several spatial reference objects found while iterating through a folder and its subdirectories.  The projection of the data is identical to ETRS_1989_UTM_Zone_32N, but is named something else -- I'm just trying to reset the name to ETRS_1989_UTM_Zone_32N.  According to the help, this property is both readable and writable in ArcGIS 10.2, which is what I'm running.  I'm just not sure how to go about writing in the new projection name via the script...anybody have any ideas?  Any feedback is greaty appreciated!

Here's my code so far:

import os
import arcpy

workspace = r"C:\Scripts\Reproject"
newProjection = "ETRS_1989_UTM_Zone_32N"

def recursiveProjections(workspace):
    """
    Function iterates through a workspace and its subfolders using arcpy.da.walk and returns
    a list of spatial reference objects of all geographic datasets (including those inside
    geodatabases).  Parameter: target workspace

    """
    projections = []
    for dirpath, dirnames, filenames in arcpy.da.Walk(workspace):
        for filename in filenames:
            desc = arcpy.Describe(os.path.join(dirpath, filename))
            srObject = desc.spatialReference
            projections.append(srObject)
    return projections

def editProjection(workspace):
    projections = recursiveProjections(workspace)
    for projection in projections:
        print projection.name

editProjection(workspace)
0 Kudos
1 Solution

Accepted Solutions
AndrewLowerre
New Contributor III

Hi Trillium,

Perhaps the 'Define Projection' tool (ArcGIS Help (10.2, 10.2.1, and 10.2.2) ) is what you're after?

If I understand you correctly, you want to walk over all the feature classes in a workspace and change the Spatial Reference for each one to ETRS_1989_UTM_Zone_32N. 'Define Projection' should enable you to do that.

Hope this helps,

Andrew

View solution in original post

17 Replies
AndrewLowerre
New Contributor III

Hi Trillium,

Perhaps the 'Define Projection' tool (ArcGIS Help (10.2, 10.2.1, and 10.2.2) ) is what you're after?

If I understand you correctly, you want to walk over all the feature classes in a workspace and change the Spatial Reference for each one to ETRS_1989_UTM_Zone_32N. 'Define Projection' should enable you to do that.

Hope this helps,

Andrew

TrilliumLevine1
Occasional Contributor

Hi Andrew,

Thanks for the response, but that won't work since (as far as I know) you can't define a projection for something that already has one defined.  Anyway, I figured out how to do it in code:

import os
import arcpy

workspace = r"C:\Scripts\Reproject"
newProjection = "PROJCS['ETRS_1989_UTM_Zone_32N'"

def recursiveProjections(workspace):
    """
    Function iterates through a workspace and its subfolders using arcpy.da.walk and returns
    a list of spatial reference objects of all geographic datasets (including those inside
    geodatabases).  Parameter: target workspace

    """
    projections = []
    for dirpath, dirnames, filenames in arcpy.da.Walk(workspace):
        for filename in filenames:
            desc = arcpy.Describe(os.path.join(dirpath, filename))
            srObject = desc.spatialReference
            projections.append(srObject)
    return projections

def editProjection(workspace):
    projections = recursiveProjections(workspace)
    for projection in projections:
        projectionParameters = projection.exportToString()
        parameterSplit = projectionParameters.split(",")
##        print parameterSplit[0]
        parameterSplit[0] = newProjection
        SR_outstring = ",".join(parameterSplit)
        print SR_outstring

editProjection(workspace)
DarrenWiens2
MVP Honored Contributor

Just a note about Andrew Lowerre​'s suggestion for Define Projection. The general wisdom is that you shouldn't use Define once a CRS has been defined, because you have correctly defined the CRS in the first place. In this case, you have "incorrectly" (on purpose) defined your CRS with the "wrong" name. It is perfectly reasonable to use Define to change the name. I suspect your script mirrors the Define tool - it would be interesting to see the run time comparison.

AndrewLowerre
New Contributor III

Hi Darren,

This was my understanding as well, but since Trillium seemed to have found something that worked, I figured case closed.

Cheers,

Andrew

0 Kudos
NeilAyres
MVP Alum

I have a feeling that the correct way would be just to set the projection using Define.

In the code above I cannot see how the actual projection is redefined. It just changes the "Name" part of the projection text representation.

0 Kudos
DarrenWiens2
MVP Honored Contributor

Neil Ayres​, the code does exactly what you suggest, renaming a known projection, essentially creating a "custom" projection. The equivalent using Define would be to create a custom projection beforehand and define to that. Six one way, half dozen the other (although actual performance may differ).

0 Kudos
NeilAyres
MVP Alum

Well exactly. So wouldn't the sr remain a custom one?

Far better just to do

sr = arcpy.SpatialReference(25832) # wkid for 'ETRS_1989_UTM_Zone_32N'
arcpy.DefineProjection_management(infc, sr)

And you can define the sr for a feature class that already has one. With certain caveats of course, don't define the fc as something it isn't...

TrilliumLevine1
Occasional Contributor

Thanks for all the feedback, everyone -- looks like Neil's answer will keep the simplest.

0 Kudos
TrilliumLevine1
Occasional Contributor

Hi Again,

I'm running into a problem with the version of this script making use of DefineProjection.  I'm getting an error indicating a problem executing the tool (see screenshot).  FYI, I'm using 10.2.2 and Python 2.7 on a Windows 7 64-bit system.  I've also uploaded my test data folder, in case anyone wants to take a look at it.  Anyone have any ideas?

Thanks again,

Trill

existing code:

import os
import arcpy

def recursiveProjections(workspace):
    """ Function iterates through a workspace and its subfolders using arcpy.da.walk and returns
        a tuple containing two lists: 1) list of spatial reference objects of all geographic datasets (including those inside
        geodatabases) and 2) a list of filepaths for the geographic datasets.  Parameter: target workspace
    """
    describeDatasets = []
    filesList = []
    for dirpath, path, filenames in arcpy.da.Walk(workspace):
        for filename in filenames:
            desc = arcpy.Describe(os.path.join(dirpath, filename))
            describeDatasets.append(desc)
    for path, path_names, data_names in arcpy.da.Walk(workspace):
        for data_name in data_names:
            filesList.append(os.path.join(path, data_name))
    return describeDatasets, filesList


def defineProjection(workspace):
    """ Function redefines the existing projection for datasets in a workspace.  A log file is created listing
        the paths of all redefined datasets.  Parameter: workspace
    """
    # unpack tuple returned by def recursiveProjections into two lists
    descriptions, filenames = recursiveProjections(workspace)
    # iterate through features and redefine their projections correctly
    for feature in descriptions:
       arcpy.DefineProjection_management(feature, newProjection)
    # logging
    for filename in filenames:
        print filename


def main():
    defineProjection(workspace)


if __name__ == '__main__':
    main()
0 Kudos