Generieren einer mehrwertigen Auswahlliste in ArcGIS mithilfe der Werkzeugüberprüfung ohne Verwendung der Häufigkeit?


11

Ich versuche, eine Modell- und Skriptkombination anzupassen, die auf der ESRI-Blog-Site mit dem Titel "Generieren einer mehrwertigen Auswahlliste" zu finden ist.

Ich bin jedoch zu dem Schluss gekommen, dass ein Teil der im eingebetteten Skript verwendeten Validierung vom 'Frequenz'-Tool abhängt, um ordnungsgemäß zu funktionieren. Dies ist jedoch nur mit einer erweiterten Lizenz (lahm) verfügbar. Der Blog-Beitrag erklärt den Workflow und wo die Modelle und Skripte heruntergeladen werden können (aber ich werde sie auf Anfrage gerne hier veröffentlichen). Soweit ich das beurteilen kann, ist der Kern der Funktionalität, nach der ich suche, die Erstellung einer mehrwertigen Auswahlliste:

Geben Sie hier die Bildbeschreibung ein

..ist vorausgesetzt, dass das Validierungsskript ordnungsgemäß funktioniert. Ohne die Validierung kann ich die Werte aus dem Feld nicht als Liste anzeigen lassen. Gibt es etwas, das ich aus diesem Validierungsskript entfernen kann, um die gewünschte Funktionalität zu erhalten, oder gibt es eine Problemumgehung? Ich bin mit dem Validierungsprozess nicht vertraut. Hier ist der Code für die Validierung (ich wollte ihn als Codebeispiel veröffentlichen, aber es sieht so aus, als ob es einfacher wäre, ihm zu folgen): Geben Sie hier die Bildbeschreibung ein

[ Anmerkung des Herausgebers: Hier ist der tatsächliche Validierungscode, das Bild ist nicht korrekt.]

import arcpy

class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""
    return

  def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parmater
    has been changed."""
    if self.params[1].altered: #Set condition - if the input field value changes
        if self.params[1].value: #if the field parameter has a value
            for field in arcpy.Describe(self.params[0].value).fields: #iterate through fields in the input dataset
                if field.name.lower() == self.params[1].value.value.lower(): #find the field object with the same name as field parameter
                    try:
                        if self.params[2].values: #if this parameter has seleted values
                            oldValues = self.params[2].values #set old values to the selected values
                    except Exception:
                        pass
                    values = set() #create an empty set
                    fieldname = self.params[1].value.value #set the value of variable fieldname equal to the input field value
                    FrequencyTable = arcpy.Frequency_analysis (self.params[0].value, "in_memory\Frequency", self.params[1].value.value, "") #for large tables create a frequency table
                    cursor = arcpy.SearchCursor(FrequencyTable, "", "", self.params[1].value.value, "{0} A".format(self.params[1].value.value)) #open a search cursor on the frequency table
                    for row in cursor: #loop through each value
                        values.add(row.getValue(fieldname)) #add the value to the set
                    self.params[2].filter.list = sorted(values) #set the filter list equal to the sorted values
                    newValues = self.params[2].filter.list
                    try:
                        if len(oldValues): # if some values are selected
                            self.params[2].values = [v for v in oldValues if v in newValues] # check if seleted values in new list,
                            # if yes, retain the seletion.
                    except Exception:
                        pass

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return

Ist es möglich, dass meine Annahme (durch Testen), dass die Validierung das Schlüsselelement ist, falsch ist und dass etwas anderes nicht zulässt, dass die Werte als auswählbare Liste angezeigt werden? Vielen Dank im Voraus. Diese Art von Funktionalität wird die Einführung mehrerer wichtiger Workflows, die ich in unserem Unternehmen zu verteilen versuche, wirklich beschleunigen!


1
Welche Version von ArcGIS verwenden Sie? Ich frage, weil das bei 10.1 arcpy.da.SearchCursorviel schneller und besser für diese Aufgabe geeignet ist als das ältere arcpy.SearchCursor.
blah238

1
Der Validierungscode für die von Ihnen verknüpfte Toolbox unterscheidet sich vom Validierungscode in dem von Ihnen verknüpften Bild. Ersteres erfordert eine erweiterte Lizenz, da das Frequenz-Tool verwendet wird. Letzteres, das in einem früheren Blog-Beitrag beschrieben wurde, sollte dies nicht tun, da es nur Standard-Arcpy-Funktionen wie SearchCursor verwendet. Ich habe keine Antwort für Sie, aber wenn Sie die beiden zusammenfügen, können Sie es vielleicht herausfinden.
blah238

@ blah268 Es ist 10.2, tut mir leid, dass ich das verpasst habe. Hmm, das ist eine sehr interessante Beobachtung. Ich werde mir das ansehen, aber ich bin neugierig: Verstehe ich richtig, dass die Validierung die Werte als Auswahlliste übergibt? Die Multi-Choice ist die Funktionalität, nach der ich suche. Ich melde mich bei Ihnen und vielen Dank für die Antwort!
Clickinaway

1
In den Parametereigenschaften des Skriptwerkzeugs richten Sie die Liste der Parameter und ihrer Eigenschaften ein (einschließlich einer MultiValue-Eigenschaft). Bei der Überprüfung des Skriptwerkzeugs füllt dieses spezielle Werkzeug die mehrwertigen Parameterwerte basierend auf anderen Parameterwerten (Feature-Class und Feldname). Wenn ich für größere Feature-Classes damit herumspiele, würde ich dies nicht in Produktion bringen. Zu langsam und auch fehlerfrei, wenn in den Geoverarbeitungsoptionen nicht die Option "Ausgaben von Geoverarbeitungsvorgängen überschreiben" aktiviert ist.
blah238

1
Ich kann nicht chatten, aber ich würde vorschlagen, Ihre Frage zu bearbeiten, um Ihre Anforderungen, Ihre Versuche und die Funktionsweise zu beschreiben.
blah238

Antworten:


9

Ich dachte, einige Leute finden das vielleicht wertvoll. ESRI war so freundlich, dies zu lösen und eine Alternative zu der im Blog-Beitrag verwendeten Validierung zu finden, für die keine erweiterte Lizenz erforderlich ist. Obwohl ich sicherlich einige zusätzliche Elemente herausfinden musste, kann ich den Validierungscode nicht gutschreiben. Aber die Ziele rechtfertigen die Mittel und dies ist die Antwort auf meine Frage. Bitte schön:

import arcpy
class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""
    return

  def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parameter
    has been changed."""
    if self.params[0].value and self.params[1].value:
        self.params[2].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[0].value, self.params[1].value.value) if row[0]})

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return

Die Verwendung von arcpy.da.SearchCursor gibt sehr schnell Werte aus dem ausgewählten Feld zurück, wenn man die Anzahl der Datensätze berücksichtigt, die durchsucht werden (zumindest in meinen Daten). Ich kann einen neuen Thread starten, um zu sehen, ob jemand Ideen hat, wie ein Filter auf die Validierung basierend auf einer Abfrage angewendet werden kann. Ich hoffe das hilft jemandem, aber ich bin froh, dass wir eine Antwort haben!


1

Ich habe es auf eine andere Weise gemacht: Die Verwendung der Datenbank besteht aus fünf Ebenen, ohne das Shapefile oder die Felder auszuwählen, indem nur Elemente aus der ersten Ebene ausgewählt werden. Das Validierungsskript generiert die Werte für die zweite Ebene gemäß Ihrer Auswahl in der ersten Ebene. Ihr Skript:

import arcpy
class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):  
    """Setup arcpy and the list of tool parameters."""  
    self.params = arcpy.GetParameterInfo()  



  def initializeParameters(self):  
    """Refine the properties of a tool's parameters.  This method is  
    called when the tool is opened."""  
    return  

  def updateParameters(self):

    fc="C:/LUCS/System_shapes/sys.shp"
##    fc = arcpy.MakeFeatureLayer_management(Lucssys)  
    """Modify the values and properties of parameters before internal  
    validation is performed.  This method is called whenever a parmater  
    has been changed."""  
##    if self.params[0].value and self.params[0].value:


    fc="C:/LUCS/System_shapes/sys.shp"  
    col=  ("L1_NAM") 
    self.params[0].filter.list = [str(val) for val in  
                                    sorted(  
                                      set(  
                                        row.getValue(col)  
                                        for row in arcpy.SearchCursor(fc, None, None,col)))]  
    if self.params[0].value not in self.params[0].filter.list:  
      self.params[0].value = self.params[0].filter.list[0]


    if self.params[0].value:

        fc="C:/LUCS/System_shapes/sys.shp"  
        col1=  ("L1_NAM")
        col2=  ("L2_NAM") 
        fields=(col1,col2)
##___________level2___________________________________________________________
    fc="C:/LUCS/System_shapes/sys.shp" 
    col1=  ("L1_NAM")
    col2=  ("L2_NAM") 
    fields=(col1,col2)

    Level0list=[]
    Level0list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col1)) ==(str(self.params[0].value)):
                      Level0list.append (row.getValue(col2))

    for elem in Level0list:
              if elem not in Level0list_uniq:
                  Level0list_uniq.append(elem)


    if self.params[1].value not in self.params[1].filter.list:  
        self.params[1].filter.list =Level0list_uniq
##________________level3______________________________________________________        
    fc="C:/LUCS/System_shapes/sys.shp" 
    col2=  ("L2_NAM")
    col3=  ("L3_NAM") 
    fields=(col2,col3)
    Level2list=[]
    Level2list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col2)) ==(str(self.params[1].value)):
                      Level2list.append (row.getValue(col3))
    for elem in Level2list:
              if elem not in Level2list_uniq:
                  Level2list_uniq.append(elem)
    if self.params[2].value not in self.params[2].filter.list:  
        self.params[2].filter.list =Level2list_uniq
##________________level4______________________________________________________        
    fc="C:/LUCS/System_shapes/sys.shp" 
    col3=  ("L3_NAM")
    col4=  ("L4_NAM") 
    fields=(col3,col4)

    Level3list=[]
    Level3list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col3)) ==(str(self.params[2].value)):
                      Level3list.append (row.getValue(col4))
    for elem in Level3list:
              if elem not in Level3list_uniq:
                  Level3list_uniq.append(elem)
    if self.params[3].value not in self.params[3].filter.list:  
        self.params[3].filter.list =Level3list_uniq
##________________level5______________________________________________________        
    fc="C:/LUCS/System_shapes/sys.shp" 
    col4=  ("L4_NAM")
    col5=  ("L5_NAM") 
    fields=(col4,col5)

    Level4list=[]
    Level4list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col4)) ==(str(self.params[3].value)):
                      Level4list.append (row.getValue(col5))
    for elem in Level4list:
              if elem not in Level4list_uniq:
                  Level4list_uniq.append(elem)
    if self.params[4].value not in self.params[4].filter.list:  
        self.params[4].filter.list =Level4list_uniq

  def updateMessages(self):  
    """Modify the messages created by internal validation for each tool  
    parameter.  This method is called after internal validation."""  

0
Add new conditions to ensure a single option when the same term exists in more than one category. ِand to force arcpy to deal with arabic fonts

import arcpy
import sys

reload(sys)

sys.setdefaultencoding('utf-8')

class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""



  def __init__(self):  
    """Setup arcpy and the list of tool parameters."""  
    self.params = arcpy.GetParameterInfo()  




  def updateParameters(self):

    fc="C:/LUCS/System_shapes/sys.shp"
    col=  ("L1_NAM")
 ##________________level1_________________

    self.params[0].filter.list = [str(val) for val in  
                                    sorted(  
                                      set(  
                                        row.getValue(col)  
                                        for row in arcpy.SearchCursor(fc, None, None,col)))]  
    if self.params[0].value not in self.params[0].filter.list:  
      self.params[0].value = self.params[0].filter.list[0]



    if self.params[0].value:

        fc="C:/LUCS/System_shapes/sys.shp"  
        col1=  ("L1_NAM")
        col2=  ("L2_NAM")
        col3=  ("L3_NAM") 
        col4=  ("L4_NAM")
        col5=  ("L5_NAM") 
        fields=(col1,col2,col3,col4,col5)
        Level1list=[]
        Level1list_uniq=[]
        Level2list=[]
        Level2list_uniq=[]
        Level3list=[]
        Level3list_uniq=[]
        Level4list=[]
        Level4list_uniq=[]
        Level5list=[]
        Level5list_uniq=[]

        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
                        if (row.getValue(col1)) ==(str(self.params[0].value)):
                                Level1list.append (row.getValue(col2))

        for elem in Level1list:
                        if elem not in Level1list_uniq:
                            Level1list_uniq.append(elem)


        if self.params[1].value not in self.params[1].filter.list:  
              self.params[1].filter.list =Level1list_uniq
      ##________________level3_________________        
        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
                  if (row.getValue(col1)) ==(str(self.params[0].value)):
                    if (row.getValue(col2)) ==(str(self.params[1].value)):
                            Level2list.append (row.getValue(col3))
        for elem in Level2list:
                    if elem not in Level2list_uniq:
                        Level2list_uniq.append(elem)
        if self.params[2].value not in self.params[2].filter.list:  
              self.params[2].filter.list =Level2list_uniq
      ##________________level4_______________       
        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
              if (row.getValue(col1)) ==(str(self.params[0].value)):

                    if (row.getValue(col3)) ==(str(self.params[2].value)):
                            Level3list.append (row.getValue(col4))
        for elem in Level3list:
                    if elem not in Level3list_uniq:
                        Level3list_uniq.append(elem)
        if self.params[3].value not in self.params[3].filter.list:  
              self.params[3].filter.list =Level3list_uniq
      ##________________level5_______________      
        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
            if (row.getValue(col1)) ==(str(self.params[0].value)):
                    if (row.getValue(col4)) ==(str(self.params[3].value)):
                            Level4list.append (row.getValue(col5))
        for elem in Level4list:
                    if elem not in Level4list_uniq:
                        Level4list_uniq.append(elem)
        if self.params[4].value not in self.params[4].filter.list:  
              self.params[4].filter.list =Level4list_uniq

    return

Bitte formatieren Sie Ihren gesamten Code richtig.
Marcelo Villa

es wurde getan, seine Arbeit in 10.5.0
Younes Idriss

Ein Teil Ihres Codes ist formatiert, andere Zeilen jedoch nicht ( z. B. die Importanweisungen Ihres Codes). Verwenden Sie die { }Schaltfläche, um Ihren Code richtig zu formatieren.
Marcelo Villa

danke für den Rat
Younes Idriss

Es sieht auch so aus, als ob Ihnen die Definition einer Klasse fehlt.
Marcelo Villa
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.