¿Generar lista de opciones de valores múltiples en ArcGIS usando Validación de herramienta sin usar Frecuencia?

11

Estoy tratando de adaptar una combinación de modelo y script que se encuentra en el sitio del blog de ESRI titulado 'Generando una lista de opciones de valores múltiples'.

Sin embargo, he concluido que parte de la validación utilizada en el script incrustado depende de la herramienta 'Frecuencia' para funcionar correctamente, pero esto solo está disponible con una licencia avanzada (lame). La publicación del blog explica el flujo de trabajo y dónde descargar los modelos y los scripts (pero los publicaré aquí a pedido). Por lo que puedo decir, el núcleo de la funcionalidad que busco es generar una lista de opciones de valores múltiples:

ingrese la descripción de la imagen aquí

... se basa en que el script de validación funcione correctamente. Sin la validación, no puedo obtener los valores del campo para que aparezcan como una lista. ¿Hay algo que pueda eliminar de este script de validación para obtener la funcionalidad que busco, o hay una solución? No estoy familiarizado con el proceso de validación. Aquí está el código para la validación (iba a publicar como una Muestra de Código, pero parece que podría ser más fácil de seguir): ingrese la descripción de la imagen aquí

[ Nota del editor: aquí está el código de validación real, la imagen no es correcta]

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

¿Es posible que mi suposición (a través de las pruebas) de que la validación es la pieza clave sea falsa y que algo más no permita que los valores se expongan como una lista seleccionable? Muchas gracias de antemano. Tener este tipo de funcionalidad realmente impulsará la adopción de varios flujos de trabajo clave que estoy tratando de distribuir en nuestra empresa.

Clickinaway
fuente
1
¿Qué versión de ArcGIS estás usando? Pregunto porque en 10.1 el arcpy.da.SearchCursores mucho más rápido y más adecuado para esta tarea que el anterior arcpy.SearchCursor.
blah238
1
El código de validación para la caja de herramientas que ha vinculado es diferente del código de validación en la imagen que ha vinculado. El primero requiere una licencia avanzada porque utiliza la herramienta de frecuencia. Este último, detallado en una publicación de blog anterior, no debería porque solo usa funciones de arcpy estándar como SearchCursor. No tengo una respuesta para ti, pero si las unes, tal vez puedas resolverlo.
blah238
@ blah268 Es 10.2, perdón por perderse eso. Hmm, ahora esa es una observación muy interesante. Veré eso, pero tengo curiosidad: ¿entiendo correctamente que la validación es lo que pasa los valores como una lista de opciones? la opción múltiple es la funcionalidad que busco. Me pondré en contacto con usted y muchas gracias por la respuesta.
Clickinaway
1
Las propiedades de los parámetros de la herramienta de script es donde configura la lista de parámetros y sus propiedades (que incluye una propiedad MultiValue). La validación de la herramienta de secuencia de comandos es donde esta herramienta en particular llena los valores de parámetros de valores múltiples basados ​​en otros valores de parámetros (clase de entidad y nombre de campo). Jugando con él para clases de entidad más grandes, no pondría esto en producción. Demasiado lento, y también errores si no tiene "Sobrescribir las salidas de las operaciones de geoprocesamiento" marcadas en las opciones de Geoprocesamiento.
blah238
1
No puedo chatear, pero lo que sugeriría es editar su pregunta para detallar sus requisitos, lo que ha intentado y lo que no funciona.
blah238

Respuestas:

9

Pensé que algunas personas podrían encontrar esto valioso. ESRI fue lo suficientemente amable como para ayudar a resolver esto y encontrar una alternativa a la validación utilizada en la publicación del blog que no requiere una licencia avanzada. Si bien ciertamente tuve que resolver algunos elementos adicionales, no puedo tomar el crédito por el código de validación. Pero, los fines justifican los medios y esto califica como la respuesta a mi pregunta. Aqui tienes:

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

El uso de arcpy.da.SearchCursor devuelve valores del campo elegido muy rápidamente considerando la cantidad de registros que busca (al menos en mis datos). Puedo comenzar un nuevo hilo para ver si alguien tiene alguna idea sobre cómo aplicar un filtro a la validación basada en una consulta. Espero que esto ayude a alguien, ¡pero me alegra que tengamos una respuesta!

Clickinaway
fuente
1

Lo hice de otra manera: el uso de la base de datos consta de cinco niveles, sin elegir el shapefile o los campos simplemente seleccionando elementos del primer nivel, el script de validación genera los valores para el segundo nivel de acuerdo con su elección en el primer nivel, el script:

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."""  
Younes Idriss
fuente
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
Younes Idriss
fuente
Por favor, formatee todo su código correctamente.
Marcelo Villa-Piñeros
estaba hecho, está funcionando en 10.5.0
Younes Idriss
Parte de su código está formateado, pero como puede ver, otras líneas no lo están ( por ejemplo, las declaraciones de importación de su código). Use el { }botón para formatear correctamente su código.
Marcelo Villa-Piñeros
También parece que te falta la definición de una clase.
Marcelo Villa-Piñeros