+ Reply to Thread
Results 1 to 12 of 12

Thread: Arcpy Dataframe

  1. #1
    Patrick Fischer
    Join Date
    Sep 2011
    Posts
    38
    Points
    3
    Answers Provided
    1


    0

    Post Arcpy Dataframe

    Hi everyone, i'm trying to make a script that does the following

    Pulls the coordinates from the active dataframe and inputs them into a polygon for a preselected feature class. In addition populates certain attribute fields from data saved in the MXD such as scale and creation date. Also there are some other particulars in the fields that I want calculate such as Producer, Notes, Product Type, Country Code. I've taken a look at Dataframe Extent under Arcpy and was wondering if it was possible to pull the current extent from the active dataframe. Looking at the example code I made a theory of using the "Current" command to pull the coordinates.

    Code:
    df = arcpy.mapping.ListDataFrames(mxd)[0]
    newExtent = df.extent
    newExtent.XMin, newExtent.YMin = -180.0, -90.0
    newExtent.XMax, newExtent.YMax = 180.0, 90.0
    df.extent = newExtent
    That's the example code I found located at http://help.arcgis.com/en/arcgisdesk...0000003000000/ Any help and advice and help is greatly appreciated.

  2. #2
    Mathew Coyle

    Join Date
    Feb 2011
    Posts
    1,392
    Points
    969
    Answers Provided
    151


    0

    Default Re: Arcpy Dataframe

    Creating a polygon is fairly simple.

    Code:
    mxd = arcpy.mapping.MapDocument("CURRENT")
    df = arcpy.mapping.ListDataFrames(mxd,"Layers")[0]
    
    extent = df.extent
    array = arcpy.Array()
    
    array.add(extent.lowerLeft)
    array.add(extent.lowerRight)
    array.add(extent.upperRight)
    array.add(extent.upperLeft)
    array.add(extent.lowerLeft)
     
    polygon = arcpy.Polygon(array)
    arcpy.CopyFeatures_management(polygon, r"C:\GIS\Default.gdb\polytest")
    After that adding fields and inputting some map document properties shouldn't be hard, but I don't have an example of it handy. See http://help.arcgis.com/en/arcgisdesk...000000n000000/
    Last edited by mzcoyle; 09-08-2011 at 06:14 AM. Reason: forgot array

  3. #3
    Nicholas Peihl
    Join Date
    Jul 2010
    Posts
    47
    Points
    2
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    I have a mostly-completed project that makes polygons of the main dataframe of each MXD in a given folder and saves the MXD properties and layer information in a file geodatabase. You can take a look at my code at https://bitbucket.org/npeihl/mapindextoolv2/overview.

    I apologize for lack of documentation. I haven't put it into production yet.

  4. #4
    Chandeep Corea
    Join Date
    Apr 2011
    Posts
    47
    Points
    1
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    Hi,

    I've created a script to do what you need and it's attached. Using the same code structure you should be able to populate the extra fields that you want.

    If you have any issues please tell me as I would like to improve the script.

    best,
    Attached Files

  5. #5
    Patrick Fischer
    Join Date
    Sep 2011
    Posts
    38
    Points
    3
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    I actually was able to work through most of this. I was going to do the fields later as i'm taking this one step at a time. Right now the newest thing I am trying to implement is being able to select which dataframe from the mxd you want to use. The reason for this is that the amount of mxd's i'm looking at 500+ have different dataframe names. Now i'm using arcpy.GetParameter(0) as i'm running this through ArcGIS and not from python so that it is more user friendly to people who do not know python coding. basically rough gist of script so far is:

    Code:
    import arcpy, os, sys
    
    mxdin = acrpy.GetParameter(0)
    
    
    mxd = arcpy.mapping.MapDocument(mxdin)
    df = arcpy.mapping.ListDataFrames(mxd,"Layers")[0]
    
    extent = df.extent
    array = arcpy.Array()
    
    array.add(extent.lowerLeft)
    array.add(extent.lowerRight)
    array.add(extent.upperRight)
    array.add(extent.upperLeft)
    array.add(extent.lowerLeft)
     
    try:
    
      polygon = arcpy.Polygon(array)
      arcpy.CopyFeatures_management(polygon, r"C:\GIS\Default.gdb\polytest"
    
    except:
      print "Failed to create polygon"
    I've thought of a couple ways to do it, I haven't tried anything yet though. Some of my ideas were to put the list of dataframes into an array and have a parameter that lets the user select from a drop down list which dataframe to use. Ideas?

  6. #6
    Patrick Fischer
    Join Date
    Sep 2011
    Posts
    38
    Points
    3
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    Ok I now have a working script that does everything I wanted to do. Some things i've noticed while running this is hat calculate fields is particularly slow, is there a way to speed it up or another function I can use instead? I took a few things from corea's script, thank you btw it was a great help. I have thought about using the rows part but i'm unsure how to use that exactly. This whole thing has been a wonderful learning process for me and i'm happy I was able to get to where i'm at now, thank you everyone

    Here is my script in its current form.

    Code:
    # Dataframe To Feature Class tool.
    # Pulls the extent of the active dataframe in an mxd, and fills out fields based on input values
    # from the user.
    # Author:  LCpl Patrick Fischer
    # Riff.Ibanezius@gmail.com
    # 3D Topo Plt, 3D Intel BN, Camp Hansen Okinawa, Japan
    
    import arcpy, os, sys
    
    # Deletes feature class from previous time the script was ran.
    arcpy.Delete_management(r"Z:\Training\Python\test_scripts\Extent_map.gdb\polygon")
    
    # Collect Parameters from User input
    
    mxdin = arcpy.GetParameterAsText(0)
    
    mxd = arcpy.mapping.MapDocument(mxdin)
    
    df = arcpy.mapping.ListDataFrames(mxd, "La*") [0] # select main dataframe not location diagram
    
    
    ext = df.extent
    array = arcpy.Array()
    
    array.add(ext.lowerLeft)
    array.add(ext.lowerRight)
    array.add(ext.upperRight)
    array.add(ext.upperLeft)
    array.add(ext.lowerLeft)
    
    polygon = arcpy.Polygon(array, df.spatialReference)
    
    arcpy.AddMessage("Extent has successfully been converted to a polygon")
    
    
    #Checks spatial reference from the dataframe to see if it needs to be transformed into another projection.
    
    if df.spatialReference == "WGS 1984":
        arcpy.Project_management(polygon, r"Z:\Training\Python\test_scripts\Extent_Map.gdb\polygon", "C:\Program Files\ArcGIS\Desktop10.0\Coordinate Systems\Geographic Coordinate Systems\World\WGS 1984.prj")
    
    else:
        arcpy.CopyFeatures_management(polygon, r"Z:\Training\Python\test_scripts\Extent_Map.gdb\polygon")
        print 'Already projected into WGS 1984' #change to message box
    
    arcpy.AddMessage("Successfuly projected into WGS 1984")
    polypro = r"Z:\Training\Python\test_scripts\Extent_Map.gdb\polygon"
    
    #add fields to new feature class
    
    arcpy.AddField_management(polypro, "PRODUCT_ID", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "PRODUCT_DATE", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "SCALE", "FLOAT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "EDITION", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "CLASSIFICATION", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "TYPE", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "PRODUCER", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "COUNTRY_CODE", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "NOTES", "TEXT", "", "", 250, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "PDF_PATH", "TEXT", "", "", 250, "", "NULLABLE", "REQUIRED")
    
    #Set parameters for user input
    
    PROID = arcpy.GetParameterAsText(1)
    PRODA = arcpy.GetParameterAsText(2)
    ED = arcpy.GetParameterAsText(3)
    CLA = arcpy.GetParameterAsText(4)
    TYP = arcpy.GetParameterAsText(5)
    PROD = arcpy.GetParameterAsText(6)
    CC = arcpy.GetParameterAsText(7)
    NOTES = arcpy.GetParameterAsText(8)
    PDF = arcpy.GetParameterAsText(9)
    
    arcpy.AddMessage("Calculating fields based on input values")
    
    #Calculate Fields based on user input
    for el in arcpy.mapping.ListLayoutElements(mxd, "DATAFRAME_ELEMENT"):
        SCALE = el.scale
        arcpy.CalculateField_management(polypro, "PRODUCT_ID", PROID, "", "")
        arcpy.CalculateField_management(polypro, "PRODUCT_DATE", PRODA, "", "")
        arcpy.CalculateField_management(polypro, "SCALE", SCALE, "", "")
        arcpy.CalculateField_management(polypro, "EDITION", ED, "", "")
        arcpy.CalculateField_management(polypro, "CLASSIFICATION", CLA, "", "")
        arcpy.CalculateField_management(polypro, "TYPE", TYP, "", "")
        arcpy.CalculateField_management(polypro, "PRODUCER", PROD, "", "") 
        arcpy.CalculateField_management(polypro, "COUNTRY_CODE", CC, "", "")
        arcpy.CalculateField_management(polypro, "NOTES", NOTES, "", "")
        arcpy.CalculateField_management(polypro, "PDF_PATH", PDF, "", "")
    
    arcpy.AddMessage("Succesfully calculated fields, appending to Topo Products feature class.")
    
    Feature = arcpy.GetParameterAsText(10)
    
    arcpy.Append_management(polypro, Feature ", "NO_TEST", "", "")
    Also sometimes i'll get an error about list is out of range, on one mxd it was due to what I think was to many data frames (around 50), but it happened again on another with just 2 data frames. I've ran this successfully with mxds with up to 5 data frames with no issues. Is this an anomaly or is something seriously wrong?

  7. #7
    Mathew Coyle

    Join Date
    Feb 2011
    Posts
    1,392
    Points
    969
    Answers Provided
    151


    0

    Default Re: Arcpy Dataframe

    I find update cursor to be faster than calculate field in most operations.

    Example
    Code:
    rows = arcpy.UpdateCursor(layer)
    for row in rows:
        row.values = 1
        rows.updateRow(row)
    For more detail see
    http://help.arcgis.com/en/arcgisdesk...0000003m000000
    Mathew Coyle, EADA10
    GIS Analyst
    Alberta-Pacific Forest Industries Inc.
    ArcGIS 10.2.2 Testing
    ArcGIS 10.1 SP1
    Desktop, Server, ArcPad
    Windows 7 SP1 64-bit

  8. #8
    Nicholas Peihl
    Join Date
    Jul 2010
    Posts
    47
    Points
    2
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    Quote Originally Posted by djriff View Post
    Ok I now have a working script that does everything I wanted to do. Some things i've noticed while running this is hat calculate fields is particularly slow, is there a way to speed it up or another function I can use instead? I took a few things from corea's script, thank you btw it was a great help. I have thought about using the rows part but i'm unsure how to use that exactly. This whole thing has been a wonderful learning process for me and i'm happy I was able to get to where i'm at now, thank you everyone

    Here is my script in its current form.

    Code:
    # Dataframe To Feature Class tool.
    # Pulls the extent of the active dataframe in an mxd, and fills out fields based on input values
    # from the user.
    # Author:  LCpl Patrick Fischer
    # Riff.Ibanezius@gmail.com
    # 3D Topo Plt, 3D Intel BN, Camp Hansen Okinawa, Japan
    
    import arcpy, os, sys
    
    # Deletes feature class from previous time the script was ran.
    arcpy.Delete_management(r"Z:\Training\Python\test_scripts\Extent_map.gdb\polygon")
    
    # Collect Parameters from User input
    
    mxdin = arcpy.GetParameterAsText(0)
    
    mxd = arcpy.mapping.MapDocument(mxdin)
    
    df = arcpy.mapping.ListDataFrames(mxd, "La*") [0] # select main dataframe not location diagram
    
    
    ext = df.extent
    array = arcpy.Array()
    
    array.add(ext.lowerLeft)
    array.add(ext.lowerRight)
    array.add(ext.upperRight)
    array.add(ext.upperLeft)
    array.add(ext.lowerLeft)
    
    polygon = arcpy.Polygon(array, df.spatialReference)
    
    arcpy.AddMessage("Extent has successfully been converted to a polygon")
    
    
    #Checks spatial reference from the dataframe to see if it needs to be transformed into another projection.
    
    if df.spatialReference == "WGS 1984":
        arcpy.Project_management(polygon, r"Z:\Training\Python\test_scripts\Extent_Map.gdb\polygon", "C:\Program Files\ArcGIS\Desktop10.0\Coordinate Systems\Geographic Coordinate Systems\World\WGS 1984.prj")
    
    else:
        arcpy.CopyFeatures_management(polygon, r"Z:\Training\Python\test_scripts\Extent_Map.gdb\polygon")
        print 'Already projected into WGS 1984' #change to message box
    
    arcpy.AddMessage("Successfuly projected into WGS 1984")
    polypro = r"Z:\Training\Python\test_scripts\Extent_Map.gdb\polygon"
    
    #add fields to new feature class
    
    arcpy.AddField_management(polypro, "PRODUCT_ID", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "PRODUCT_DATE", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "SCALE", "FLOAT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "EDITION", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "CLASSIFICATION", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "TYPE", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "PRODUCER", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "COUNTRY_CODE", "TEXT", "", "", 50, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "NOTES", "TEXT", "", "", 250, "", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(polypro, "PDF_PATH", "TEXT", "", "", 250, "", "NULLABLE", "REQUIRED")
    
    #Set parameters for user input
    
    PROID = arcpy.GetParameterAsText(1)
    PRODA = arcpy.GetParameterAsText(2)
    ED = arcpy.GetParameterAsText(3)
    CLA = arcpy.GetParameterAsText(4)
    TYP = arcpy.GetParameterAsText(5)
    PROD = arcpy.GetParameterAsText(6)
    CC = arcpy.GetParameterAsText(7)
    NOTES = arcpy.GetParameterAsText(8)
    PDF = arcpy.GetParameterAsText(9)
    
    arcpy.AddMessage("Calculating fields based on input values")
    
    #Calculate Fields based on user input
    for el in arcpy.mapping.ListLayoutElements(mxd, "DATAFRAME_ELEMENT"):
        SCALE = el.scale
        arcpy.CalculateField_management(polypro, "PRODUCT_ID", PROID, "", "")
        arcpy.CalculateField_management(polypro, "PRODUCT_DATE", PRODA, "", "")
        arcpy.CalculateField_management(polypro, "SCALE", SCALE, "", "")
        arcpy.CalculateField_management(polypro, "EDITION", ED, "", "")
        arcpy.CalculateField_management(polypro, "CLASSIFICATION", CLA, "", "")
        arcpy.CalculateField_management(polypro, "TYPE", TYP, "", "")
        arcpy.CalculateField_management(polypro, "PRODUCER", PROD, "", "") 
        arcpy.CalculateField_management(polypro, "COUNTRY_CODE", CC, "", "")
        arcpy.CalculateField_management(polypro, "NOTES", NOTES, "", "")
        arcpy.CalculateField_management(polypro, "PDF_PATH", PDF, "", "")
    
    arcpy.AddMessage("Succesfully calculated fields, appending to Topo Products feature class.")
    
    Feature = arcpy.GetParameterAsText(10)
    
    arcpy.Append_management(polypro, Feature ", "NO_TEST", "", "")
    Also sometimes i'll get an error about list is out of range, on one mxd it was due to what I think was to many data frames (around 50), but it happened again on another with just 2 data frames. I've ran this successfully with mxds with up to 5 data frames with no issues. Is this an anomaly or is something seriously wrong?
    I agree with Matthew that you should use a cursor instead of Calculating Fields. An Insert Cursor should work nicely for you.

    Also, the "list out of range" error may be due to no Dataframes in the MXD that start with "La" as you specify when you are creating the "df" variable. If ArcPy can't find any dataframes in the MXD that start with "La" then it creates an empty list. Calling the first index "[0]" on an empty list returns the out of range error.

  9. #9
    Patrick Fischer
    Join Date
    Sep 2011
    Posts
    38
    Points
    3
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    Quote Originally Posted by npeihl View Post
    I agree with Matthew that you should use a cursor instead of Calculating Fields. An Insert Cursor should work nicely for you.

    Also, the "list out of range" error may be due to no Dataframes in the MXD that start with "La" as you specify when you are creating the "df" variable. If ArcPy can't find any dataframes in the MXD that start with "La" then it creates an empty list. Calling the first index "[0]" on an empty list returns the out of range error.
    So i used cursor and rows and found it much more to my advantage. Works quite nicely. Still want to know how to put the list of dataframes into a list you can select from in arcCatalog.

  10. #10
    Mathew Coyle

    Join Date
    Feb 2011
    Posts
    1,392
    Points
    969
    Answers Provided
    151


    0

    Default Re: Arcpy Dataframe

    Quote Originally Posted by djriff View Post
    Still want to know how to put the list of dataframes into a list you can select from in arcCatalog.
    Not sure I quite understand what you are looking for. You mean just a table of the data frame names?
    Mathew Coyle, EADA10
    GIS Analyst
    Alberta-Pacific Forest Industries Inc.
    ArcGIS 10.2.2 Testing
    ArcGIS 10.1 SP1
    Desktop, Server, ArcPad
    Windows 7 SP1 64-bit

  11. #11
    Patrick Fischer
    Join Date
    Sep 2011
    Posts
    38
    Points
    3
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    Quote Originally Posted by mzcoyle View Post
    Not sure I quite understand what you are looking for. You mean just a table of the data frame names?
    That's pretty much what i'm looking for. A table that you can select which data frame you want to take the extent from.

  12. #12
    Nicholas Peihl
    Join Date
    Jul 2010
    Posts
    47
    Points
    2
    Answers Provided
    1


    0

    Default Re: Arcpy Dataframe

    Quote Originally Posted by djriff View Post
    That's pretty much what i'm looking for. A table that you can select which data frame you want to take the extent from.
    You could retrieve the dataframes, print them as a list of options for the user and then get the user's response via "raw_input". However, I don't know if this will work when the script is used in an ArcToolbox.

    I envision it something like this:

    Code:
    # Get a list of dataframes in the mxd and assign the list to df
    dataFrames = arcpy.ListDataframes(mxd)
    
    # Give each dataframe in the df list a number starting with 1 using enumerate and make it a dictionary
    options = dict(enumerate(dataFrames, 1))
    
    # Show options and let the user select which dataframe
    response = int(raw_input("Select the number of the dataframe you want: %s \n" % options.items()))
    
    # Assign df to the user's choice
    df = options[response]
    If you use that code you may want to build in some try:except clauses to send user-friendly error messages if bad info is entered.

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts