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

Hack: restrict CDI date selection for lag; COUNTRY=jordan #1326

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c015a37
Adding support for custom seasons in validity configuration
gislawill Jul 30, 2024
fece4d0
Fixing season bounds
gislawill Jul 30, 2024
92f5fb6
fixing tests
gislawill Jul 30, 2024
78cbd13
Fixing past season bug
gislawill Jul 31, 2024
a1681ff
CDI - configure seasons as quarters
wadhwamatic Aug 4, 2024
131e842
Ensure query dates are availables for composite requests
gislawill Aug 5, 2024
680ff15
Test updates
gislawill Aug 5, 2024
3ad7808
Better handle timezones
gislawill Aug 6, 2024
dbdabc4
adjust bounding box
wadhwamatic Aug 6, 2024
c2eaabe
remove layers available through shared config
wadhwamatic Aug 6, 2024
779d38d
Merge branch 'master' into feat/allow-flexible-season-validity
gislawill Aug 6, 2024
b2e960b
Merge branch 'feat/allow-flexible-season-validity' of https://github.…
gislawill Aug 6, 2024
07afa32
Accomodate leap years in constructDateFromSeason
gislawill Aug 6, 2024
67b8fe7
Adding hacky-ish expected data lag
gislawill Aug 6, 2024
200e675
TS fix
gislawill Aug 6, 2024
4ac8b61
revert bbox
wadhwamatic Aug 7, 2024
7d6bccc
Merge branch 'feat/allow-flexible-season-validity' into hack/restrict…
wadhwamatic Aug 7, 2024
05a7719
update CDI date lag for demo
wadhwamatic Aug 7, 2024
e141dd8
temporary arabic translations
wadhwamatic Aug 7, 2024
c451b57
additional temporary translations
wadhwamatic Aug 7, 2024
f55e9a0
remove forecast layers
wadhwamatic Aug 7, 2024
a36c41e
Merge branch 'master' into hack/restrict-day-selection-for-lag
wadhwamatic Sep 6, 2024
39c0ce2
Merge branch 'master' into hack/restrict-day-selection-for-lag
wadhwamatic Sep 13, 2024
de88004
Merge branch 'master' into hack/restrict-day-selection-for-lag
wadhwamatic Sep 16, 2024
8a951b7
extend date lag and modify CDI params based on Sara's input
wadhwamatic Sep 17, 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
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ const paintProps: (
const CompositeLayer = memo(({ layer, before }: Props) => {
// look to refacto with impactLayer and maybe other layers
const [adminBoundaryLimitPolygon, setAdminBoundaryPolygon] = useState(null);
const selectedDate = useDefaultDate(layer.dateLayer);
const selectedDate = useDefaultDate(
layer.dateLayer,
layer.expectedDataLagDays,
);
const serverAvailableDates = useSelector(availableDatesSelector);
const opacityState = useSelector(opacitySelector(layer.id));
const dispatch = useDispatch();
Expand Down
28 changes: 16 additions & 12 deletions frontend/src/config/jordan/layers.json
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,7 @@
"type": "composite",
"period": "monthly",
"base_url": "https://hip-service.ovio.org/q_multi_geojson",
"expected_data_lag_days": 110,
"validity": {
"forward": 1,
"backward": 2,
Expand All @@ -1385,7 +1386,7 @@
"CHIRPS",
"R1S_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "lst_anomaly",
Expand All @@ -1394,7 +1395,7 @@
"MODIS",
"MYD11C2_TDD_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "ndvi_dekad",
Expand All @@ -1404,7 +1405,7 @@
"NDVI_smoothed_5KM"
],
"aggregation": "average",
"invert": "True"
"invert": "False"
}
],
"legend": [
Expand Down Expand Up @@ -1471,6 +1472,7 @@
"type": "composite",
"period": "seasonal",
"base_url": "https://hip-service.ovio.org/q_multi_geojson",
"expected_data_lag_days": 180,
"validity": {
"mode": "season",
"seasons": [
Expand All @@ -1492,7 +1494,7 @@
"CHIRPS",
"R1S_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "lst_anomaly",
Expand All @@ -1501,7 +1503,7 @@
"MODIS",
"MYD11C2_TDD_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "ndvi_dekad",
Expand All @@ -1511,7 +1513,7 @@
"NDVI_smoothed_5KM"
],
"aggregation": "average",
"invert": "True"
"invert": "False"
}
],
"legend": [
Expand Down Expand Up @@ -1578,6 +1580,7 @@
"type": "composite",
"period": "monthly",
"base_url": "https://hip-service.ovio.org/q_multi_geojson",
"expected_data_lag_days": 110,
"validity": {
"forward": 1,
"backward": 2,
Expand All @@ -1591,7 +1594,7 @@
"CHIRPS",
"R1S_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "lst_anomaly",
Expand All @@ -1600,7 +1603,7 @@
"MODIS",
"MYD11C2_TDD_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "ndvi_dekad",
Expand All @@ -1610,7 +1613,7 @@
"NDVI_smoothed_5KM"
],
"aggregation": "average",
"invert": "True"
"invert": "False"
}
],
"legend": [
Expand Down Expand Up @@ -1677,6 +1680,7 @@
"type": "composite",
"period": "seasonal",
"base_url": "https://hip-service.ovio.org/q_multi_geojson",
"expected_data_lag_days": 180,
"validity": {
"mode": "season",
"seasons": [
Expand All @@ -1698,7 +1702,7 @@
"CHIRPS",
"R1S_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "lst_anomaly",
Expand All @@ -1707,7 +1711,7 @@
"MODIS",
"MYD11C2_TDD_DEKAD"
],
"aggregation": "last_dekad"
"aggregation": "average"
},
{
"id": "ndvi_dekad",
Expand All @@ -1717,7 +1721,7 @@
"NDVI_smoothed_5KM"
],
"aggregation": "average",
"invert": "True"
"invert": "False"
}
],
"legend": [
Expand Down
1 change: 0 additions & 1 deletion frontend/src/config/jordan/prism.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
],
"categories": {
"rainfall": {
"forecasts": ["daily_rainfall_forecast", "dekad_rainfall_forecast", "dekad_rainfall_anomaly_forecast"],
"rainfall_amount": [
{
"group_title": "Rainfall Aggregate",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,9 @@ export class CompositeLayerProps extends CommonLayerProps {

@optional
endDate?: string;

@optional
expectedDataLagDays?: number;
}

export class StaticRasterLayerProps extends CommonLayerProps {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/context/layers/composite_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const fetchCompositeLayerData: LazyLoader<CompositeLayerProps> =
min_lat: boundingBox[1],
max_lon: boundingBox[2],
max_lat: boundingBox[3],
start_date: areaStartDate ?? '2002-01-01',
start_date: areaStartDate ?? '2002-07-01',
end_date: areaEndDate ?? '2021-07-31',
},
layers: inputLayers.map(({ key, aggregation, importance, invert }) => ({
Expand Down
105 changes: 68 additions & 37 deletions frontend/src/utils/layers-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import {
Extent,
expandBoundingBox,
} from 'components/MapView/Layers/raster-utils';
import { LayerKey, LayerType, isMainLayer, DateItem } from 'config/types';
import {
LayerKey,
LayerType,
isMainLayer,
DateItem,
CompositeLayerProps,
} from 'config/types';
import {
AALayerId,
LayerDefinitions,
Expand Down Expand Up @@ -110,42 +116,56 @@ const useLayers = () => {
2,
) as Extent;

const selectedLayersWithDateSupport = useMemo(
() =>
selectedLayers
.filter((layer): layer is DateCompatibleLayer => {
if (
layer.type === 'admin_level_data' ||
layer.type === 'static_raster'
) {
return Boolean(layer.dates);
}
if (layer.type === 'point_data') {
// some WMS layer might not have date dimension (i.e. static data)
return Boolean(layer.dateUrl);
}
if (layer.type === 'wms') {
// some WMS layer might not have date dimension (i.e. static data)
return layer.id in serverAvailableDates;
}
if (layer.type === 'composite') {
// some WMS layer might not have date dimension (i.e. static data)
return (
layer.id in serverAvailableDates ||
layer.dateLayer in serverAvailableDates
);
}
return dateSupportLayerTypes.includes(layer.type);
})
.filter(layer => isMainLayer(layer.id, selectedLayers))
.map(layer => ({
...layer,
dateItems: getPossibleDatesForLayer(layer, serverAvailableDates)
.filter(value => value) // null check
.flat(),
})),
[selectedLayers, serverAvailableDates],
);
const selectedLayersWithDateSupport = useMemo(() => {
const initSelectedLayersWithDateSupport = selectedLayers
.filter((layer): layer is DateCompatibleLayer => {
if (
layer.type === 'admin_level_data' ||
layer.type === 'static_raster'
) {
return Boolean(layer.dates);
}
if (layer.type === 'point_data') {
// some WMS layer might not have date dimension (i.e. static data)
return Boolean(layer.dateUrl);
}
if (layer.type === 'wms') {
// some WMS layer might not have date dimension (i.e. static data)
return layer.id in serverAvailableDates;
}
if (layer.type === 'composite') {
// some WMS layer might not have date dimension (i.e. static data)
return (
layer.id in serverAvailableDates ||
layer.dateLayer in serverAvailableDates
);
}
return dateSupportLayerTypes.includes(layer.type);
})
.filter(layer => isMainLayer(layer.id, selectedLayers));

const earliestExpectedDataLagDays =
initSelectedLayersWithDateSupport.reduce(
(acc, layer) =>
Math.max(
acc,
(layer as CompositeLayerProps).expectedDataLagDays ?? 0,
),
0,
);

const soonestAvailableDate =
new Date().getTime() -
(earliestExpectedDataLagDays ?? 0) * 24 * 60 * 60 * 1000;

return initSelectedLayersWithDateSupport.map(layer => ({
...layer,
dateItems: getPossibleDatesForLayer(layer, serverAvailableDates)
.filter(value => value) // null check
.filter(date => date.displayDate <= soonestAvailableDate)
.flat(),
}));
}, [selectedLayers, serverAvailableDates]);

/*
takes all the dates possible for every layer and counts the amount of times each one is duplicated.
Expand Down Expand Up @@ -185,6 +205,16 @@ const useLayers = () => {
if (selectedLayersWithDateSupport.length === 0) {
return [];
}

const earliestExpectedDataLagDays = selectedLayersWithDateSupport.reduce(
(acc, layer) =>
Math.max(acc, (layer as CompositeLayerProps).expectedDataLagDays ?? 0),
0,
);
const soonestAvailableDate =
new Date().getTime() -
(earliestExpectedDataLagDays ?? 0) * 24 * 60 * 60 * 1000;

const selectedNonAALayersWithDateSupport =
selectedLayersWithDateSupport.filter(
layer => layer.type !== 'anticipatory_action',
Expand All @@ -201,6 +231,7 @@ const useLayers = () => {
// convert back to number array after using YYYY-MM-DD strings in countBy
)
.map(dateString => new Date(dateString).setUTCHours(12, 0, 0, 0))
.filter(date => date <= soonestAvailableDate)
.sort((a, b) => a - b);
}, [selectedLayerDatesDupCount, selectedLayersWithDateSupport]);

Expand Down
23 changes: 18 additions & 5 deletions frontend/src/utils/useDefaultDate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useDispatch, useSelector } from 'react-redux';
import { useEffect } from 'react';
import { isMainLayer, LayerKey } from 'config/types';
import { useEffect, useMemo } from 'react';
import { DateItem, isMainLayer, LayerKey } from 'config/types';
import { availableDatesSelector } from 'context/serverStateSlice';
import {
dateRangeSelector,
Expand All @@ -15,7 +15,10 @@ import { getFormattedDate } from './date-utils';
* Returns either the user selected date or the default date, dispatching it to the date picker beforehand. Can also return undefined if no default date is available.
* @param availableDatesLookupKey key to lookup in AvailableDates
*/
export function useDefaultDate(layerId: LayerKey): number | undefined {
export function useDefaultDate(
layerId: LayerKey,
expectedDataLagDays?: number,
): number | undefined {
const dispatch = useDispatch();
const selectedLayers = useSelector(layersSelector);
// check layer without group or main layer in group
Expand All @@ -26,9 +29,19 @@ export function useDefaultDate(layerId: LayerKey): number | undefined {

// TODO - use getPossibleDatesForLayer
const possibleDates = useSelector(availableDatesSelector)[layerId];
const soonestAvailableDate =
new Date().getTime() - (expectedDataLagDays ?? 0) * 24 * 60 * 60 * 1000;

const defaultDate: number | undefined =
possibleDates?.[(possibleDates?.length || 0) - 1]?.displayDate;
const defaultDate = useMemo(
() =>
possibleDates?.reduceRight((acc: number | undefined, date: DateItem) => {
if (!acc && date.displayDate <= soonestAvailableDate) {
return date.displayDate;
}
return acc;
}, undefined),
[possibleDates, soonestAvailableDate],
);

// React doesn't allow updating other components within another component
// useEffect removes this error and updates DateSelector correctly in the lifecycle.
Expand Down
Loading