There is no real difference in applying the ratio to integer or float data. In evaluating results, you should first, be looking at the distributional characteristics of your data and not the visual. If the data is in fact "flat" you should see this in a plot of the probability density function (PDF).
Here is a worked example, using data in the RStoolbox package, that illustrates the expected results from NDWI. Please note that, although the USGS uses the Gao method, I prefer the McFeeters ratio of NIR and Green.
###############################################################
#### Normalized difference water index (NDWI)
# parameters:
# nir - (630 to 690nm) landsat 5&7 band 4
# swir - short-wave infrared 1 (1,550 to 1,750nm), landsat 5&7 band 5
# green - Green (2,090 to 2,350nm), landsat 5&7 band 2
# s – scaling factor (default is NULL)
# method – ("mcfeeters", "gao") Gao is the common method used
# by USGS in level 1 processing
# scale – apply data scaling (default is FALSE)
###############################################################
ndwi <- function(nir = NULL, swir = NULL, green = NULL, s = NULL,
method = c("mcfeeters", "gao"), scale = FALSE) {
if(is.null(nir)) stop("Must define NIR band")
if(class(nir) != "RasterLayer")
stop("Data must be raster class objects")
if(method[1] == "gao" ) {
if(is.null(swir)) stop("Must define SWIR band")
cat("Calculating NDWI using NIR and SWIR")
if(class(swir) != "RasterLayer")
stop("Data must be raster class objects")
i <- (nir - swir) / (nir + swir)
} else if(method[1] == "mcfeeters" ) {
if(is.null(green)) stop("Must define Green band")
cat("Calculating NDWI using NIR and Green")
if(class(green) != "RasterLayer")
stop("Data must be raster class objects")
i <- (green - nir) / (green + nir)
} else {
stop("Not a supported method")
}
if(scale == TRUE) {
i <- (i - cellStats(i, min, asSample=FALSE)) * (1 - -1) /
(cellStats(i, max, asSample=FALSE) -
cellStats(i, min, asSample=FALSE)) + -1
}
if( !is.null(s) ) { i <- s * i }
return( i )
}
Example with at-sensor reflectance correction (float) and without (8-bit integer).
library(raster)
library(RStoolbox)
data(lsat)
metaData <- readMeta(system.file("external/landsat/LT52240631988227CUB02_MTL.txt",package="RStoolbox"))
lsat.ref <- radCor(lsat, metaData = metaData, method = "apref")
ndwi.int <- ndwi(nir=lsat[[4]] , green=lsat[[2]])
ndwi.float <- ndwi(nir=lsat.ref[[4]] , green=lsat.ref[[2]])
par(mfrow=c(2,2))
plot(density(ndwi.int[]),main="distribution of ndwi int")
plot(ndwi.int, main="ndwi from integer")
plot(density(ndwi.float[]),main="distribution of ndwi float")
plot(ndwi.float, main="ndwi from float")
As you can see there is not a notable difference in the index or the resulting distributions. But there is some variation. We can see the specific differences in the distributional moments.
summary(ndwi.int[])
summary(ndwi.float[])
This can likely be attributed to the fact that at-sensor reflectance for level 1 processing also includes dark-object subtraction and changes atmospheric attenuation thus, changing some the characteristics of the data. This is why it is at-sensor reflectance recommended for calculating metrics such as this.
I am not sure why you are seeing a uniform color but, my guess would be a stretch issue in the plot function. You may want to try RStoolbox::ggR plot function, with stretch = "lin", "sqrt" or "log", to see if you get the same result. Also, first check the distribution of the data. If it is flat then there is, in fact, something going sideways in the metric. I included a function for NDWI so, you may want to try it but, that said, your calculation is correct.