Radius of gyration (in the field of ecology) is a measure of the spatial extent of a habitat patch, and is defined as the mean distance between each cell in the patch and the patch centroid (cell-center to cell-center distance).
Can anyone suggest an efficient way to calculate this metric from a raster where patches have a value 1 and the background has a value of 0?
My current model uses the following series of processes, but is clunky and requires a hefty processing time. See below:
- Convert raster layer to polygon to find the centroid of each patch (Raster to Polygon, Feature to Point.
- Convert raster layer to point to find cell centers of each cell (Raster to Point).
- Find the cell center that is closest to the centroid (Near).
- Calculate distance between the cell center closest to the centroid and every other cell center in the patch (Point Distance).
- Calculate mean of the resulting table of distances (Summary Statistics)
This is all very clunky and time-consuming given the multiple conversions necessary and the number of patches I need to calculate. I am guessing there is a faster and more efficient way to perform this calculation, as other programs like FragStats can do it very rapidly.
Answer
The workflow below:
- is super fast, because it is raster based
- unlike vector approach, that you are using, it will handle the situation with biggie sitting next to a small patch, when cells of the former are closer to centre of small pacth
INPUT BINARY RASTER:
Note: I removed background values of 0.
WORKFLOW:
arcpy.gp.RegionGroup_sa("binary","C:/FELIX_DATA/SCRARCH/GROUPS","EIGHT","WITHIN","NO_LINK","#")
arcpy.gp.SingleOutputMapAlgebra_sa("$$XMAP","C:/FELIX_DATA/SCRARCH/X","#")
arcpy.gp.SingleOutputMapAlgebra_sa("$$YMAP","C:/FELIX_DATA/SCRARCH/Y","#")
arcpy.gp.ZonalStatistics_sa("GROUPS","VALUE","X","C:/FELIX_DATA/SCRARCH/xMean","MEAN","DATA")
arcpy.gp.ZonalStatistics_sa("GROUPS","VALUE","Y","C:/FELIX_DATA/SCRARCH/yMean","MEAN","DATA")
arcpy.gp.RasterCalculator_sa("""Power(("X" - "xMean")*("X" - "xMean")+("Y" - "yMean")*("Y" - "yMean"),0.5)""","C:/FELIX_DATA/SCRARCH/distance")
arcpy.gp.ZonalStatisticsAsTable_sa("GROUPS","VALUE","distance","C:/FELIX_DATA/SCRARCH/stats.dbf","DATA","MEAN")
arcpy.RasterToPolygon_conversion("GROUPS","C:/FELIX_DATA/SCRARCH/polygons.shp","SIMPLIFY","VALUE")
arcpy.AddField_management("POLYGONS","R_GYR","FLOAT","#","#","#","#","NULLABLE","NON_REQUIRED","#")
arcpy.AddJoin_management("POLYGONS","GRIDCODE","stats","VALUE","KEEP_ALL")
arcpy.CalculateField_management("POLYGONS","polygons.R_GYR","[stats.MEAN]","VB","#")
OUTPUT PATCHES WITH COMPUTED RADIUS:
Very little efforts required to bring it to Python, where by importing spatial analyst tools one can use in memory rasters, e.g. first line will look something like this:
outRegionGrp = RegionGroup(binary, "EIGHT")
If you have to repeat this process, I suggest scripting it.
No comments:
Post a Comment