Skip to content

Commit

Permalink
fix formatting issue with one of the R chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
bhass-neon committed Feb 4, 2024
1 parent f816668 commit 03f5f2e
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 122 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## ----load-libraries, message=FALSE, warning=FALSE------------------------------------------------------------------------------------------------------------------------
## ----load-libraries, message=FALSE, warning=FALSE----------------------------------------------------------------------------------------------------------------------------

# load required packages
library(rhdf5)
Expand All @@ -13,7 +13,7 @@ wd <- "~/data/"
setwd(wd)


## ----download-h5, eval=FALSE---------------------------------------------------------------------------------------------------------------------------------------------
## ----download-h5, eval=FALSE-------------------------------------------------------------------------------------------------------------------------------------------------
## byTileAOP(dpID = 'DP3.30006.001',
## site = 'SJER',
## year = '2021',
Expand All @@ -22,7 +22,7 @@ setwd(wd)
## savepath = wd)


## ----read-h5-------------------------------------------------------------------------------------------------------------------------------------------------------------
## ----read-h5-----------------------------------------------------------------------------------------------------------------------------------------------------------------
# define filepath to the hyperspectral dataset
h5_file <- paste0(wd,"DP3.30006.001/neon-aop-products/2021/FullSite/D17/2021_SJER_5/L3/Spectrometer/Reflectance/NEON_D17_SJER_DP3_257000_4112000_reflectance.h5")

Expand All @@ -46,11 +46,11 @@ plotRGB(rgbStack,
stretch = "lin")


## ----dev-new, eval=FALSE-------------------------------------------------------------------------------------------------------------------------------------------------
## ----dev-new, eval=FALSE-----------------------------------------------------------------------------------------------------------------------------------------------------
## dev.new(noRStudioGD = TRUE)


## ----click-to-select, eval=FALSE, comment=NA-----------------------------------------------------------------------------------------------------------------------------
## ----click-to-select, eval=FALSE, comment=NA---------------------------------------------------------------------------------------------------------------------------------

# change plotting parameters to better see the points and numbers generated from clicking
par(col="red", cex=2)
Expand All @@ -59,23 +59,22 @@ par(col="red", cex=2)
plotRGB(rgbStack, r=1, g=2, b=3, scale=300, stretch = "hist")

# use the 'click' function
c <- click(rgbStack, n = 7, id=TRUE, xy=TRUE, cell=TRUE, type="p", pch=16, col="red", col.lab="red")
c <- click(rgbStack, n = 6, id=TRUE, xy=TRUE, cell=TRUE, type="p", pch=16, col="red", col.lab="red")





## ----convert-cell-to-row-column------------------------------------------------------------------------------------------------------------------------------------------
## ----convert-cell-to-row-column----------------------------------------------------------------------------------------------------------------------------------------------
# convert raster cell number into row and column (used to extract spectral signature below)
c$row <- c$cell%/%nrow(rgbStack)+1 # add 1 because R is 1-indexed
c$col <- c$cell%%ncol(rgbStack)


## ----extract-spectral-signaures------------------------------------------------------------------------------------------------------------------------------------------
## ----extract-spectral-signatures---------------------------------------------------------------------------------------------------------------------------------------------

# create a new dataframe from the band wavelengths so that we can add the reflectance values for each cover type
pixel_df <- as.data.frame(wavelengths)

# loop through each of the cells that we selected
for(i in 1:length(c$cell)){
# extract spectral values from a single pixel
Expand All @@ -100,8 +99,7 @@ pixel_df <- cbind(pixel_df,b[2])
## ----plot-spectral-signatures, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types: Water, Tree, Grass, Soil, Roof, and Road. The x-axis is wavelength in nanometers and the y-axis is reflectance."----
# Use the melt() function to reshape the dataframe into a format that ggplot prefers
pixel.melt <- reshape2::melt(pixel_df, id.vars = "wavelengths", value.name = "Reflectance")

# Now, let's plot some spectral signatures!
# Now, let's plot the spectral signatures!
ggplot()+
geom_line(data = pixel.melt, mapping = aes(x=wavelengths, y=Reflectance, color=variable), lwd=1.5)+
scale_colour_manual(values = c("blue3","green4","green2","tan4","grey50","black"),
Expand All @@ -112,32 +110,28 @@ ggplot()+
xlab("Wavelength")


## ----mask-atmospheric-absorption-bands, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types: Water, Tree, Grass, Soil, Roof, and Road. Added to the plot are two greyed-out rectangles in regions near 1400nm and 1850nm where the reflectance measurements are obscured by atmospheric absorption. The x-axis is wavelength in nanometers and the y-axis is reflectance."----
## ----mask-atmospheric-absorption-bands, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types: Water, Tree, Grass, Soil, Roof, and Road. This plot includes two greyed-out rectangles in regions near 1400nm and 1850nm where the reflectance measurements are obscured by atmospheric absorption. The x-axis is wavelength in nanometers and the y-axis is reflectance."----

# grab reflectance metadata (which contains absorption band limits)
reflMetadata <- h5readAttributes(h5_file,"/SJER/Reflectance" )

ab1 <- reflMetadata$Band_Window_1_Nanometers
ab2 <- reflMetadata$Band_Window_2_Nanometers

# Plot spectral signatures again with rectangles showing the absorption bands
# Plot spectral signatures again with grey rectangles highlighting the absorption bands
ggplot()+
geom_line(data = pixel.melt, mapping = aes(x=wavelengths, y=Reflectance, color=variable), lwd=1.5)+
geom_rect(mapping=aes(ymin=min(pixel.melt$Reflectance),ymax=max(pixel.melt$Reflectance), xmin=ab1[1], xmax=ab1[2]), color="black", fill="grey40", alpha=0.8)+
geom_rect(mapping=aes(ymin=min(pixel.melt$Reflectance),ymax=max(pixel.melt$Reflectance), xmin=ab2[1], xmax=ab2[2]), color="black", fill="grey40", alpha=0.8)+
scale_colour_manual(values = c("blue3","green4","green2","tan4","grey50","black"),
labels = c("Water","Tree","Grass","Soil","Roof","Road"))+
labs(color = "Cover Type")+
ggtitle("Land cover spectral signatures")+
ggtitle("Land cover spectral signatures with\n atmospheric absorption bands greyed out")+
theme(plot.title = element_text(hjust = 0.5, size=20))+
xlab("Wavelength")


## ----remove-absorption-band-reflectances, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types. Values falling within the two rectangles from the previous image have been set to NA and ommited from the plot. The x-axis is wavelength in nanometers and the y-axis is reflectance."----

## ----remove-absorption-band-reflectances, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types. Values falling within the atmospheric absorption bands have been set to NA and ommited from the plot. The x-axis is wavelength in nanometers and the y-axis is reflectance."----
# Duplicate the spectral signatures into a new data.frame
pixel.melt.masked <- pixel.melt

# Mask out all values within each of the two atmospheric absorption bands
pixel.melt.masked[pixel.melt.masked$wavelengths>ab1[1]&pixel.melt.masked$wavelengths<ab1[2],]$Reflectance <- NA
pixel.melt.masked[pixel.melt.masked$wavelengths>ab2[1]&pixel.melt.masked$wavelengths<ab2[2],]$Reflectance <- NA
Expand All @@ -148,13 +142,12 @@ ggplot()+
scale_colour_manual(values = c("blue3","green4","green2","tan4","grey50","black"),
labels = c("Water","Tree","Grass","Soil","Roof","Road"))+
labs(color = "Cover Type")+
ggtitle("Land cover spectral signatures")+
ggtitle("Land cover spectral signatures with\n atmospheric absorption bands removed")+
theme(plot.title = element_text(hjust = 0.5, size=20))+
xlab("Wavelength")



## ----challenge-answer, echo=FALSE, eval=FALSE----------------------------------------------------------------------------------------------------------------------------
## ----challenge-answer, echo=FALSE, eval=FALSE--------------------------------------------------------------------------------------------------------------------------------
##
## # Challenge Answers - These challenge problems will depend on the specific
## # pixels that you select, but here we answer these questions generally.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ As shown here:
</div>


For this next part, if you are following along in RStudio, you will need to enter these line below directly in the Console. `dev.new(noRStudioGD = TRUE)` will open up a separate window for plotting, where you will also run the `click` command.
For this next part, if you are following along in RStudio, you will need to enter these line below directly in the Console. `dev.new(noRStudioGD = TRUE)` will open up a separate window for plotting, which is where you will click the pixels to extract spectra, using the `terra::click` functionality.

```{r dev-new, eval=FALSE}
dev.new(noRStudioGD = TRUE)
Expand All @@ -166,11 +166,11 @@ par(col="red", cex=2)
plotRGB(rgbStack, r=1, g=2, b=3, scale=300, stretch = "hist")
# use the 'click' function
c <- click(rgbStack, n = 7, id=TRUE, xy=TRUE, cell=TRUE, type="p", pch=16, col="red", col.lab="red")
c <- click(rgbStack, n = 6, id=TRUE, xy=TRUE, cell=TRUE, type="p", pch=16, col="red", col.lab="red")
```

Once you have clicked your six points, the graphics window should close. If you want to choose new points, or if you accidentally clicked something you didn't want to in the step, run the previous chunk of code again to start over.
Once you have clicked your six points, the graphics window should close. If you want to choose new points, or if you accidentally clicked a point that you didn't intend to, run the previous 2 chunks of code again to re-start.

```{r create-c-hidden, include=FALSE, purl=FALSE}
c <- read.csv("./click_df.csv")
Expand All @@ -187,11 +187,10 @@ c$col <- c$cell%%ncol(rgbStack)
## Extract Spectral Signatures from HDF5 file
Next, we will loop through each of the cells that and use the `h5read()` function to extract the reflectance values of all bands from the given pixel (row and column).

```{r extract-spectral-signaures}
```{r extract-spectral-signatures}
# create a new dataframe from the band wavelengths so that we can add the reflectance values for each cover type
pixel_df <- as.data.frame(wavelengths)
# loop through each of the cells that we selected
for(i in 1:length(c$cell)){
# extract spectral values from a single pixel
Expand All @@ -216,18 +215,10 @@ pixel_df <- cbind(pixel_df,b[2])
## Plot Spectral signatures using ggplot2
Finally, we have everything that we need to plot the spectral signatures for each of the pixels that we clicked. In order to color our lines by the different land cover types, we will first reshape our data using the `melt()` function, then plot the spectral signatures.

1. Water
2. Tree canopy (avoid the shaded northwestern side of the tree)
3. Irrigated grass
4. Bare soil (baseball diamond infield)
5. Building roof (blue)
6. Road

```{r plot-spectral-signatures, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types: Water, Tree, Grass, Soil, Roof, and Road. The x-axis is wavelength in nanometers and the y-axis is reflectance."}
# Use the melt() function to reshape the dataframe into a format that ggplot prefers
pixel.melt <- reshape2::melt(pixel_df, id.vars = "wavelengths", value.name = "Reflectance")
# Now, let's plot some spectral signatures!
# Now, let's plot the spectral signatures!
ggplot()+
geom_line(data = pixel.melt, mapping = aes(x=wavelengths, y=Reflectance, color=variable), lwd=1.5)+
scale_colour_manual(values = c("blue3","green4","green2","tan4","grey50","black"),
Expand All @@ -243,34 +234,30 @@ Nice! However, there seems to be something weird going on in the wavelengths nea
## Atmospheric Absorption Bands
Those irregularities around 1400nm and 1850 nm are two major atmospheric absorption bands - regions where gasses in the atmosphere (primarily carbon dioxide and water vapor) absorb radiation, and therefore, obscure the reflected radiation that the imaging spectrometer measures. Fortunately, the lower and upper bound of each of those atmospheric absorption bands is specified in the HDF5 file. Let's read those bands and plot rectangles where the reflectance measurements are obscured by atmospheric absorption.

```{r mask-atmospheric-absorption-bands, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types: Water, Tree, Grass, Soil, Roof, and Road. Added to the plot are two greyed-out rectangles in regions near 1400nm and 1850nm where the reflectance measurements are obscured by atmospheric absorption. The x-axis is wavelength in nanometers and the y-axis is reflectance."}
```{r mask-atmospheric-absorption-bands, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types: Water, Tree, Grass, Soil, Roof, and Road. This plot includes two greyed-out rectangles in regions near 1400nm and 1850nm where the reflectance measurements are obscured by atmospheric absorption. The x-axis is wavelength in nanometers and the y-axis is reflectance."}
# grab reflectance metadata (which contains absorption band limits)
reflMetadata <- h5readAttributes(h5_file,"/SJER/Reflectance" )
ab1 <- reflMetadata$Band_Window_1_Nanometers
ab2 <- reflMetadata$Band_Window_2_Nanometers
# Plot spectral signatures again with rectangles showing the absorption bands
# Plot spectral signatures again with grey rectangles highlighting the absorption bands
ggplot()+
geom_line(data = pixel.melt, mapping = aes(x=wavelengths, y=Reflectance, color=variable), lwd=1.5)+
geom_rect(mapping=aes(ymin=min(pixel.melt$Reflectance),ymax=max(pixel.melt$Reflectance), xmin=ab1[1], xmax=ab1[2]), color="black", fill="grey40", alpha=0.8)+
geom_rect(mapping=aes(ymin=min(pixel.melt$Reflectance),ymax=max(pixel.melt$Reflectance), xmin=ab2[1], xmax=ab2[2]), color="black", fill="grey40", alpha=0.8)+
scale_colour_manual(values = c("blue3","green4","green2","tan4","grey50","black"),
labels = c("Water","Tree","Grass","Soil","Roof","Road"))+
labs(color = "Cover Type")+
ggtitle("Land cover spectral signatures")+
ggtitle("Land cover spectral signatures with\n atmospheric absorption bands greyed out")+
theme(plot.title = element_text(hjust = 0.5, size=20))+
xlab("Wavelength")
```

Now we can clearly see that the noisy sections of each spectral signature are within the atmospheric absorption bands. For our final step, let's take all reflectance values from within each absorption band and set them to `NA` to remove the noisiest sections from the plot.

```{r remove-absorption-band-reflectances, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types. Values falling within the two rectangles from the previous image have been set to NA and ommited from the plot. The x-axis is wavelength in nanometers and the y-axis is reflectance."}
```{r remove-absorption-band-reflectances, fig.width=9, fig.height=6, fig.cap="Plot of spectral signatures for the six different land cover types. Values falling within the atmospheric absorption bands have been set to NA and ommited from the plot. The x-axis is wavelength in nanometers and the y-axis is reflectance."}
# Duplicate the spectral signatures into a new data.frame
pixel.melt.masked <- pixel.melt
# Mask out all values within each of the two atmospheric absorption bands
pixel.melt.masked[pixel.melt.masked$wavelengths>ab1[1]&pixel.melt.masked$wavelengths<ab1[2],]$Reflectance <- NA
pixel.melt.masked[pixel.melt.masked$wavelengths>ab2[1]&pixel.melt.masked$wavelengths<ab2[2],]$Reflectance <- NA
Expand All @@ -281,13 +268,12 @@ ggplot()+
scale_colour_manual(values = c("blue3","green4","green2","tan4","grey50","black"),
labels = c("Water","Tree","Grass","Soil","Roof","Road"))+
labs(color = "Cover Type")+
ggtitle("Land cover spectral signatures")+
ggtitle("Land cover spectral signatures with\n atmospheric absorption bands removed")+
theme(plot.title = element_text(hjust = 0.5, size=20))+
xlab("Wavelength")
```

There you have it, spectral signatures for six different land cover types, with the readings from the atmospheric absorption bands removed.
There you have it, spectral signatures for six different land cover types, with the regions from the atmospheric absorption bands removed.

<div id="ds-challenge" markdown="1">

Expand Down
Loading

0 comments on commit 03f5f2e

Please sign in to comment.