Raster Analysis#
Histogram#
This script reads a raster in blocks, collects pixel values (excluding NoData), and creates a histogram using matplotlib.
import arcpy
import numpy
import matplotlib.pyplot as plt
ras = r'C:\image.tif'
desc = arcpy.Describe(ras)
ext = desc.Extent
xmin = ext.XMin
ymin = ext.YMin
rows = desc.height
cols = desc.width
width = desc.meanCellWidth
height = desc.meanCellHeight
sp_ref = desc.spatialReference
NoData = desc.noDataValue
block = 1000
xBSize = block
yBSize = block
values = []
for i in range(0, rows, yBSize):
if i + yBSize < rows:
numRows = yBSize
else:
numRows = rows - i
for j in range(0, cols, xBSize):
if j + xBSize < cols:
numCols = xBSize
else:
numCols = cols - j
xtile = xmin + (j * width)
ytile = ymin + (i * height)
lowleft = arcpy.Point(xtile, ytile)
array = arcpy.RasterToNumPyArray(ras, lowleft, numCols, numRows)
array = array[numpy.where(array != NoData)]
values = values + list(array)
fig, ax = plt.subplots(figsize=(10, 10))
b = list(numpy.arange(-1, 1, 0.1)) # Set bin classes
n, bins, patches = ax.hist(values, color='lime', bins=b)
ax.xaxis.set_major_locator(plt.MaxNLocator(10)) # Set number of X tick labels
ax.set_xlim(-1, 1)
ax.set_ylim(0, 100)
# Add labels above bars
for i in range(0, len(n)):
x_pos = bins[i] + ((bins[i + 1] - bins[i]) / 2)
y_pos = n[i] + (n[i] * 0.1)
label = str(int(n[i]))
ax.text(x_pos, y_pos, label, horizontalalignment='center', fontsize=9)
plt.show()
Note
The block-based approach is essential for large rasters that don’t fit entirely into memory. Adjust the block variable (default 1000 pixels) based on your available RAM and raster size.