Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDAP-495 - ABoVE Lidar Vizualization #297

Draft
wants to merge 44 commits into
base: develop
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b7121b5
Lidar subsetting + renderers
Oct 24, 2023
39f95dc
PNG renderer
Oct 24, 2023
6c54a97
CSV and ZIP renderers
Oct 24, 2023
b6e1c6f
Merge branch 'apache:master' into SDAP-495-stv-lidar
RKuttruff Oct 26, 2023
91b88ce
Added slicing params to lidar alg spec
Oct 26, 2023
3bad8c5
Improved plotting + slices
Nov 2, 2023
b4bfc85
Improved plotting + slices
Nov 6, 2023
5af6086
Suppress overly verbose loggers instead of all loggers to INFO
Jan 29, 2024
4caee50
Fit data from multiple scenes to common grid
Jan 29, 2024
a791007
Suppress overly verbose loggers instead of all loggers to INFO
Jan 29, 2024
3087df2
Merge remote-tracking branch 'RKuttruff/SDAP-495-stv-lidar' into SDAP…
Jan 29, 2024
3234e65
lidar 3d plotting
Feb 1, 2024
639d7d7
Update .asf.yaml (#293)
RKuttruff Feb 1, 2024
01bea57
SDAP-495 3d plotting fixes
Feb 5, 2024
30ce242
minor tweaks
Feb 6, 2024
c636a3a
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Feb 8, 2024
cdf4e7a
Remove mpl backend call
Feb 8, 2024
7bb8bcb
Changelog
Feb 8, 2024
43274c4
Merge branch 'apache:master' into SDAP-495-stv-lidar
RKuttruff Feb 13, 2024
421b86d
Support for 2D Lidar slicing along any arbitrary line defined by WKT
Feb 15, 2024
0c58a7b
Merge remote-tracking branch 'RKuttruff/SDAP-495-stv-lidar' into SDAP…
Feb 15, 2024
e982f4b
Slicing improvements:
Feb 16, 2024
b93ec8b
Response for no data in bounds
Feb 28, 2024
deb62e0
Better handling of close-together flightlines
Mar 7, 2024
5f7b2a3
Merge branch 'develop' into SDAP-495-stv-lidar
Mar 18, 2024
3879137
Lidar updates
Mar 18, 2024
b4c1e40
Merge branch 'develop' into SDAP-495-stv-lidar
Mar 20, 2024
dec1e81
poetry re-lock after deps update from merge
Mar 20, 2024
15a80be
Properly scale CC before plotting
Apr 4, 2024
11e6382
Major Lidar update
Apr 23, 2024
f356b42
Disable Lidar 3d & minor updates
May 6, 2024
1075063
Bugfix for lat/lon slices of custom size
May 15, 2024
40fbad0
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Jun 18, 2024
6256486
poetry re lock
Jun 18, 2024
30015e0
Merge branch 'apache:develop' into SDAP-495-stv-lidar
RKuttruff Jun 25, 2024
f2e8b3f
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Jul 9, 2024
72d7bef
poetry lock
Jul 9, 2024
3751ccc
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Aug 19, 2024
abaac86
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Sep 23, 2024
81450a2
Poetry re-lock
Sep 23, 2024
cc6bf6a
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Sep 23, 2024
e1839a3
Merge remote-tracking branch 'origin/develop' into SDAP-495-stv-lidar
Sep 23, 2024
2ee54de
Merge branch 'apache:develop' into SDAP-495-stv-lidar
RKuttruff Sep 24, 2024
53c27e9
Merge branch 'apache:develop' into SDAP-495-stv-lidar
RKuttruff Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Slicing improvements:
- Removed restriction that lat and/or lon slices cannot be used with arbitrary line slices, though the png result can get a bit long if all three are used
- ZIP output now contains CSV files for slices as well as main subset
- Vastly improved time for JSON, CSV and ZIP outputs
  • Loading branch information
rileykk committed Feb 16, 2024
commit e982f4b53cc65fe463b731192688a1cd46b24e10
93 changes: 53 additions & 40 deletions analysis/webservice/algorithms/Lidar.py
Original file line number Diff line number Diff line change
@@ -24,8 +24,8 @@
from io import BytesIO
from itertools import zip_longest, chain
from tempfile import NamedTemporaryFile, TemporaryDirectory
from typing import Tuple

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
@@ -50,6 +50,7 @@

EPOCH = timezone('UTC').localize(datetime(1970, 1, 1))
NP_EPOCH = np.datetime64('1970-01-01T00:00:00')
PD_EPOCH = pd.Timestamp('1970-01-01T00:00:00')
ISO_8601 = '%Y-%m-%dT%H:%M:%S%z'

# Precomputed resolutions of LIDAR data grids, computed over the entire ABoVE dataset
@@ -214,11 +215,11 @@ def parse_arguments(self, request):
slice_line = None

if render_type == '2D':
if (lat_slice is not None or lon_slice is not None) and slice_wkt is not None:
raise NexusProcessingException(
reason='Cannot define latSlice and/or lonSlice and sliceWKT at the same time',
code=400
)
# if (lat_slice is not None or lon_slice is not None) and slice_wkt is not None:
# raise NexusProcessingException(
# reason='Cannot define latSlice and/or lonSlice and sliceWKT at the same time',
# code=400
# )

if lat_slice is not None:
parts = lat_slice.split(',')
@@ -612,10 +613,10 @@ def source_name_from_granule(granule: str, end=-3) -> str:
slice_wkt = None

# tmp
# try:
# ds.to_netcdf('/tmp/lidar.nc')
# except:
# print('failed to dump test netcdf :(')
try:
ds.to_netcdf('/tmp/lidar.nc')
except:
print('failed to dump test netcdf :(')

if lat_slice is not None:
slice_lat, slice_min_lon, slice_max_lon = lat_slice
@@ -760,7 +761,7 @@ def meta(self):

return m

def results(self, reduce_time=False):
def results(self, reduce_time=False) -> Tuple[xr.Dataset, tuple]:
ds, (lat_slice, lon_slice, line_slice) = NexusResults.results(self)

if reduce_time and len(ds['time']) > 1:
@@ -776,31 +777,28 @@ def points_list(self):

logger.info('Generating non-NaN points list')

for i, t in enumerate(ds.time):
for j, lat in enumerate(ds.lat):
for k, lon in enumerate(ds.lon):
ds_point = ds.isel(time=i, lat=j, lon=k)

zg = ds_point['ground_height'].item()
rh50 = ds_point['mean_veg_height'].item()
rh98 = ds_point['canopy_height'].item()
cc = ds_point['canopy_coverage'].item()
for pt in ds.to_dataframe().reset_index(level=['lat', 'lon', 'time']).itertuples():
zg = getattr(pt, 'ground_height')
rh50 = getattr(pt, 'mean_veg_height')
rh98 = getattr(pt, 'canopy_height')
cc = getattr(pt, 'canopy_coverage')

if all([np.isnan(v) for v in [zg, rh50, rh98, cc]]):
continue
if all([np.isnan(v) for v in [zg, rh50, rh98, cc]]):
continue

point_ts = int((t.data - NP_EPOCH) / np.timedelta64(1, 's'))
ts: pd.Timestamp = getattr(pt, 'time')
point_ts = int((ts - PD_EPOCH).total_seconds())

points.append(dict(
latitude=lat.item(),
longitude=lon.item(),
time=point_ts,
time_iso=datetime.utcfromtimestamp(point_ts).strftime(ISO_8601),
ground_height=zg,
mean_vegetation_height=rh50,
canopy_height=rh98,
canopy_coverage=cc
))
points.append(dict(
latitude=getattr(pt, 'lat'),
longitude=getattr(pt, 'lon'),
time=point_ts,
time_iso=datetime.utcfromtimestamp(point_ts).strftime(ISO_8601),
ground_height=zg,
mean_vegetation_height=rh50,
canopy_height=rh98,
canopy_coverage=cc
))

if lat_slice is not None:
if len(lat_slice['time']) > 1:
@@ -1110,12 +1108,11 @@ def toNetCDF(self):
buf.seek(0)
return buf.read()

def toCSV(self):
points, slice_points = self.points_list()
def toCSV(self, points=None):
if points is None:
points, _ = self.points_list()
df = pd.DataFrame(points)

# print(df)

buffer = BytesIO()

df.to_csv(buffer, index=False)
@@ -1124,12 +1121,30 @@ def toCSV(self):
return buffer.read()

def toZip(self):
csv_results = self.toCSV()
points, slice_points = self.points_list()

csv_results = self.toCSV(points)

csv_slices = []

for slice_type in slice_points:
s = slice_points[slice_type]

if slice_type in ['latitude', 'longitude']:
filename = f'{slice_type}_slice.csv'
else:
filename = 'line_slice.csv'

slice_csv = self.toCSV(s['slice'])

csv_slices.append((filename, slice_csv))

buffer = BytesIO()

with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as zip:
zip.writestr('lidar_subset.csv', csv_results)
for s in csv_slices:
zip.writestr(*s)

buffer.seek(0)
return buffer.read()
@@ -1155,8 +1170,6 @@ def toImage(self):
ax = fig.add_subplot(111, projection='3d')
ax.view_init(elev=view_elev, azim=view_azim)

# ZG

lats = np.unique(results['lat'].values)
lons = np.unique(results['lon'].values)