Generare un elenco di scelte multivalore in ArcGIS utilizzando la convalida dello strumento senza utilizzare la frequenza?


11

Sto cercando di adattare una combinazione di modello e script trovata sul sito del blog ESRI intitolata "Generare un elenco di scelte multivalore".

Tuttavia, ho concluso che parte della convalida utilizzata nello script incorporato si basa sullo strumento "Frequenza" per funzionare correttamente, ma questo è disponibile solo con e Licenza avanzata (lame). Il post sul blog spiega il flusso di lavoro e dove scaricare i modelli e gli script (ma li posterò felicemente qui su richiesta). Per quanto posso dire, il nucleo della funzionalità che sto cercando, generando un elenco di scelte multivalore:

inserisci qui la descrizione dell'immagine

..è basato sullo script di validazione che funziona correttamente. Senza la convalida, non sono in grado di visualizzare i valori dal campo come elenco. C'è qualcosa che posso rimuovere da questo script di convalida per ottenere la funzionalità che sto cercando o c'è una soluzione? Non ho familiarità con il processo di convalida. Ecco il codice per la convalida (stavo per pubblicare un esempio di codice, ma sembra che potrebbe essere più facile da seguire): inserisci qui la descrizione dell'immagine

[ Nota dell'editore: ecco il codice di validazione attuale, l'immagine non è corretta]

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

È possibile che la mia ipotesi (tramite test) che la convalida sia l'elemento chiave sia falsa e che qualcos'altro non consenta che i valori vengano esposti come elenco selezionabile? Molte grazie in anticipo. Avere questo tipo di funzionalità farà davvero iniziare l'adozione di diversi flussi di lavoro chiave che sto cercando di distribuire nella nostra azienda!


1
Quale versione di ArcGIS stai usando? Lo chiedo perché a 10.1 arcpy.da.SearchCursorè molto più veloce e più adatto a questo compito rispetto al vecchio arcpy.SearchCursor.
blah238

1
Il codice di convalida per la casella degli strumenti collegata è diverso dal codice di convalida nell'immagine collegata. Il primo richiede una licenza avanzata perché utilizza lo strumento Frequenza. Quest'ultimo, dettagliato in un precedente post sul blog, non dovrebbe perché utilizza solo funzioni arcpy standard come SearchCursor. Non ho una risposta per te, ma se metti insieme i due forse potresti capirlo.
blah238,

@ blah268 E 'il 10.2, scusami se mi manca. Hmm, ora è un'osservazione molto interessante. Lo guarderò, ma sono curioso: capisco correttamente che la convalida è ciò che passa i valori come un elenco di scelta? la scelta multipla è la funzionalità che sto cercando. Tornerò da te e molte grazie per la risposta!
Clickinaway

1
Le proprietà dei parametri dello strumento di script sono quelle in cui si imposta l'elenco dei parametri e le relative proprietà (che include una proprietà MultiValue). La convalida dello strumento di script è dove questo particolare strumento popola i valori dei parametri multivalore in base ad altri valori di parametro (classe di funzionalità e nome campo). Giocando con esso per classi di funzioni più grandi, non lo metterei in produzione. Troppo lento e anche errori se non si è selezionato "Sovrascrivi gli output delle operazioni di geoprocessing" nelle opzioni di Geoprocessing.
blah238

1
Non sono in grado di chattare, ma ciò che suggerirei è modificare la tua domanda per dettagliare le tue esigenze, cosa hai provato e cosa non funziona.
blah238

Risposte:


9

Ho pensato che alcune persone potrebbero trovare questo prezioso. ESRI è stato così gentile da aiutarci a risolvere questo problema e trovare un'alternativa alla convalida utilizzata nel post del blog che non richiede una licenza avanzata. Anche se sicuramente ho dovuto capire alcuni elementi aggiuntivi, non posso prendermi il merito per il codice di convalida. Ma i fini giustificano i mezzi e questo si qualifica come la risposta alla mia domanda. Ecco qui:

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

L'uso di arcpy.da.SearchCursor restituisce valori dal campo scelto molto velocemente considerando il numero di record che sta cercando (almeno nei miei dati). Potrei iniziare una nuova discussione per vedere se qualcuno ha qualche idea su come applicare un filtro alla convalida basata su una query. Spero che questo aiuti qualcuno, ma sono contento che abbiamo una risposta!


1

L'ho fatto in un altro modo: utilizzando il database è costituito da livelli di fivel, senza scegliere il file di forma o i campi semplicemente selezionando gli elementi dal primo livello lo script di convalida genera i valori per il secondo livello in base alla tua scelta al primo livello, lei lo 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."""  

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

Si prega di formattare l'intero codice correttamente.
Marcelo Villa-Piñeros,

è stato fatto, funziona in 10.5.0
Younes Idriss il

Parte del tuo codice è formattata, ma come puoi vedere altre righe non lo sono ( ad esempio le dichiarazioni di importazione del tuo codice). Utilizzare il { }pulsante per formattare correttamente il codice.
Marcelo Villa-Piñeros,

Sembra anche che ti manchi la definizione di una classe.
Marcelo Villa-Piñeros,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.