Solved

Coordinate System Units

  • 16 February 2021
  • 14 replies
  • 36 views

Badge +3

So in the Coordinate System Gallery, one can see what units that coordinate system uses (ex: foot, meter, etc.). I need to access the unit of the picked system programatically so I can perform conversions if needed, but I don't see this information available as a feature attribute or property. Is this possible in any way, perhaps with some custom python? Thanks.

icon

Best answer by dbaldacchino1 17 February 2021, 01:25

View original

14 replies

Userlevel 1
Badge +21

It's not very straightforward, but if you use a CoordinateSystemExtractor, followed by a CoordinateSystemDescriptionConverter and convert to OGC WKT you get some text where you should be able to extract the units

Badge +3

Thanks @ebygomm​ , I also just found a custom transformer in FME HUB that does just what you described: CoordinateSystemMapUnitExtractor. It then uses some regex to find the units...exactly what I thought of doing but didn't realize how you can get to the description data. This custom transformer uses PROJ.4 String but I'll try your suggestion (prefer not to use custom transformers if I don't have to!)

Userlevel 1
Badge +21

An alternative python solution (I've not delved too deeply, so don't know if there's a better way of parsing the parameters or returning the units directly). This finds the coordinate system from a feature, but you could return that from an attribute or parameter instead

import fme
import fmeobjects
 
def findUnit(feature):
    coordsys = feature.getCoordSys()
    coordsysManager = fmeobjects.FMECoordSysManager()
    parameters = coordsysManager.getCoordSysParms(coordsys)
    unit = parameters.index("UNIT")
    
    feature.setAttribute("Unit",parameters[unit+1])

 

Badge +3

An alternative python solution (I've not delved too deeply, so don't know if there's a better way of parsing the parameters or returning the units directly). This finds the coordinate system from a feature, but you could return that from an attribute or parameter instead

import fme
import fmeobjects
 
def findUnit(feature):
    coordsys = feature.getCoordSys()
    coordsysManager = fmeobjects.FMECoordSysManager()
    parameters = coordsysManager.getCoordSysParms(coordsys)
    unit = parameters.index("UNIT")
    
    feature.setAttribute("Unit",parameters[unit+1])

 

I'd have to play around a bit...only know enough Python to be dangerous. I think we need a CoordinateSystemPropertiesExtractor transformer, don't you think?! That would make life easier!

Badge +3

An alternative python solution (I've not delved too deeply, so don't know if there's a better way of parsing the parameters or returning the units directly). This finds the coordinate system from a feature, but you could return that from an attribute or parameter instead

import fme
import fmeobjects
 
def findUnit(feature):
    coordsys = feature.getCoordSys()
    coordsysManager = fmeobjects.FMECoordSysManager()
    parameters = coordsysManager.getCoordSysParms(coordsys)
    unit = parameters.index("UNIT")
    
    feature.setAttribute("Unit",parameters[unit+1])

 

There, posted :) https://community.safe.com/s/idea/0874Q000000j0VQQAY/detail

Badge +3

Here's an example that gets the job done. Tested on all the different variations of units. Also extracts the unit "number" for conversion purposes.CoordSys_Units

Badge +3

So turns out that the file "coordsys.db" is a | delimited text file. Since I want to do some processing in the workspace based on the units (which I can extract with the above), I wanted to generate all the permutations possible (8,870 coordinate systems in that file) so I read it in as a text file, used regex to extract the coordinate system name, then ran all those features through the above and finally used a DuplicateFilter to find all the unique units. I'm attaching the results file just in case it's of value to anyone reading this discussion.

Userlevel 1
Badge +21

So turns out that the file "coordsys.db" is a | delimited text file. Since I want to do some processing in the workspace based on the units (which I can extract with the above), I wanted to generate all the permutations possible (8,870 coordinate systems in that file) so I read it in as a text file, used regex to extract the coordinate system name, then ran all those features through the above and finally used a DuplicateFilter to find all the unique units. I'm attaching the results file just in case it's of value to anyone reading this discussion.

Your regex isn't working quite correctly as some of those units, e.g. SECOND should be 4.84814E-06

Badge +3

Your regex isn't working quite correctly as some of those units, e.g. SECOND should be 4.84814E-06

Hi @ebygomm​ , thanks for catching that! I was looking only for digits. I'll look into it and update the affected files above.

Badge +3

Your regex isn't working quite correctly as some of those units, e.g. SECOND should be 4.84814E-06

The posts above were updated with new files. MicroInch was also incorrect because of the non-digit characters. All good now (you can see the updated regex). Thanks again for looking at the details!

Userlevel 1
Badge +21

Your regex isn't working quite correctly as some of those units, e.g. SECOND  should be 4.84814E-06

This is how I've got that info in the past

import fme
import fmeobjects
 
class FeatureProcessor(object):
    def __init__(self):
        pass
    def input(self,feature):
        pass
    def close(self):
        units = []
        coordsysManager = fmeobjects.FMECoordSysManager()
        coordsystems = coordsysManager.getCoordSysList()
        for s in coordsystems:
          p = coordsysManager.getCoordSysParms(s)
          unit = p[p.index("UNIT")+1]
          if unit not in units:
              units.append(unit)
        units.sort()
        for u in units:
            feature = fmeobjects.FMEFeature()
            lst = coordsysManager.getUnitParms(u)
            dict = {lst[i]:lst[i+1] for i in range(0,len(lst),2)}
            feature.setAttribute("UNIT",u)
            feature.setAttribute("UNIT_TYPE",dict["UNIT_TYPE"])
            feature.setAttribute("UNIT_ABBREVIATION",dict["UNIT_ABBREVIATION"])
            feature.setAttribute("UNIT_FACTOR",dict["UNIT_FACTOR"])
            self.pyoutput(feature)

 

Badge +3

Your regex isn't working quite correctly as some of those units, e.g. SECOND should be 4.84814E-06

Thanks a lot for that. I'm curious though as to why these results differ from what is obtained via parsing the data from the CoordinateSystemDescriptionConverter?

Userlevel 1
Badge +21

Your regex isn't working quite correctly as some of those units, e.g. SECOND should be 4.84814E-06

I did notice a couple of differences but these were units that were of type angle, they seemed to be in radians one place and degrees the other (I forget which way round)

Badge +3

Your regex isn't working quite correctly as some of those units, e.g. SECOND should be 4.84814E-06

I'm seeing quite a few differences in the name and units themselves, and the quantity of units. I would have expected both methods to yield the exact same results since the Python method is also accessing the FME library of coordinate systems itself. Anyway I stuck with extracting the data from the selected coordinate system itself per the above non-Python method. As a use-case: I am downloading Open Street Map data, reprojecting, then extruding polygons that have a height (in meters), so I need to know what the coordinate system's units are to convert appropriately. Here's an example of picking a weird CS (wrong for the area but it's just a test) and making sure the math checks out.

SiteExtents_CoordSys Units and Heights

Reply