I am using c# GDAL bindings in attempts to read raster values and preform fairly simple calculations. In summary, I would like to get the mean of the values and then get the sum of values below the mean and the sum of values above the mean. Everything appears to work fine except for when I attempt to read the raster to a buffer. The result is producing an array in which every value is -3.402823E+38
The data is float data and i wish to keep that way for my calculations. Code is as follows.
class Program
{
static void Main(string[] args)
{
Gdal.AllRegister();
Ogr.RegisterAll();
Dataset dataset = Gdal.Open(@"xxxxxxxxxxx.tif", Access.GA_ReadOnly);
Band band = dataset.GetRasterBand(1);
int width = band.XSize;
int height = band.YSize;
int size = width * height;
double min = 0.00;
double max = 0.00;
double mean = 0.00;
double stddev = 0.00;
var stats = band.GetStatistics(1, 0, out min, out max, out mean, out stddev);
//Console.WriteLine($"Statistics retrieved and returned a result of {stats}");
Console.WriteLine($"X : {width} Y : {height} SIZE: {size}");
Console.WriteLine($"MIN : {min} MAX : {max} MEAN : {mean} STDDEV : {stddev}");
DataType type = band.DataType;
Console.WriteLine($"Data Type : {type}");
float gtMean = 0; //cut
float ltMean = 0; //fill
float[] data = new float[size];
var dataArr = band.ReadRaster(0, 0, width, height, data, width, height, 0, 0);
int i, j;
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
float value = data[i + j * width];
if (value > (float)mean)
{
gtMean += value;
}
if (value < (float)mean)
{
ltMean += value;
}
}
}
Console.WriteLine($"Sum of values above the mean {gtMean}");
Console.WriteLine($"Sum of values below the mean {ltMean}");
double pixelArea = 0.10763911106;
Console.WriteLine("Press Any Key To Exit....");
Console.ReadLine();
}
}
EDIT / UPDATE
As suggested in the comments the values i was observing represent the no data values. The below script accounts for these values and excludes them from the sums.
class Program
{
static void Main(string[] args)
{
Gdal.AllRegister();
Ogr.RegisterAll();
Dataset dataset = Gdal.Open(@"\\fap2\mapping\GIS\Data\Third Party\AI_PRIME\Carbon_County\19N_91W\Calculated\Block_49_ToFeet_Clip.tif", Access.GA_ReadOnly);
Band band = dataset.GetRasterBand(1);
int width = band.XSize;
int height = band.YSize;
int size = width * height;
double min = 0.00;
double max = 0.00;
double mean = 0.00;
double stddev = 0.00;
double noData = 0.00;
int hasNodata = 0;
band.GetNoDataValue(out noData, out hasNodata);
var stats = band.GetStatistics(1, 0, out min, out max, out mean, out stddev);
//Console.WriteLine($"Statistics retrieved and returned a result of {stats}");
Console.WriteLine($"X : {width} Y : {height} SIZE: {size}");
Console.WriteLine($"MIN : {min} MAX : {max} MEAN : {mean} STDDEV : {stddev}");
Console.WriteLine($"HAS NO DATA : {hasNodata} Value : {noData}");
DataType type = band.DataType;
Console.WriteLine($"Data Type : {type}");
float gtMean = 0; //cut
float ltMean = 0; //fill
float[] data = new float[size];
var dataArr = band.ReadRaster(0, 0, width, height, data, width, height, 0, 0);
float fMean = (float)mean;
float fNoData = (float)noData;
int i, j;
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
float value = data[i + j * width];
if (value != fNoData)
{
if (value > fMean)
{
gtMean += value;
}
else if (value < fMean)
{
ltMean += value;
}
}
}
}
Console.WriteLine($"Sum of values above the mean {gtMean}");
Console.WriteLine($"Sum of values below the mean {ltMean}");
}
}
Best Answer
As Michael Stimson pointed out in his comments,
-3.402823E+38
is the minimum value for a float and should be considered as the no data value in this instance. The inclusion of these values drastically effects the values in which we are attempting to solve for.Below is a working example. For context, the program bellow attempts a simple cut/fill analysis on a DEM initiated at the mean elevation. In other words it is analyzing values above and below the mean. The tif being used was clipped to a specific area and the z values where converted to feet in preparation for this analysis. The raster's resolution is 10 cm. Furthermore, the code posted in the initial question was not properly summing the values above and below the mean. This has also been corrected below.