Skip to content

Commit

Permalink
Add netcdf support
Browse files Browse the repository at this point in the history
  • Loading branch information
underbluewaters committed Oct 8, 2024
1 parent fea7dca commit 5f23ef3
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ export default function DataUploadDropzone({
</h4>
<p className="text-sm">
{t(
"SeaSketch currently supports vector data in GeoJSON, Shapefile (zipped), GeoTiff, and FlatGeobuf formats."
"SeaSketch currently supports vector data in GeoJSON, Shapefile (zipped), GeoTiff, NetCDF and FlatGeobuf formats."
)}
</p>
{Boolean(state.droppedFiles) && !state.error && (
Expand Down
32 changes: 32 additions & 0 deletions packages/spatial-uploads-handler/src/formats/netcdf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import gdal from "gdal-async";
import { Logger } from "../logger";

export async function getLayerIdentifiers(path: string, logger: Logger) {
const ids: string[] = [];
const data = await logger.exec(
["gdalinfo", ["-json", path]],
"Problem getting layer identifiers"
);
const info = JSON.parse(data);
const metadata = info.metadata || {};
const subdatasets = metadata["SUBDATASETS"] || {};
for (const key in subdatasets) {
if (/_NAME$/.test(key)) {
ids.push(subdatasets[key]);
}
}
console.log("ids", ids);
return ids;
}

export async function convertToGeoTiff(
layerId: string,
outputPath: string,
logger: Logger
) {
await logger.exec(
["gdal_translate", ["-co", "COMPRESS=DEFLATE", layerId, outputPath]],
"Problem converting to GeoTIFF"
);
return outputPath;
}
4 changes: 3 additions & 1 deletion packages/spatial-uploads-handler/src/handleUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { processRasterUpload } from "./processRasterUpload";
import { notifySlackChannel } from "./notifySlackChannel";
import { getObject, putObject } from "./remotes";
import { Logger } from "./logger";
import { getLayerIdentifiers } from "./formats/netcdf";

export { SpatialUploadsHandlerRequest };

Expand Down Expand Up @@ -150,6 +151,7 @@ export default async function handleUpload(

const s3LogPath = `s3://${process.env.BUCKET}/${jobId}.log.txt`;
let { name, ext, base } = path.parse(objectKey);

name = sanitize(name);
const originalName = name;
name = `${jobId}`;
Expand All @@ -170,7 +172,7 @@ export default async function handleUpload(
// After the environment is set up, we can start processing the file depending
// on its type
try {
if (isTif) {
if (isTif || ext === ".nc") {
stats = await processRasterUpload({
logger,
path: workingFilePath,
Expand Down
20 changes: 17 additions & 3 deletions packages/spatial-uploads-handler/src/processRasterUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { rasterInfoForBands } from "./rasterInfoForBands";
import { Logger } from "./logger";
import gdal from "gdal-async";
import bbox from "@turf/bbox";
import { convertToGeoTiff, getLayerIdentifiers } from "./formats/netcdf";

export async function processRasterUpload(options: {
logger: Logger;
Expand Down Expand Up @@ -41,6 +42,19 @@ export async function processRasterUpload(options: {

const { ext, isCorrectProjection } = await validateInput(path, logger);

if (ext === ".nc") {
const layerIdentifiers = await getLayerIdentifiers(path, logger);
if (layerIdentifiers.length > 0) {
path = await convertToGeoTiff(
layerIdentifiers[0],
pathJoin(workingDirectory, jobId + ".tif"),
logger
);
} else {
throw new Error("No layers found in NetCDF file");
}
}

await updateProgress("running", "analyzing");
// Get raster stats
const stats = await rasterInfoForBands(path);
Expand Down Expand Up @@ -155,12 +169,12 @@ async function validateInput(path: string, logger: Logger) {

// Use rasterio to see if it is a supported file format
const isTif = ext === ".tif" || ext === ".tiff";
if (!isTif) {
throw new Error("Only GeoTIFF files are supported");
if (!isTif && ext !== ".nc") {
throw new Error("Only GeoTIFF and NetCDF files are supported");
}

const ds = await gdal.openAsync(path);
if (ds.driver.description !== "GTiff") {
if (ds.driver.description !== "GTiff" && ds.driver.description !== "netCDF") {
throw new Error(`Unrecognized raster driver "${ds.driver.description}"`);
}

Expand Down
3 changes: 2 additions & 1 deletion packages/spatial-uploads-handler/src/rasterInfoForBands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ export async function rasterInfoForBands(
) {
// find a scaling factor that will represent the range of data values with
// the full range of the encoding scheme.
if (range < 16_777_216) {
// This is useful for float values which may just be 0-1
if (range < 500) {
scale = 1;
// stretch values to fit full encoding scheme
// Use factors of 10, e.g. 10, 100, 1000, etc.
Expand Down

0 comments on commit 5f23ef3

Please sign in to comment.