Skip to content

Commit

Permalink
Merge pull request #60 from nismod/feature/update-backend
Browse files Browse the repository at this point in the history
Update backend, dataset references
  • Loading branch information
tomalrussell authored Jun 14, 2024
2 parents 8f4bcec + 1c55221 commit 5bb379b
Show file tree
Hide file tree
Showing 23 changed files with 14,893 additions and 7,555 deletions.
21,837 changes: 14,445 additions & 7,392 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@mui/icons-material": "^5.11.11",
"@mui/lab": "^5.0.0-alpha.123",
"@mui/material": "^5.11.13",
"@mui/x-tree-view": "^7.7.0",
"@nismod/irv-api-client": "^0.8.0",
"@nismod/irv-autopkg-client": "^0.2.7-dev",
"@react-hook/debounce": "^4.0.0",
Expand Down Expand Up @@ -55,12 +56,13 @@
"devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^4.1.0",
"@mdx-js/rollup": "^2.3.0",
"@storybook/addon-essentials": "^7.0.0-beta.64",
"@storybook/addon-interactions": "^7.0.0-beta.64",
"@storybook/addon-links": "^7.0.0-beta.64",
"@storybook/blocks": "^7.0.0-beta.64",
"@storybook/react": "^7.0.0-beta.64",
"@storybook/react-vite": "^7.0.0-beta.64",
"@storybook/addon-essentials": "^7.6.19",
"@storybook/addon-interactions": "^7.6.19",
"@storybook/addon-links": "^7.6.19",
"@storybook/blocks": "^7.6.19",
"@storybook/cli": "^8.1.8",
"@storybook/react": "^7.6.19",
"@storybook/react-vite": "^7.6.19",
"@storybook/testing-library": "^0.0.14-next.1",
"@types/d3-array": "^3.0.4",
"@types/d3-color": "^3.1.0",
Expand Down Expand Up @@ -88,7 +90,7 @@
"prettier": "^3.0.3",
"prop-types": "^15.8.1",
"rollup-plugin-visualizer": "^5.9.0",
"storybook": "^7.0.0-rc.4",
"storybook": "^8.1.8",
"typescript": "^5.0.2",
"vite": "^4.2.0",
"vite-plugin-qrcode": "^0.2.1",
Expand Down
82 changes: 82 additions & 0 deletions src/config/cdd/cdd-view-layer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Color } from 'deck.gl/typed';
import React from 'react';

import { InteractionTarget, RasterTarget } from '@/lib/data-map/interactions/types';
import { RasterColorMap, RasterLegend } from '@/lib/data-map/legend/RasterLegend';
import { RasterHoverDescription } from '@/lib/data-map/tooltip/RasterHoverDescription';
import { ViewLayer } from '@/lib/data-map/view-layers';
import { rasterTileLayer } from '@/lib/deck/layers/raster-tile-layer';
import { numFormat, toLabelLookup } from '@/lib/helpers';

import { SOURCES } from '../sources';
import { CDDType, METRIC_VALUE_LABELS } from './metadata';

const METRIC_FORMATS: Record<
CDDType,
{
colorMap: RasterColorMap;
formatValue: (x: number) => string;
transparentColor?: Color;
}
> = {
relative: {
colorMap: {
scheme: 'magma',
range: [0, 1],
},
formatValue: (x: number) => `${numFormat(x * 100, 2)}%`,
},
absolute: {
colorMap: {
scheme: 'magma',
range: [0, 360],
},
formatValue: numFormat,
transparentColor: [255, 255, 255, 0],
},
};

const valueLabelLookup = toLabelLookup(METRIC_VALUE_LABELS);

export function cddViewLayer(type: CDDType): ViewLayer {
const { colorMap, formatValue, transparentColor = [255, 255, 255, 0] } = METRIC_FORMATS[type];
const label = `${valueLabelLookup[type]}`;

const formatFn = (x: number) => (x != null ? formatValue(x) : '-');

return {
id: `cdd_${type}`,
interactionGroup: 'raster_assets',
params: {
type,
},
fn: ({ deckProps }) =>
rasterTileLayer(
{
transparentColor,
},
deckProps,
{
data: SOURCES.raster.getUrl({
path: `cdd_miranda/${type}`,
...colorMap,
}),
refinementStrategy: 'no-overlap',
},
),
renderLegend: () =>
React.createElement(RasterLegend, {
label,
colorMap,
getValueLabel: formatFn,
}),
renderTooltip(hoveredObject: InteractionTarget<RasterTarget>) {
return React.createElement(RasterHoverDescription, {
colorMap,
color: hoveredObject.target.color,
label,
formatValue: formatFn,
});
},
};
}
16 changes: 16 additions & 0 deletions src/config/cdd/metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ValueLabel } from '@/lib/controls/params/value-label';

export const METRIC_TYPES = ['absolute', 'relative'] as const;

export type CDDType = (typeof METRIC_TYPES)[number];

export const METRIC_VALUE_LABELS: ValueLabel<CDDType>[] = [
{
value: 'absolute',
label: 'Mean absolute Change (days per year)',
},
{
value: 'relative',
label: 'Relative Change',
},
];
29 changes: 18 additions & 11 deletions src/config/hazards/domains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,31 @@ export interface HazardParams {
interface HazardDomainConfig {
defaults: Record<string, any>;
dependencies: Record<string, string[]>;
domain: string; // backend/raster_tile_source domain
}

export const HAZARD_DOMAINS_CONFIG: Record<HazardType, HazardDomainConfig> = {
fluvial: {
domain: 'aqueduct',
defaults: {
hazard: 'fluvial',
rp: 100,
rcp: 'baseline',
epoch: 'present',
gcm: 'MIROC-ESM-CHEM',
epoch: 'baseline',
gcm: 'WATCH',
},
dependencies: {
rp: ['hazard'],
rcp: ['epoch'],
gcm: ['epoch'],
gcm: ['epoch', 'hazard'],
},
},
coastal: {
domain: 'aqueduct',
defaults: {
hazard: 'coastal',
rp: 100,
epoch: 'present',
epoch: 'baseline',
rcp: 'baseline',
gcm: 'None',
},
Expand All @@ -37,14 +43,11 @@ export const HAZARD_DOMAINS_CONFIG: Record<HazardType, HazardDomainConfig> = {
},
},
cyclone: {
domain: 'cyclone_storm',
defaults: {
rp: 10,
rp: 100,
gcm: 'constant',
/**
* epoch and rcp for cyclones are added programmatically upon load
* adjust custom code for data loading when these fields are added to the backend
*/
epoch: 'present',
epoch: 'baseline',
rcp: 'baseline',
},
dependencies: {
Expand All @@ -53,8 +56,9 @@ export const HAZARD_DOMAINS_CONFIG: Record<HazardType, HazardDomainConfig> = {
},
},
cyclone_iris: {
domain: 'cyclone_iris',
defaults: {
rp: 10,
rp: 100,
epoch: 2020,
ssp: 'constant',
},
Expand All @@ -63,6 +67,7 @@ export const HAZARD_DOMAINS_CONFIG: Record<HazardType, HazardDomainConfig> = {
},
},
extreme_heat: {
domain: 'isimip',
defaults: {
epoch: 'baseline',
rcp: 'baseline',
Expand All @@ -73,13 +78,15 @@ export const HAZARD_DOMAINS_CONFIG: Record<HazardType, HazardDomainConfig> = {
},
},
earthquake: {
domain: 'earthquake',
defaults: {
rp: 475,
medium: 'soil',
},
dependencies: {},
},
drought: {
domain: 'isimip',
defaults: {
epoch: 'baseline',
rcp: 'baseline',
Expand Down
24 changes: 11 additions & 13 deletions src/config/hazards/exposure/exposure-view-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@ export type ExposureSource = Subset<HazardType, 'extreme_heat' | 'drought'>;

export const EXPOSURE_COLOR_MAPS: Record<ExposureSource, RasterColorMap> = {
extreme_heat: {
scheme: 'reds',
range: [0, 5000],
rangeTruncated: [false, true],
scheme: 'gist_heat_r',
range: [1000, 2_000_000],
rangeTruncated: [true, true],
},
drought: {
scheme: 'oranges',
range: [0, 1000],
rangeTruncated: [false, true],
range: [1000, 500_000],
rangeTruncated: [true, true],
},
};

function numFormatWhole(value: number) {
return `${value.toLocaleString(undefined, { maximumFractionDigits: 0 })}`;
function numFormatWhole(nearest: number) {
nearest = nearest ? nearest : 1;
return (value) =>
`${(Math.round(value / nearest) * nearest).toLocaleString(undefined, { maximumFractionDigits: 0 })}`;
}

export function exposureViewLayer(hazardType: ExposureSource, hazardParams: any): ViewLayer {
Expand All @@ -53,25 +55,21 @@ export function exposureViewLayer(hazardType: ExposureSource, hazardParams: any)
data: getHazardDataUrl({ hazardType, metric: 'exposure', hazardParams }, colorMap),
refinementStrategy: 'no-overlap',
},
// temporarily hide EH below zoom 6 due to artifacts in data
hazardType === 'extreme_heat' && {
minZoom: 6,
},
);
},
renderLegend() {
return React.createElement(RasterLegend, {
label,
colorMap,
getValueLabel: numFormatWhole,
getValueLabel: numFormatWhole(1),
});
},
renderTooltip(hover: InteractionTarget<RasterTarget>) {
return React.createElement(RasterHoverDescription, {
colorMap,
color: hover.target.color,
label,
formatValue: numFormatWhole,
formatValue: numFormatWhole(1000),
});
},
};
Expand Down
8 changes: 4 additions & 4 deletions src/config/hazards/hazard-view-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { rasterTileLayer } from '@/lib/deck/layers/raster-tile-layer';

import { HazardHoverDescription } from './HazardHoverDescription';
import { HazardLegend } from './HazardLegend';
import { HAZARD_COLOR_MAPS } from './metadata';
import { HAZARD_COLOR_MAPS, HazardType } from './metadata';
import { getHazardDataPath, getHazardDataUrl } from './source';

export function getHazardId(hazardType: string, hazardParams: any) {
export function getHazardId(hazardType: HazardType, hazardParams: any) {
return getHazardDataPath({ hazardType, metric: 'occurrence', hazardParams });
}

Expand All @@ -19,7 +19,7 @@ export function hazardViewLayer(hazardType: string, hazardParams: any): ViewLaye
const magFilter = isCyclone ? GL.NEAREST : GL.LINEAR;

const id = hazardType;
const deckId = getHazardId(hazardType, hazardParams);
const deckId = getHazardId(hazardType as HazardType, hazardParams);

return {
id,
Expand All @@ -43,7 +43,7 @@ export function hazardViewLayer(hazardType: string, hazardParams: any): ViewLaye
{
id: `${id}@${deckId}`, // follow the convention viewLayerId@deckLayerId
data: getHazardDataUrl(
{ hazardType, metric: 'occurrence', hazardParams },
{ hazardType: hazardType as HazardType, metric: 'occurrence', hazardParams },
{ scheme, range },
),
refinementStrategy: 'no-overlap',
Expand Down
29 changes: 29 additions & 0 deletions src/config/hazards/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const HAZARD_COLOR_MAPS: Record<HazardType, RasterColorMap> = {
export interface HazardMetadata {
label: string;
formatValue: (x: number) => ReactNode | string;
getPath: (hazardParams: any, metric?: 'occurrence' | 'exposure') => string;
labelAbbreviations?: Record<string, string>;
legendAnnotation?: string;
}
Expand All @@ -61,35 +62,63 @@ export const HAZARDS_METADATA: Record<HazardType, HazardMetadata> = {
cyclone: {
label: 'Cyclones (STORM)',
formatValue: makeValueFormat('_m/s', { maximumFractionDigits: 1 }),
getPath: (hazardParams) => {
const { rp, rcp, epoch, gcm } = hazardParams;
return `cyclone_storm/${rp}/${gcm}/${rcp}/${epoch}`;
},
},
cyclone_iris: {
label: 'Cyclones (IRIS)',
formatValue: makeValueFormat('_m/s', { maximumFractionDigits: 1 }),
getPath: (hazardParams) => {
const { rp, ssp, epoch } = hazardParams;
return `cyclone_iris/${epoch}/${rp}/${ssp}`;
},
},
fluvial: {
label: 'River Flooding',
formatValue: makeValueFormat('_m', { maximumFractionDigits: 2 }),
getPath: (hazardParams) => {
const { rp, rcp, epoch, gcm } = hazardParams;
return `aqueduct/fluvial/${rp}/${rcp}/${epoch}/${gcm}`;
},
},
coastal: {
label: 'Coastal Flooding',
formatValue: makeValueFormat('_m', { maximumFractionDigits: 2 }),
getPath: (hazardParams) => {
const { rp, rcp, epoch, gcm } = hazardParams;
return `aqueduct/coastal/${rp}/${rcp}/${epoch}/${gcm}`;
},
},
extreme_heat: {
label: 'Extreme Heat',
formatValue: makeValueFormat('_', { maximumFractionDigits: 1, style: 'percent' }),
legendAnnotation: 'Annual probability of extreme event',
getPath: (hazardParams, metric) => {
const { rcp, epoch, gcm } = hazardParams;
return `isimip/extreme_heat/${metric}/${rcp}/${epoch}/${gcm}`;
},
},
earthquake: {
label: 'Seismic Hazard (PGA)',
formatValue: makeValueFormat('_g', { maximumFractionDigits: 3 }),
labelAbbreviations: {
PGA: 'Peak Ground Acceleration',
},
getPath: (hazardParams) => {
const { rp, medium } = hazardParams;
return `earthquake/${rp}/${medium}`;
},
},
drought: {
label: 'Droughts',
formatValue: makeValueFormat('_', { maximumFractionDigits: 1, style: 'percent' }),
legendAnnotation: 'Annual probability of extreme event',
getPath: (hazardParams, metric) => {
const { rcp, epoch, gcm } = hazardParams;
return `isimip/drought/${metric}/${rcp}/${epoch}/${gcm}`;
},
},
};

Expand Down
Loading

0 comments on commit 5bb379b

Please sign in to comment.