Question

Published parameter ATTRLIST in a Tester

  • 10 March 2015
  • 7 replies
  • 2 views

I’ve made a user parameter attributelist, that I use in a NullattributeMapper. Then I want to use a tester wich tests only the attributes that I defined in my parameter. How should I use my published parameter in a Tester? (FME 2015).

 

I would like to know since I want to convert these transformers to a custom transformer.  

 

This way didn't work for me:

 

 

 

 

 

Thanks,

 

 

7 replies

Thanks for your quick response.

 

I want to rout features with missing values different from normal features. The attributes that needs to be checked for missing values has to be a user parameter.

 

I already tried some python myself:

 

 

 

The test: if the selected attributes have the value "missing_attribute". Wich was assigned by the NullAttributeMapper.

 

 

(I also tried the attributeFilter to filter out the missing values. But the attributefilter also only takes 1 attribute as input and not a attributelist specified by a user.)
Userlevel 2
Badge +17
Comments

 

1) Probably <IndentationError> will occur when running. Lines of a method definition have to be indented correctly.

 

2) If a feature had two or more attributes storing "missing_attribute", it will be output repeatedly, because the "self.pyoutput" is called for each "missing_attribute". You should insert "break" (to escape from the loop) after outputting the feature, unless you intend to duplicate a feature which has multiple "missing_attribute". 
Thanks for your comments. That improved my script and it works fine now:

 

 

 

Now i have to make a duplicate of this pythoncaller and change val == "missing_attribute" in val != "missing_attribute" so i can route the normal features.
Userlevel 2
Badge +17
Good to hear your script worked fine.

 

 

The first PythonCaller (val == 'missing_attribute') will output features having an attribute which stores 'missing_attribute'. This probably matches to your requirement.

 

The second one (val != 'missing_attribute'), however, could also output features having an attribute which stores 'missing_attribute', if one of other selected attributes does not store 'missing_attribute'. Is it your expected behavior?

 

 

If your requirement is to classify input features into these two kinds:

 

(1) features having at least one 'missing' attribute

 

(2) others (i.e. all the selected attributes store 'non-missing' value),

 

I would add a flag attribute to the (1) features with a script, expose the flag attribute through the PythonCaller parameter setting (Attributes to Expose),  and then test the flag value with the Tester.

 

-----

 

# Python Script Example

 

class FeatureProcessor(object):

 

    def input(self, feature):

 

        attrlist = feature.getAttribute('ATTRLIST')

 

        attrsplit = attrlist.split(' ')

 

        for attribute in attrsplit:

 

            val = feature.getAttribute(attribute)

 

            if val == 'missing_attribute':

 

                feature.setAttribute('_flag', 1) # add the flag attribute

 

                break

 

        self.pyoutput(feature)

 

-----

 

 

In addition, feature.getAttribute returns 'None' if the specified attribute doesn't exist (i.e. missing). If you will leverage it, the NullAttributeMapper may not be essential.

 

 

One more.

 

When an attribute name contains a whitespace within it, splitting ATTRLIST by whitespace will not work as expected. If an attribute name may contain whitespaces, you will have to consider other approach.

 

FYI.

 

 

Takashi
Thanks for your detailed answer. You described my requirement to classify right.

 

 

The (val != 'missing_attribute') had indeed unexpected behavior.

 

Adding a flag attribute in combination with a tester is a smart solution. I used your script example and it works well.

 

 

 

Splitting by whitespace can indeed give trouble. Thanks for bringing that to my attention. Any hints how to solve that with python? Or can I use transformers?
Userlevel 2
Badge +17
Firstly, if an attribute name may contain whitespaces, the parameter which has been created based on the "Selected Attributes" parameter of the NullAttributeMapper cannot be used, because the name will not be quoted when the parameter value is fetched by the ParameterFetcher.

 

For example, if selected attribute names were A B C and X Y Z, fetched parameter value would be A B C X Y Z. There are no delimiters nor quotations, so it cannot be split into individual names anyhow.

 

 

As a workaround, discard the NullAttributeMapper, and you will have to create a published parameter in the Navigator window manually.

 

Right-click "Published Parameters" > select "Add Parameter" command.

 

 

If you create the parameter with Attribute List (comma delimited) type, fetched parameter value will be "A B C","X Y Z". i.e. the attribute names containing whitespaces will be quoted by double quotations.

 

Then, a PythonCaller with this script adds the flag to the features containing missing attribute, for example.

 

-----

 

def processFeature(feature):

 

    attrList = feature.getAttribute('ATTRLIST')

 

    for attr in [s.strip('"') for s in attrList.split(',')]:

 

        if feature.getAttribute(attr) == None:

 

            feature.setAttribute('_flag', 1)

 

            break

 

-----

 

Note: naturally it doesn't work as expected if an attribute name could contain commas.

 

 

Alternatively, you can also use the TclCaller.

 

If you create the parameter with Attribute List (space delimited) type, fetched parameter value will be "A B C" "X Y Z". It can be used directly as a list structure for a Tcl script.

 

Then, a TclCaller with this script returns the flag value as the "Destination Attribute", for example.

 

-----

 

proc setFlag {} {

 

    foreach attr [FME_GetAttribute "ATTRLIST"] {

 

        if {![FME_AttributeExists $attr]} {return 1}

 

    }

 

}

 

-----

 

 

Hope this helps.
Thanks for pointing out that after using the parameterfetcher, there is indeed no way to separate the attributevalues.

 

 

 

I followed your instructions and with help of your examples I wrote this script:

 

 

 

#-----Python script-----

 

import fme

 

import fmeobjects

 

               

 

# Template Class Interface:

 

class FeatureProcessor(object):

 

    def __init__(self):

 

        pass

 

    def input(self,feature):

 

                               attrlist = feature.getAttribute('ATTRLIST')

 

                               attrsplit = attrlist.split(',')

 

                               for attr in attrsplit:

 

                                               if feature.getAttribute(attr) == None or feature.getAttribute(attr) == '':

 

                                                               feature.setAttribute('_flag', 1)

 

                                                               break   

 

                                               else:

 

                                                               pass

 

                               self.pyoutput(feature)

 

                              

 

    def close(self):

 

        pass

 

#-----Python script------

 

 

 

Using the script withtin this workbench everything works fine:

 

 

 

Now I finally reached my end-goal wich was to create a custom transformer to check missing attributevalues in user specified attributes.

 

Thanks for your support!     

 

 

Reply