library(sf)
library(units)
library(tidyverse)
library(cowplot)
library(gridExtra)
library(ggforce)
library(ggmap)
library(data.table)
library(piggyback)
library(geosphere)
library(smoothr)
source("R/make_flight_line.R")
wproj="+proj=utm +zone=34 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs" # working projection
g3_altitude=set_units(c(28000,41000,45000),feet)
g5_altitude=set_units(c(28000,41000,51000),feet)
h_feet=g3_altitude
h=set_units(h_feet, km) #altitude in km
Details from https://avirisng.jpl.nasa.gov/specifications.html
AVIRISNG=data.frame(
instrument="AVIRIS-NG",
row=1, #just used for plotting
tfov=set_units(36,degrees),
ifov=set_units(1,mrad),
spec_n=480,
spec_res=set_units(5,nm),
spec_min=set_units(380,nm),
spec_max=set_units(2510,nm)
)
Details from https://directory.eoportal.org/web/eoportal/airborne-sensors/hytes
HyTES=data.frame(
instrument="HyTES",
row=2, #just used for plotting
tfov=set_units(50,degrees),
ifov=set_units(1.44,mrad),
spec_n=256,
spec_res=set_units(17.6,nm),
spec_min=set_units(set_units(7.5,um),nm),
spec_max=set_units(set_units(12,um),nm)
)
Details from https://prism.jpl.nasa.gov/spectrometer_char.html
PRISM=data.frame(
instrument="PRISM",
row=3, #just used for plotting
tfov=set_units(30.7,degrees),
ifov=set_units(0.97,mrad),
spec_n=608,
spec_res=set_units(2.83,nm),
spec_min=set_units(349.9,nm),
spec_max=set_units(1053.5,nm)
)
LVIS=data.frame(
instrument="LVIS",
row=4, #just used for plotting
tfov=set_units(200,mrad) %>% set_units(degrees), #https://lvis.gsfc.nasa.gov/Data/Maps/ABoVE2019Map.html
ifov=set_units(0.75,mrad),
spec_n=1,
spec_res=set_units(1,nm),
spec_min=set_units(1064,nm),
spec_max=set_units(1064,nm)
)
get_ground_fov<- function(h,fov){
2*set_units(h,km)*tan(set_units(fov/2,radians))
}
sensors=bind_rows(AVIRISNG,HyTES,PRISM,LVIS) %>%
rowwise() %>%
mutate(
# get swath widths
swath_width_low=get_ground_fov(min(h),tfov) %>% set_units(km),
swath_width_mid=get_ground_fov(median(h),tfov) %>% set_units(km),
swath_width_high=get_ground_fov(max(h), tfov) %>% set_units(km),
# calculate GIFOV - Ground-projected instantaneous field of view
gifov_low=get_ground_fov(min(h), ifov) %>% set_units(m),
gifov_mid=get_ground_fov(median(h),ifov) %>% set_units(m),
gifov_high=get_ground_fov(max(h), ifov)%>% set_units(m)
) %>%
mutate(
swath_width_km=paste0("[",round(swath_width_low,2),",",
round(swath_width_high,2),"]"),
gifov_m=paste0("[",round(gifov_low,2),",",
round(gifov_high),"]"))
sensors %>%
select(instrument,
spectral_bands=spec_n,spectral_resolution=spec_res,
swath_width_km,spatial_resolution_m=gifov_m) %>%
DT::datatable()
Read data from here
avirisng=googlesheets4::read_sheet("https://docs.google.com/spreadsheets/d/1UNgRz5EZNLcKtp9cykbi-0lG_D0LWq2lRffwFX3Lpkg/edit#gid=1639195767") %>%
filter(grepl("Alt",.$Comments)) # keep only rows that report the altitude
avirisng$alt=set_units(as.numeric(gsub("kft.*$","",gsub("Alt = ","",avirisng$Comments)))*1000,"ft")
# subtract mean scene elevation
avirisng$alt_over_ground=avirisng$alt-set_units(avirisng$`Mean Scene Elevation`,"m")
avirisng$calculated_gifov=get_ground_fov(avirisng$alt_over_ground,set_units(1,mrad)) %>% set_units(m)
avirisng$calculated_gifov_dif=avirisng$calculated_gifov-set_units(avirisng$`Pixel Size`,m)
summary(avirisng$calculated_gifov_dif)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## -4.0140 -0.0034 0.0910 0.6369 0.1717 2892.7071 131
avirisng %>%
filter(alt<set_units(70000,ft)) %>%
ggplot(aes(x=`Pixel Size`,y=calculated_gifov))+
geom_hex(bins=100)+
scale_fill_viridis_c()+
geom_abline(slope=1,intercept=0,col="red")+
coord_equal()+
xlab("Pixel size (m) reported by AVIRIS team")
avirisng %>%
filter(alt<set_units(60000,ft)) %>%
ggplot(aes(x=alt))+
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
G3 https://jsc-aircraft-ops.jsc.nasa.gov/gulfstream-giii.html 6 hours / 2,600 nautical miles = 4815.2 km
d=4815*(5/6) # 6 hour flight coverage in km (minus one hour for takeoff/landing)
set_units(d,"km")
## 4012.5 [km]
path=st_linestring(x=as.matrix(rbind(
c(18.46929,-34.38451),
c(18.37620,-34.08127),
c(18.46486,-33.99350),
c(18.77962,-33.94030),
c(18.93478,-33.84011))),dim="XY") %>%
st_sfc() %>% st_sf(path=1,geom=.,crs=4326) %>%
smooth(method = "ksmooth")
flights <- sensors %>%
rowwise() %>%
mutate(geometry=make_flight_line(path=path,
swath_width = swath_width_mid)) %>%
st_as_sf() %>%
mutate(instrument=factor(instrument,ordered=T,levels = c("HyTES","AVIRIS-NG","PRISM","LVIS")))
bbox=flights %>% #st_transform(flights,4326) %>%
st_buffer(dist = 0.2) %>%
st_bbox();names(bbox)=c("left","bottom","right","top")
hdf <- get_map(location=bbox,
maptype="toner", zoom=12,
source="stamen")
#hdf <- get_map(location=bbox, #different background
# maptype="satellite", zoom=12)
ggmap(hdf, extent = "normal")+
geom_sf(data=st_transform(flights,4326),mapping=aes(fill=instrument),
alpha=.4,color=NA,inherit.aes = F)+
geom_sf(data=st_transform(path,4326),inherit.aes = F)+
ylab("Latitude")+
xlab("Longitude")
## Coordinate system already present. Adding new coordinate system, which will replace the existing one.
flights %>%
st_segmentize(50) %>%
# mutate(OGR_STYLE = "BRUSH(fc:#0000FF80); PEN(c:#FF0000,w:1px)") %>% #fiddle with kml aesthetics
st_write("data/transect.kml",append=F,altitudeMode="clampToGround")
## Writing layer `transect' to data source `data/transect.kml' using driver `KML'
## Writing 4 features with 16 fields and geometry type Polygon.
if(F){ # if desired, push file to github release
tag="v0.0.1"
repo="BioSCape-io/BioSCape_flights"
pb_new_release(repo, tag)
pb_upload("data/transect.kml",
repo = repo,
tag = tag)
}