Summary
- Summary
-
Activity Documentation for Shoreline Module
- Diagram
- SelectionPage
- ProcessingPage
- ProcessingPage
- AlgorithmCard
- Function Calls within Shoreline Analysis Steps
- Code Used in Shoreline
Activity Documentation for Shoreline Module
This documentation provides a detailed explanation of the user interaction pages in the Shoreline module.
Diagram
SelectionPage
The SelectionPage is the initial page where users can choose the analysis module. When the user selects the Shoreline Analyst option, they are redirected to the ProcessingPage . This page displays options for the user to choose the analysis module. When the user selects the Shoreline Analyst option, they are redirected to the ProcessingPage .
push('/processing')
This function redirects the user to the ProcessingPage when they select the Shoreline Analyst option.
ProcessingPage
The ProcessingPage is the page where users go through the steps of the shoreline analysis.
ProcessingPage
Page that shows the processing of the selected algorithm (bathymetry, shoreline or coastal squeeze).
This page guides the user through the steps of the shoreline analysis. The steps are as follows:
1. Choose Satellite: The user selects either the Sentinel-2 or Landsat satellite for the analysis. 2. Set Region of Interest: The user draws a polygon on the map to define the area of interest. 3. Set Period: The user selects a start and end date to filter the available images. 4. Filter Images: The user selects the desired images from the available options. 5. Set Parameters: The user enters parameters such as transect spacing, extension, and threshold. 6. Results: The results of the shoreline analysis are displayed, including charts, statistics, and exports.
useSelector(getAcquisitionParameters)
This function retrieves the acquisition parameters selected by the user in the previous steps, including the satellite choice, region of interest, period, selected images, and analysis parameters.
AlgorithmCard
The AlgorithmCard component displays information for each step of the shoreline analysis process. The cards specific to the Shoreline Analyst steps are shown. This component shows a card with information for each step of the shoreline analysis. The cards related to the Shoreline Analyst steps are displayed.
Function Calls within Shoreline Analysis Steps
The following function calls are made within the Shoreline Analyst steps of the ProcessingPage :
getAvailableImages(geometry, startDate, endDate)
This function fetches the available images from the selected satellite based on the defined region of interest and period. It returns a list of images with metadata such as image ID, date, and cloud coverage percentage.
createTransects(geometry, transectSpacing, transectExtension)
This function creates transects (lines) within the defined region of interest based on the user-entered parameters for transect spacing and extension.
extraction(images, threshold)
This function extracts shorelines from the selected images. The threshold parameter is used to determine the land-water boundary.
statistics(shorelines)
This function calculates statistics for the extracted shorelines, including Shoreline Change Envelope (SCE), Net Shoreline Movement (NSM), End Point Rate (EPR), and Linear Regression Rate (LRR). It also classifies the LRR using Esteves and Finkl (1998) intervals.
transects(shorelines)
This function calculates the intersection points of the transects and shorelines. It also computes summary statistics for each shoreline, such as mean distance and standard deviation.
Code Used in Shoreline
push('/processing')
Redirects to the processing page.
dispatch(push('/processing'));
Inputs:
No input parameters for this function.
Output:
Redirects to '/processing' page.
Use
Call this function to redirect to the processing page.
push('/processing');
useSelector(getAcquisitionParameters)
Extracts acquisition parameters from the store.
const acquisitionData = useSelector(getAcquisitionParameters, shallowEqual);
Inputs:
getAcquisitionParameters: Selector function to extract data from the store.
Output:
acquisitionData: The acquisition parameters extracted from the store.
Use
Call this hook to extract data from the Redux store.
const someData = useSelector(someSelector);
getAvailableImages(geometry, startDate, endDate)
Fetches available satellite images within a geometry and time period.
//algorithms/acquisition/index.js
export const getAvailableImages = (geometry, startDate, endDate) => {
// Compute a list of valid dates in the region to be retrieved
const query = getSatelliteCollection().filterBounds(geometry).filterDate(startDate, endDate);
const process = (available) => {
// Retrieve the globally extreme dates (earliest and latest)
const global = retrieveExtremes(available);
// Compute the grid position of each image and sort in ascending order
const enhanced = available
.map(addGridPosition)
.sort(Metadata.GRID_POSITION);
// Retrieve the northeasternmost grid position within the specified bounds
const northeasternPosition = ee
.Image(enhanced.toList(1).get(0))
.get(Metadata.GRID_POSITION);
// Keep images in the slice where the satellite passed first (northeast)
const filtered = enhanced.filter(
ee.Filter.eq(Metadata.GRID_POSITION, northeasternPosition)
);
// Retrieve the extremes in the northeastern position
const northeastern = retrieveExtremes(filtered);
// Compute the difference in days between the earliest image in the
// northeastern position and the globally earliest image
const difference = northeastern.earliest
.difference(global.earliest, "day")
.abs();
const remainder = ee.Number(difference).mod(REVISIT_DAYS);
// The amount of days we need to go back is given by the reverse of the
// difference, in terms of the duration of an orbit
const step = ee.Number(REVISIT_DAYS).subtract(remainder);
// Compute the date of the earliest possible image in the northeastern
// position (whether or not it exists) by going back in time
const earliestDate = global.earliest.advance(step.multiply(-1), "day");
// Compute the amount of complete orbital cycles between the earliest and
// latest possible dates of the images in the northeastern position (whether
// or not they exist)
const completeCycles = ee
.Number(earliestDate.difference(global.latest, "day").abs())
.divide(REVISIT_DAYS)
.ceil();
// Generate slices of 16 (0, 16, 32, 48, ...), one for each complete cycle
const additions = ee.List.sequence(0, null, REVISIT_DAYS, completeCycles);
// Transform each slice into an empty image. If the slice contains at least
// one image, we add metadata related to the correspondent orbital cycle,
// to allow for filtering later
const carriers = additions.map((increment) => {
const startingDate = earliestDate.advance(increment, "day");
const collection = sliceByRevisit(available, startingDate, REVISIT_DAYS);
const empty = ee.Algorithms.IsEqual(collection.size(), 0);
const properties = ee.Algorithms.If(
empty,
{},
mergeProperties(collection)
);
return ee.Image(0).set(properties);
});
// Keep only the images whose combined geometries contain the AOI
const valid = ee.ImageCollection.fromImages(carriers).filter(
ee.Filter.contains(Metadata.FOOTPRINT, geometry)
);
// For now only the date of the slice is important.
return ee.List(valid.toList(valid.size()).map(getDate));
};
return ee.List(
ee.Algorithms.If(query.size().gt(0), process(query), ee.List([]))
);
};
Inputs:
geometry: The geometry to fetch images within. startDate: The start date of the time period. endDate: The end date of the time period.
Output:
A list of available images within the given geometry and time period.
Use
Call this generator function to get available satellite images within a given area and time range.
yield* getAvailableImages(geometry, '2020-01-01', '2020-12-31');
createTransects(geometry, transectSpacing, transectExtension)
Generates transects within a geometry.
/**
* Generates transects orthogonal to the specified polygon.
* @param {ee.Feature} polygon a Feature describing the area to be covered
*/
export const generateOrthogonalTransects = (coordinates, step, extent) => {
coordinates = ee.List(coordinates);
const first = ee.Dictionary({
a: ee.List(coordinates.get(0)),
remainder: 0,
transects: [],
});
const result = coordinates
.slice(1)
.iterate(transectAccumulator(step, extent), [first]);
let transects = ee
.List(result)
.map((dict) => ee.Feature(ee.Dictionary(dict).get("transects")))
.flatten();
transects = ee.FeatureCollection(transects);
transects = ee.Algorithms.If(
ee.Algorithms.IsEqual(transects.size(), 0),
ee.List([]),
transects.toList(transects.size())
);
return ee.List(transects);
};
Inputs:
geometry: The geometry to generate transects within. transectSpacing: The spacing between transects. transectExtension: The length of each transect.
Output:
A list of transect features.
Use
Call this generator function to generate transects within a given geometry.
yield* createTransects(geometry, 100, 500);
extraction(images, threshold)
Extracts shorelines from a list of images.
/**
* Extracts shorelines from the specified images.
* @param {ee.ImageCollection|ee.Image} images the input images
* @param {Number} threshold the threshold to binarize the images
*/
export const extraction = (images, threshold) => {
// Cast to ImageCollection and filter invalid images
images = ee.ImageCollection(images).filter(ee.Filter.notNull(['B1', 'B2', 'B3']));
// Add NDWI band
const withNDWI = images.map(addNDWI);
// Reduce collection to a single image
const reduced = withNDWI.reduce('mean');
// Binarize using the threshold
const binary = reduced.lt(threshold);
// Extract shorelines from the binary image
const shorelines = binary.reduceToVectors({
geometry: binary.geometry(),
crs: binary.projection(),
scale: binary.projection().nominalScale(),
eightConnected: false,
maxPixels: 1e9
});
return shorelines;
};
Inputs:
images: A list of images to extract shorelines from. threshold: The threshold value for water segmentation.
Output:
A list of shoreline features.
Use
Call this generator function to extract shorelines from a list of images.
const shorelines = yield* extraction(images, 0.2);
statistics(shorelines)
Calculates shoreline change statistics.
/**
* Adds statistics about the distances observed in *transects*,
* such as StdDev and Mean.
* *Adds CASSIE internals props*
* @param {ee.List<Feature>} transects
* @param {ee.FeatureCollection} shorelines
* @returns {ee.FeatureCollection} the shorelines with added statistics
*/
export const summaryShorelineStatistics = (transects, shorelines) => {
const shorelineList = ee.List(shorelines.toList(shorelines.size()));
const shorelineIds = shorelineList.map((feature) => ee.Feature(feature).id());
const shorelineTable = ee.Dictionary.fromLists(shorelineIds, shorelineList);
const distances = ee
.List(transects)
.map((transect) =>
ee
.Dictionary(
ee.Dictionary(ee.Feature(transect).get(INTERNALS)).get("measurement")
)
.values()
)
.flatten();
/**
* Reduce distances per shoreline
*/
const transformed = ee.Dictionary(
distances.iterate((input, acc) => {
const current = ee.Dictionary(input);
const dict = ee.Dictionary(acc);
const key = current.get("withRespectTo");
const value = current.get("distance");
const feature = ee.Feature(shorelineTable.get(key));
const target = ee.Dictionary(dict.get(key, { distances: [] }));
const targetList = ee.List(target.get("distances"));
return dict.set(
key,
target.combine(
ee.Dictionary({
distances: targetList.add(value),
date: feature.get(TIME_START),
})
)
);
}, ee.Dictionary({}))
);
/* Attach properties to shorelines */
const features = ee.List(transformed.keys()).map((key) => {
const summary = ee.Dictionary(transformed.get(key));
const distances = ee.List(summary.get("distances", []));
const stats = distances.reduce(
combineReducers(ee.Reducer.mean(), ee.Reducer.stdDev())
);
const internals = ee.Dictionary({ [INTERNALS]: distances });
return ee
.Feature(shorelineTable.get(key))
.setMulti(
summary
.remove(["distances"])
.combine(ee.Dictionary(stats))
.combine(internals)
);
});
return ee.FeatureCollection(features).sort("date");
};
Inputs:
shorelines: A list of shoreline features.
Output:
Shoreline change statistics.
Use
Call this generator function to calculate shoreline change statistics from a list of shorelines.
const stats = yield* statistics(shorelines);
transects(shorelines)
Generates transects and calculates transect-based shoreline change statistics.
export const generateOrthogonalTransects = (coordinates, step, extent) => {
coordinates = ee.List(coordinates);
const first = ee.Dictionary({
a: ee.List(coordinates.get(0)),
remainder: 0,
transects: [],
});
const result = coordinates
.slice(1)
.iterate(transectAccumulator(step, extent), [first]);
let transects = ee
.List(result)
.map((dict) => ee.Feature(ee.Dictionary(dict).get("transects")))
.flatten();
transects = ee.FeatureCollection(transects);
transects = ee.Algorithms.If(
ee.Algorithms.IsEqual(transects.size(), 0),
ee.List([]),
transects.toList(transects.size())
);
return ee.List(transects);
};
Inputs:
shorelines: A list of shoreline features. transects: A list of transect features.
Output:
Transect features with shoreline change statistics.
Use
Call this generator function to generate transects from shorelines and calculate transect-based shoreline change statistics.
const transects = yield* transects(shorelines, transects);