“用于栅格操作的Python FME对象API”的答案 https://knowledge.亚搏在线safe.com/questions/38000/python-fme-objects-api-for-raster-manipulation.html “用于栅格操作的Python FME对象API”问题的最新答案 由Daveatsafe回答亚搏在线 https://knowledge.亚搏在线safe.com/answers/41015/view.html

@takashi,你是正确的。但是,我们的光栅开发团队想要澄清一些事情:

获取光栅数据有两个方面:填充者(即满足数据请求的东西)和消费者(即请求数据的东西)。
对填充器的请求总是由使用者驱动的。也就是说,除非有人请求数据,否则不会进行数据请求。消费者可以自由地要求更多或更少的数据。虽然填充器通常期望有
ceil(光栅行数/每个tile的行数)x ceil(光栅列数/每个tile的列数)
' getTile '调用,但情况并非总是如此。例如,消费者可能只关心数据的某个子集,例如光栅是否被剪切。
我还想添加一些关于如何使用平铺大小的更多细节。
平铺大小基本上是访问数据的最有效方式。例如,' PNG '读取器的填充器的平铺大小总是为' <列数> x 1 row`, since that is how PNG data is stored.
From the perspective of an `FMEBandTilePopulator` author, tile size has an impact on how `getTile` will be implemented. The `getTile` call must always return a tile that is the same size as the one passed in. However, the `FMEBandTilePopulator` has some control over what tile sizes will be passed in, through a few properties on the corresponding `FMEBandProperties` object: `tileType`, `numTileCols`, `numTileRows`
- When `tileType` is `FME_TILE_TYPE_FIXED`, the `FMEBandTilePopulator` will only be passed tiles that are `numTileCols x numTileRows` in size, and where `startRow` and `startCol` align with tile size boundaries
- When `tileType` is `FME_TILE_TYPE_FIXED_MULTIPLE`, the `FMEBandTilePopulator` will only be passed tiles that are `(N x numTileCols) x (M x numTileRows)` in size. For example, if the reported tile size is 5x7, the `FMEBandTilePopulator` could get passed a tile that is 10x7 or 5x14 or 10x14, etc. Similar to `FME_TILE_TYPE_FIXED`, `startRow` and `startCol` will align with tile size boundaries
- When `tileType` is `FME_TILE_TYPE_FLEXIBLE`, the `FMEBandTilePopulator` may be passed tiles of any size that are not guaranteed to be aligned with tile size boundaries
Consumers of raster data have it easy: they don't have to worry about any of these tile size considerations. They are free to request tiles of any size and alignment, and it is up to FME to reconcile these requests with a size that works for the populator. From the consumer's perspective, the tile size reported by `FMEBandProperties` is simply a recommendation: using the reported size may result in better performance or lower memory usage.

星期三,2017年3月8日23:13:06 GMT daveat亚搏在线safe
答案由隆 https://knowledge.亚搏在线safe.com/answers/40965/view.html.

Hi @DaveAtSafe,感谢您关于每个Tile的行数的回复

OK。我知道一个光栅带的数据内容可以包含一个或多个块。FMEBandTilePopulator.getTile()方法将被调用多次当填充数据内容的乐队,如果行/列的数量<强>每瓦< /强>设置为乐队的数量小于光栅的行/列<强> < / >强。方法调用的数量等于块的数量。即< / p > < >以前装天花板(光栅的行数/每瓦的行数)x装天花板(光栅的列数/每瓦列数)< / pre > < p >和起始行/列索引在给定的数据将通过参数传递矩阵和大小(startRow startCol,瓷砖)getTile()方法用于创建每个瓷砖。因此,在我的练习中,MyUInt8BandTilePopulator.getTile()方法也可以像这样使用参数定义,这个定义允许每个tile指定任意数量的行/列作为band属性。

class MyUInt8BandTilePopulator(fmeobjects.FMEBandTilePopulator): def __init__(self, dataArray): self. class MyUInt8BandTilePopulator(fmeobjects.FMEBandTilePopulator):datarray = datarray def clone(self): return MyUInt8BandTilePopulator(self.dataArray) def getTile(self, startRow, startCol, tile): numRows, numCols = tile. getnumrows (), tile. getnumcols () endRow, endCol = startRow + numRows, startCol + numCols data = [self. dataArray];datarearray [r][startCol:endCol] for r in range(startRow, endRow)] newTile = fmeobjects. datarearray [r][startCol:endCol] for r in range(startRow, endRow)]FMEUInt8Tile(numRows, numCols) newTile. setdata (data)返回newTile 

是否正确?< / p > < p > < / p > < p > < / p > 格林尼治标准时间2017年3月8日星期三00:07:44 答案由隆 https://knowledge.亚搏在线safe.com/answers/40871/view.html

计算细胞值统计的示例。< / p >

[Fixed: 2017-03-15]

# PythonCaller Script Example: Statistics of Raster Cell Values # Calculate fundamental statistics of cell values (except Nodata) # in the band(s) of the input raster. # This example only supports REAL64 and REAL32 but you can enhance # it easily if necessary. import fmeobjects, math class RasterBandStatisticsCalculator(object): def __init__(self): self.keys = [ 'interpretation', 'nodata', 'count', 'sum', 'min', 'max', 'range', 'median', 'mean', 'stdev', 'stdevp', ] # Returns a tuple (tile object, interpretation name). # This method returns (None, 'Unsupported') # when the specified interpretation was not supported, def tileAndInterpretation(self, interpretation, numRows, numCols): if interpretation == fmeobjects.FME_INTERPRETATION_REAL64: return (fmeobjects.FMEReal64Tile(numRows, numCols), 'REAL64') elif interpretation == fmeobjects.FME_INTERPRETATION_REAL32: return (fmeobjects.FMEReal32Tile(numRows, numCols), 'REAL32') ###################################################### # Add other interpretations here if necessary. ###################################################### else: return (None, 'Unsupported') # Returns a dictionary containing the statistics of specified band. def calculateStatistics(self, band, numRows, numCols): # Get the band properties. bandProperties = band.getProperties() interpretation = bandProperties.getInterpretation() # Create a tile that will be used to get cell values of the band. # The interpretation, number of rows, and number of columns # have to be consistent with the band properties. tile, interpret = self.tileAndInterpretation(interpretation, numRows, numCols) stats = {'interpretation': interpret} if tile != None: # Get all the cell values except Nodata as a list. values = [] nodataValue = band.getNodataValue() if nodataValue == None: for data in band.getTile(0, 0, tile).getData(): values += data else: nodata = nodataValue.getData()[0][0] for data in band.getTile(0, 0, tile).getData(): values += [v for v in data if v != nodata] stats['nodata'] = nodata # Calculate statistics. values.sort() count = len(values) stats['count'] = count if 0 < count: total = sum(values) stats['sum'] = total stats['min'] = values[0] stats['max'] = values[-1] stats['range'] = (values[-1] - values[0]) # Median m = count // 2 stats['median'] = (values[m] if count % 2 == 1 else (values[m-1] + values[m]) * 0.5) # Mean (average) avrg = float(total) / count stats['mean'] = avrg # Standard Deviation if 1 < count: s = sum([(v - avrg)**2 for v in values]) stats['stdev'] = math.sqrt(s / (count - 1)) stats['stdevp'] = math.sqrt(s / count) return stats def input(self, feature): raster = feature.getGeometry() if isinstance(raster, fmeobjects.FMERaster): rasterProperties = raster.getProperties() numRows = rasterProperties.getNumRows() numCols = rasterProperties.getNumCols() for i in range(raster.getNumBands()): stats = self.calculateStatistics(raster.getBand(i), numRows, numCols) for key in self.keys: attr = '_band{%d}.%s' % (i, key) if key in stats: feature.setAttribute(attr, stats[key]) else: feature.setAttributeNullWithType(attr, fmeobjects.FME_ATTR_REAL64) self.pyoutput(feature) 

Sun, 05 Mar 2017 02:00:37 GMT
答案由filatsafe亚搏在线 https://knowledge.亚搏在线safe.com/answers/40857/view.html

感谢Takashi为FME 2017.0突出了FME对象Python API中新增的光栅。伟大的示例应用程序!我只是想让大家知道,更新的2017.0 Python API文档,包括新的光栅API,现在可以在https://docs.safe.com/fme/html/FME_Objects_Python_API/index.html

在线访问亚搏在线
星期五,2017年3月03日23:26:00 GMT filat亚搏在线safe
答案由隆 https://knowledge.亚搏在线safe.com/answers/40622/view.html.

第二个练习:计算单元值,将调色板附加到标注栏,然后尝试光栅工具。从Conway的人生游戏

FME挑战:生活游戏

亚搏在线#蟒蛇骑士脚本示例:康威的生活游戏#FME 2017.0 RC构建17254,2017-02-28#每个输出功能都包含一个表示活/死细胞的光栅光栅只有一个波段,波段有一个调色板假设输入功能具有这些属性1.发电量(0<;整数):要处理的代数2.numRows(0<;整数):结果光栅中的行数3.numCols(0<;整数):结果光栅中的列数4.初始速率(0<;雷亚尔<;1) :第一代活细胞的比率将在输出特征中添加一个名为“_generation”的新属性,该属性存储表示生成顺序的基于1的序列号。导入fmeobjects,随机类MyUInt8BandTilePopulator(fmeobjects.FMEBandTilePopulator):def_uuinit_uu(self,dataArray):self.dataArray=dataArray def clone(self):返回MyUInt8BandTilePopulator(self.dataArray)def getTile(self,startRow,startCol,tile):numRows,numCols=len(self.dataArray),len(self.dataArray[0])newfile=fmeobjects.FMEUInt8Tile(numRows,numCols)newfile.setData(self.dataArray)返回newfile类ConwaysGameOfLife(object):def uuu init__;(self):self.rasterTools=fmeobjects.FMERasterTools()def输入(self,feature):#从feature属性获取参数。numGenerations=int(feature.getAttribute('numGenerations'))self.numRows=int(feature.getAttribute('numRows'))self.numCols=int(feature.getAttribute('numCols'))self.initialRate=float(feature.getAttribute('initialRate'))如果0<;numGenerations\和0<;self.numRows和0<;self.numCols\和0.0<;=self.initialRate和self.initialRate<;=1.0:self.initialize()outNumRows,outNumCols=self.numRows*10,self.numCols*10光栅=范围内i无(numGenerations):光栅=self.nextGeneration(光栅)功能。setGeometry(self.rasterTools.resampleByRowCol(outNumRows,outNumCols,fmeobjects.FME_插值_NearestNearest Nearest Neighbork,光栅))功能。setAttribute(“U generation”,i+1)self.pyoutput(feature)else:feature.setAttribute(“U错误”,“无效参数”)self.pyoutput(feature)def initialize(self):#光栅属性xspace,yspace=1.0,1.0 xCellOrigin,yCellOrigin=0.5,0.5 xOrigin,yOrigin=0.0,0 x旋转,yRotation=0.0,0.0 self.rasterprivaties=fmeobjects.fmeraderprivaties.fmeraderproperties(self.numRows,self.numCols、xspace、yspace、xCellOrigin、yCellOrigin、xOrigin、yOrigin、xRotation)#频带属性self.bandProperties=fmeobjects.FMEBandProperties(‘生命游戏’、fmeobjects.FME_解释单元8、fmeobjects.FME_TILE_TYPE_固定、self.numRows、,self.numCols)#创建一个调色板对象,表示:#-------------------------RGB24#0 220220220#1 128,0,0#------key=fmeobjects.FMEUInt8Tile(1,2)key.setData([[0,1]])value=fmeobjects.fmergb24file(1,2)value.setData([[220220,128,0,0,0,]])self.palete=fmeobjects.FMEPalette(“”,值)#返回表示下一代的光栅,如果参数为无,则返回表示第一代的光栅。def下一代(自我,prevRaster):nextData=[]如果prevRaster==None:num=self.numRows*self.numCols alives=int(num*self.initialRate)seed=[1代表范围内的i(alives)]+[0代表范围内的i(num-alives)]随机。对[i*self.numCols代表范围内的i(self.numRows)]:nextData.append(seed[s:s+seed.numCols])否则:#获取上一代。tile=fmeobjects.FMEUInt8Tile(self.numRows,self.numCols)prevData=prevgraster.getBand(0).getTile(0,0,tile.getData()#创建一个临时数据数组,其大小为每边放大一行/列#上一个光栅的顶部、底部、左侧和右侧,并将0设置为所有附加的外部边缘单元格。#这种数据数组可以很容易地计算每个单元在上一代中存活的相邻单元数。tmp=[[0表示范围内的i(self.numCols+2)]\+[[0]+数据+[0]表示范围内的数据]\+[[0表示范围内的i(self.numCols+2)]\ \为下一代创建新的数据数组。对于范围内的i(self.numRows):行=[]对于范围内的j(self.numCols):#计算上一代中存活的相邻单元的数量,然后根据游戏规则确定该单元在下一代中是否可以存活。n=tmp[i+0][j]+tmp[i+0][j+1]+tmp[i+0][j+2]\+tmp[i+1][j+2]\+tmp[i+2][j]+tmp[i+2][j+1]+tmp[i+2][j+2]如果上一个数据[i][j]=1:行。追加(如果[2,3]中有n,则追加1)其他:行。追加(如果n==3,则追加1)下一个数据。追加(行)turn a raster containing a single band. raster = fmeobjects.FMERaster(self.rasterProperties) band = fmeobjects.FMEBand(MyUInt8BandTilePopulator(nextData), self.rasterProperties, self.bandProperties) band.appendPalette(self.palette) # Add a palette to the band. raster.appendBand(band) return raster 

2017年2月28日星期二10:11:13 GMT
答案由隆 https://knowledge.亚搏在线safe.com/answers/40565/view.html

我会分享我的第一个练习,了解如何使用API​​创建一个新的光栅几何。

#pythoncreator脚本示例:创建包含栅格#的功能栅格将有一个带uint8的单个频段解释。导入fmeobjects#定义从fmebandtilepopulator类派生的具体类。#此类的实例将用于创建图块#并将其填充到频带(FMEBABRIAD)。类Myuint8BandTilePupulator(fmeobjects.fmebandtilepopulator):def __init __(self,dataArray):self.dataArray = dataArray#实施'克隆'方法。#在创建新频段时将多次调用。def clone(self):返回myuint8bandtilepopulator(self.dataArray)#impler'gettile'方法。#您可以在此处创建包含所需内容的新图块。#使用参数并不重要:Startrow,startcol,瓷砖。def gettile(self,startrow,startcol,瓷砖):numrows,numcols = len(self.dataArray),len(self.dataArray [0])newtile = fmeobjects.fmeuint8tile(numrows,numcols)newtile.setdata(self.dataArray) return newTile # The following two methods won't be called while creating a new band. # It seems not to be essential to implement these methods in this case, # although the API doc says "This method must be implemented # in the FMEBandTilePopulator subclass". def setDeleteSourceOnDestroy(self, deleteFlag): pass def setOutputSize(self, rows, cols): return (rows, cols) class FeatureCreator(object): def __init__(self): pass def close(self): # Contents of a tile for a band to be created. # A list of row data, each element is a list of column values. dataArray = [ [ 0, 128, 0, 128, 0, 128, 0], [128, 0, 128, 0, 128, 0, 128], [ 0, 128, 0, 128, 0, 128, 0], [128, 0, 128, 0, 128, 0, 128], [ 0, 128, 0, 128, 0, 128, 0], ] # Properties of a raster to be created. numRows, numCols = len(dataArray), len(dataArray[0]) # resolution xSpacing, ySpacing = 10.0, 10.0 # cell spacing in ground units xCellOrigin, yCellOrigin = 0.5, 0.5 # cell origin coordinates xOrigin, yOrigin = 0.0, numRows * ySpacing # left-top coordinates xRotation, yRotation = 0.0, 0.0 # rotation angle in degrees # Create a new raster. rasterProperties = fmeobjects.FMERasterProperties(numRows, numCols, xSpacing, ySpacing, xCellOrigin, yCellOrigin, xOrigin, yOrigin, xRotation, yRotation) raster = fmeobjects.FMERaster(rasterProperties) # Create a new band and append it to the raster. # It's optional to specify Nodata value when creating a band. bandTilePopulator = MyUInt8BandTilePopulator(dataArray) bandName = 'My UInt8 Band' # can be set to empty. bandProperties = fmeobjects.FMEBandProperties(bandName, fmeobjects.FME_INTERPRETATION_UINT8, fmeobjects.FME_TILE_TYPE_FIXED, numRows, numCols) nodataValue = fmeobjects.FMEUInt8Tile(1, 1) nodataValue.setData([[0]]) band = fmeobjects.FMEBand(bandTilePopulator, rasterProperties, bandProperties, nodataValue) raster.appendBand(band) # Create and output a feature containing the raster created above. feature = fmeobjects.FMEFeature() feature.setGeometry(raster) self.pyoutput(feature) 

2017年2月27日星期一08:18:28 GMT
danilo_fme回答 https://knowledge.亚搏在线safe.com/answers/40548/view.html. < p >神奇。

我将使用它!< / p > 2017年2月24日星期五20:18:07 GMT danilo_fme David_r回答 https://knowledge.亚搏在线safe.com/answers/38094/view.html 哇,是的,这真是个好消息!< / p > 2017年1月3日星期二09:33:21 GMT David_r. 答案由daleatsafe亚搏在线 https://knowledge.亚搏在线safe.com/answers/38005/view.html 很高兴你找到了。圣诞快乐!我们很高兴向Pythonistas开放光栅操作。额外的好处是——您可以使用Python 3中的任何一个。x或2。x !< / p > 太阳,2016年12月25日17:55:54 GMT daleat亚搏在线safe