Question

Schema mapper attribute range


Badge +22
  • Contributor
  • 1961 replies
Is there a way for the schema mapper to map based on a range of attribute values?

 

 

Essentially 

 

 

MinHeight, MaxHeight, NewValue

 

0,10,Level1

 

10,20, Level2

 

20,30,Level3

 

 

such that a feature with a height of 14.7 would map to Level2.

 

 

The mapping file is an external csv maintained by someone who has no knowledge of FME, and get's updated on avergae every 2 months.

 

 


4 replies

Userlevel 2
Badge +17
Hi,

 

 

If the definition of the range and the NewValue is unchangeable, the AttributeRangeMapper transformer can be used. If not, I don't think there is a transformer that satisfies your purpose, unfortunately. I would use a PythonCaller if I faced the same situation. For example:

 

-----

 

import fmeobjects import csv   class LevelSetter(object):     def __init__(self):         # Read csv rows and initialize the self.rangeMap list.         # The list will contain (MinHeight, MaxHeight, NewValue) tuples.         # Assuming the 'CSV_PATH' parameter holds the csv file path.         self.rangeMap = []         reader = csv.reader(open(str(FME_MacroValues['CSV_PATH']), 'rb'))         reader.next() # read and ignore the csv header         for r in reader:             self.rangeMap.append((float(r[0]), float(r[1]), r[2]))                  def input(self, feature):         # Get height of the feature and set appropriate NewValue (level).         h = float(feature.getAttribute('height'))         for (lower, upper, level) in self.rangeMap:             if lower <= h and h < upper:                 feature.setAttribute('level', level)                 break         self.pyoutput(feature)              def close(self):         pass -----

 

 

Takashi
I had a similar problem and solved it with the PythonCaller (thanks for the tips Takashi!) It would be great however if a future version of the AttributeRangeMapper included that functionality since it would make that transformer even more powerful.

 

 

/Olof
Badge

Hi All. I have a similar question as above (now running fme 2016 or 2017 desktop). Do any new tools in fme since this question was posted in 2013 now provide this functionality or it python still the best option? I have an engineer wanting the same type of solution. ie mapping values in a csv that can be read in at run time and set the range mapper values and an attribute mapper values. Thanks Steve @takashi @olof

Userlevel 2
Badge +17

Hi @goatboy, as far as I know, there is no regular transformer to do that easily, but Python script is not the only way. The InlineQuerier could also work within this workflow.

See also the attached workspace example: attribute-range-map-with-external-table.fmwt (FME 2017.0)

0684Q00000ArKvxQAF.png

Inline Querier | SQL Statement

select    a.*,    b.NewValue as levelfrom source as aleft outer join range as bon b.MinHeight <= a.height and a.height < b.MaxHeight

PythonCaller | Python Script

# 2017-09-12 Updated to run with both Python 2.7 and Python 3.x.import fmeobjectsimport csvclass LevelSetter(object):    def __init__(self):        # Read csv rows and initialize the self.rangeMap list.        # The list will contain (MinHeight, MaxHeight, NewValue) tuples.        # Assuming the 'CSV_PATH' parameter holds the csv file path.        self.rangeMap = []        with open(FME_MacroValues['CSV_PATH'], 'r') as csvfile:            reader = csv.reader(csvfile)            # reader.next() <- deprecated in Python 3.x            for i, r in enumerate(reader):                if 0 < i:                    self.rangeMap.append((float(r[0]), float(r[1]), r[2]))            def input(self, feature):        # Get height of the feature and set appropriate NewValue (level).        h = float(feature.getAttribute('height'))        for (lower, upper, level) in self.rangeMap:            if lower <= h and h < upper:                feature.setAttribute('level', level)                break        self.pyoutput(feature)    def close(self):        pass

Reply