diff --git a/frontend/src/config/color-maps.ts b/frontend/src/config/color-maps.ts index edd1e924..9f571636 100644 --- a/frontend/src/config/color-maps.ts +++ b/frontend/src/config/color-maps.ts @@ -20,18 +20,34 @@ export const RASTER_COLOR_MAPS = { scheme: 'reds', range: [0, 75], }, - power: { + totalValue: { scheme: 'reds', range: [0, 10], }, - water: { + economicUse: { scheme: 'blues', range: [0, 10], }, - transport: { + populationUse: { scheme: 'purples', range: [0, 10], }, + totalRisk: { + scheme: 'reds', + range: [0, 10], + }, + ead: { + scheme: 'reds', + range: [0, 10], + }, + eael: { + scheme: 'reds', + range: [0, 10], + }, + none: { + scheme: 'reds', + range: [0, 10], + }, }; function invertColorScale(colorScale: (t: number) => T) { diff --git a/frontend/src/config/risks/domains.ts b/frontend/src/config/risks/domains.ts new file mode 100644 index 00000000..e93273ee --- /dev/null +++ b/frontend/src/config/risks/domains.ts @@ -0,0 +1,67 @@ +import { DataParamGroupConfig } from 'lib/controls/data-params'; + +export interface RiskParams { + returnPeriod: number; + epoch: number; + rcp: string; + confidence: string | number; +} + +export const RISK_DOMAINS: Record> = { + none: { + paramDomains: { + returnPeriod: [0], + epoch: [2010], + rcp: ['baseline'], + confidence: ['None'], + }, + paramDefaults: { + returnPeriod: 0, + epoch: 2010, + rcp: 'baseline', + confidence: 'None', + }, + }, + fluvial: { + paramDomains: { + returnPeriod: [100], + + rcp: ['baseline'], + epoch: [2010], + confidence: ['None'], + }, + paramDefaults: { + returnPeriod: 100, + + rcp: 'baseline', + epoch: 2010, + confidence: 'None', + }, + paramDependencies: { + rcp: ({ epoch }) => { + if (epoch === 2010) return ['baseline']; + else if (epoch === 2050 || epoch === 2080) return ['2.6', '4.5', '8.5']; + }, + }, + }, + cyclone: { + paramDomains: { + returnPeriod: [100], + epoch: [2010], + rcp: ['baseline'], + confidence: [5, 50, 95], + }, + paramDefaults: { + returnPeriod: 100, + epoch: 2010, + rcp: 'baseline', + confidence: 50, + }, + paramDependencies: { + rcp: ({ epoch }) => { + if (epoch === 2010) return ['baseline']; + if (epoch === 2050 || epoch === 2100) return ['4.5', '8.5']; + }, + }, + }, +}; diff --git a/frontend/src/lib/recoil/grouped-family.ts b/frontend/src/lib/recoil/grouped-family.ts index 15e2bbb6..1d3c9260 100644 --- a/frontend/src/lib/recoil/grouped-family.ts +++ b/frontend/src/lib/recoil/grouped-family.ts @@ -14,7 +14,7 @@ export function groupedFamily( (group) => ({ get }) => { const groupParams = get(paramsFamily(group)); - console.log({ group, groupParams }); + console.log({ group, groupParams, paramsFamily }); const deps = fromPairs(groupParams?.map((param) => [param, family(paramFn(group, param))])); return get(waitForAll(deps)); }, diff --git a/frontend/src/sidebar/risks/DamageSourceControl.tsx b/frontend/src/sidebar/risks/DamageSourceControl.tsx deleted file mode 100644 index 5e618579..00000000 --- a/frontend/src/sidebar/risks/DamageSourceControl.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { - FormControl, - FormControlLabel, - FormLabel, - MenuItem, - Radio, - RadioGroup, - Select, -} from '@mui/material'; -import { useRecoilState } from 'recoil'; - -import { StateEffectRoot } from 'lib/recoil/state-effects/StateEffectRoot'; - -import { InputSection } from 'sidebar/ui/InputSection'; -import { InputRow } from 'sidebar/ui/InputRow'; -import { EpochControl } from 'sidebar/ui/params/EpochControl'; -import { RCPControl } from 'sidebar/ui/params/RCPControl'; -import { - damageSourceState, - damageSourceStateEffect, - damageTypeState, -} from 'state/damage-mapping/damage-map'; -import { HAZARDS_METADATA, HAZARDS_UI_ORDER } from 'config/hazards/metadata'; -import { LayerStylePanel } from 'sidebar/ui/LayerStylePanel'; - -export const DamageSourceControl = () => { - const [damageSource, setDamageSource] = useRecoilState(damageSourceState); - const [damageType, setDamageType] = useRecoilState(damageTypeState); - - return ( - <> - - - - - Damage type - - variant="standard" - value={damageType} - onChange={(e) => setDamageType(e.target.value)} - > - Direct Damages - Economic Losses - - - - - - Hazard - setDamageSource(value)}> - } /> - {HAZARDS_UI_ORDER.map((hazard) => ( - } - /> - ))} - - - - - - - - - - - - ); -}; diff --git a/frontend/src/sidebar/risks/RisksControl.tsx b/frontend/src/sidebar/risks/RisksControl.tsx index 1bb840af..0c8a88ef 100644 --- a/frontend/src/sidebar/risks/RisksControl.tsx +++ b/frontend/src/sidebar/risks/RisksControl.tsx @@ -1,30 +1,78 @@ -import { FormControl, FormControlLabel, FormLabel, Radio, RadioGroup } from '@mui/material'; +import { + FormControl, + FormControlLabel, + FormLabel, + MenuItem, + Radio, + RadioGroup, + Select, +} from '@mui/material'; import { useRecoilState } from 'recoil'; + +import { StateEffectRoot } from 'lib/recoil/state-effects/StateEffectRoot'; + +import { InputSection } from 'sidebar/ui/InputSection'; +import { InputRow } from 'sidebar/ui/InputRow'; +import { EpochControl } from 'sidebar/ui/params/EpochControl'; +import { RCPControl } from 'sidebar/ui/params/RCPControl'; import { riskSelectionState } from 'state/risks/risk-selection'; +import { + riskSourceState, + riskSourceStateEffect +} from 'state/risk-mapping/risk-map'; -const SECTORS = { - all: 'All sectors', - power: 'Power', - transport: 'Transport', - water: 'Water', -} +const HAZARDS = ['none', 'cyclone', 'fluvial']; +const HAZARDS_METADATA = { + none: { label: 'None' }, + cyclone: { label: 'Cyclone' }, + fluvial: { label: 'All Flooding' }, +}; export const RisksControl = () => { + const [riskSource, setRiskSource] = useRecoilState(riskSourceState); const [riskSelection, setRiskSelection] = useRecoilState(riskSelectionState); + console.log({ riskSource, riskSelection }) + return ( <> - - Sector - setRiskSelection(value)}> - {Object.entries(SECTORS).map(([sector, label]) => ( - } - /> - ))} - - + + + + Display + + variant="standard" + value={riskSelection} + onChange={(e) => setRiskSelection(e.target.value)} + > + Total value + Economic use + Population use + Total risk + Expected Annual Damages (EAD) + Expected Annual Economic Losses (EAEL) + + + + + + Hazard + setRiskSource(value)}> + {HAZARDS.map((hazard) => ( + } + /> + ))} + + + + + + + + + ); }; diff --git a/frontend/src/sidebar/risks/RisksSection.tsx b/frontend/src/sidebar/risks/RisksSection.tsx index 72d06ade..7637881b 100644 --- a/frontend/src/sidebar/risks/RisksSection.tsx +++ b/frontend/src/sidebar/risks/RisksSection.tsx @@ -1,13 +1,8 @@ import { FC } from 'react'; - -import { Collapse } from '@mui/material'; -import { TransitionGroup } from 'react-transition-group'; - import { StateEffectRoot } from 'lib/recoil/state-effects/StateEffectRoot'; import { RisksControl } from './RisksControl'; import { SidebarPanel } from 'sidebar/SidebarPanel'; -import { DamageSourceControl } from './DamageSourceControl'; import { SidebarPanelSection } from 'sidebar/ui/SidebarPanelSection'; import { risksStyleStateEffect, sectionStyleValueState } from 'state/sections'; import { ErrorBoundary } from 'lib/react/ErrorBoundary'; @@ -23,13 +18,6 @@ export const RisksSection: FC = () => { - - - - - - - ); diff --git a/frontend/src/state/data-params.ts b/frontend/src/state/data-params.ts index a7fafc4c..32fa563b 100644 --- a/frontend/src/state/data-params.ts +++ b/frontend/src/state/data-params.ts @@ -1,4 +1,5 @@ import { HAZARD_DOMAINS } from 'config/hazards/domains'; +import { RISK_DOMAINS } from 'config/risks/domains'; import { totalDamagesConfig } from 'config/domains/total-damages'; import { DataParamGroupConfig, @@ -21,6 +22,7 @@ export type DataParamParam = Readonly<{ export const dataParamConfig: Record = { ...HAZARD_DOMAINS, + ...RISK_DOMAINS, all: totalDamagesConfig, adaptation: adaptationDomainsConfig, }; diff --git a/frontend/src/state/layers/risks.ts b/frontend/src/state/layers/risks.ts index 828d5453..3d52bd0a 100644 --- a/frontend/src/state/layers/risks.ts +++ b/frontend/src/state/layers/risks.ts @@ -1,18 +1,20 @@ import { HazardParams } from 'config/hazards/domains'; import { riskViewLayer } from 'config/risks/risk-view-layer'; import { ViewLayer } from 'lib/data-map/view-layers'; -import { truthyKeys } from 'lib/helpers'; import { selector } from 'recoil'; import { dataParamsByGroupState } from 'state/data-params'; -import { riskVisibilityState } from 'state/risks/risk-visibility'; +import { riskSourceState } from 'state/risk-mapping/risk-map'; +import { riskSelectionState } from 'state/risks/risk-selection'; import { sectionVisibilityState } from 'state/sections'; export const riskLayerState = selector({ key: 'riskLayerState', - get: ({ get }) => - get(sectionVisibilityState('risks')) - ? truthyKeys(get(riskVisibilityState)).map((risk) => - riskViewLayer(risk, get(dataParamsByGroupState(risk)) as HazardParams), - ) - : [], + get: ({ get }) => { + const riskSource = get(riskSourceState); + const riskSelection = get(riskSelectionState); + console.log('riskLayerState', [riskViewLayer(riskSelection, get(dataParamsByGroupState(riskSource)) as HazardParams)]) + return get(sectionVisibilityState('risks')) + ? [riskViewLayer(riskSelection, get(dataParamsByGroupState(riskSource)) as HazardParams)] + : [] + } }); diff --git a/frontend/src/state/layers/view-layers.ts b/frontend/src/state/layers/view-layers.ts index 7aadf5be..9d2f7f4e 100644 --- a/frontend/src/state/layers/view-layers.ts +++ b/frontend/src/state/layers/view-layers.ts @@ -54,7 +54,7 @@ export const viewLayersState = selector>({ const regionLevel = get(regionLevelState); const background = get(backgroundState); const showLabels = get(showLabelsState); - console.log(get(riskLayerState), get(hazardLayerState)) + console.trace(get(riskLayerState), get(hazardLayerState)) return [ // administrative region boundaries or population density diff --git a/frontend/src/state/risk-mapping/risk-map.ts b/frontend/src/state/risk-mapping/risk-map.ts index b81d6f1f..2551aac5 100644 --- a/frontend/src/state/risk-mapping/risk-map.ts +++ b/frontend/src/state/risk-mapping/risk-map.ts @@ -1,28 +1,18 @@ -import forEach from 'lodash/forEach'; -import { atom, selector } from 'recoil'; +import { atom } from 'recoil'; -import { HAZARD_DOMAINS } from 'config/hazards/domains'; import { dataParamOptionsState, dataParamState } from 'state/data-params'; -import { hazardSelectionState } from 'state/hazards/hazard-selection'; - -export const riskSectorState = atom({ - key: 'riskSectorState', - default: 'all', -}); export const riskSourceState = atom({ key: 'riskSourceState', - default: 'all', + default: 'none', }); export const riskTypeState = atom({ key: 'riskTypeState', - default: 'direct', + default: 'totalValue', }); export const riskSourceStateEffect = ({ get, set }, riskSource) => { - syncHazardsWithRiskSourceStateEffect({ set }, riskSource); - if (riskSource !== 'all') { const riskSourceReturnPeriodDomain = get( dataParamOptionsState({ group: riskSource, param: 'returnPeriod' }), @@ -34,9 +24,3 @@ export const riskSourceStateEffect = ({ get, set }, riskSource) => { set(dataParamState({ group: riskSource, param: 'returnPeriod' }), topReturnPeriod); } }; - -function syncHazardsWithRiskSourceStateEffect({ set }, riskSource) { - forEach(HAZARD_DOMAINS, (groupConfig, group) => { - set(hazardSelectionState(group), group === riskSource); - }); -} diff --git a/frontend/src/state/risks/risk-selection.ts b/frontend/src/state/risks/risk-selection.ts index 3c45c218..c9f9bf53 100644 --- a/frontend/src/state/risks/risk-selection.ts +++ b/frontend/src/state/risks/risk-selection.ts @@ -1,9 +1,8 @@ -import fromPairs from 'lodash/fromPairs'; import { atom, RecoilValue } from 'recoil'; export const riskSelectionState = atom({ key: 'riskSelectionState', - default: 'all', + default: 'totalValue', }); interface TransactionGetterInterface { diff --git a/frontend/src/state/risks/risk-visibility.ts b/frontend/src/state/risks/risk-visibility.ts index 592e3984..c8a40d9d 100644 --- a/frontend/src/state/risks/risk-visibility.ts +++ b/frontend/src/state/risks/risk-visibility.ts @@ -6,12 +6,8 @@ export const riskVisibilityState = selector({ key: 'riskVisibilityState', get: ({ get }) => { const selectedRiskSource = get(riskSelectionState); - if (selectedRiskSource === 'all') { - return {}; - } else { - return { - [selectedRiskSource]: true, - }; - } + return { + [selectedRiskSource]: true, + }; }, }); diff --git a/frontend/src/state/sections.ts b/frontend/src/state/sections.ts index 6a7d06da..73509386 100644 --- a/frontend/src/state/sections.ts +++ b/frontend/src/state/sections.ts @@ -5,6 +5,7 @@ import { StateEffect } from 'lib/recoil/state-effects/types'; import { HAZARDS_UI_ORDER } from 'config/hazards/metadata'; import { damageSourceState } from './damage-mapping/damage-map'; +import { riskSourceState } from './risk-mapping/risk-map'; import { getHazardSelectionAggregate } from './hazards/hazard-selection'; export const sectionVisibilityState = atomFamily({ @@ -33,13 +34,11 @@ export const networksStyleStateEffect: StateEffect = ({ get, set }, styl }; export const risksStyleStateEffect: StateEffect = ({ get, set }, style) => { - if (style === 'damages') { - const hazardSelection = getHazardSelectionAggregate({ get }, HAZARDS_UI_ORDER); - const visibleHazards = truthyKeys(hazardSelection); - const defaultDamageSource = visibleHazards[0] ?? 'all'; + const hazardSelection = getHazardSelectionAggregate({ get }, HAZARDS_UI_ORDER); + const visibleHazards = truthyKeys(hazardSelection); + const defaultRiskSource = visibleHazards[0] ?? 'none'; - set(damageSourceState, defaultDamageSource); - } + set(riskSourceState, defaultRiskSource); }; export interface StyleSelectionOption {