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

Return default value of colormap along with other settings #1128

Merged
merged 3 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion app/scripts/components/exploration/atoms/datasets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { datasetLayers, reconcileDatasets } from '../data-utils';
import { datasetLayers } from '../data-utils';
import { reconcileDatasets } from '../data-utils-no-faux-module';
import { TimelineDataset, TimelineDatasetForUrl } from '../types.d.ts';
import { atomWithUrlValueStability } from '$utils/params-location-atom/atom-with-url-value-stability';

Expand Down
9 changes: 1 addition & 8 deletions app/scripts/components/exploration/atoms/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,20 +148,13 @@ export function useTimelineDatasetVisibility(
export function useTimelineDatasetColormap(
datasetAtom: PrimitiveAtom<TimelineDataset>
) {
const dataset = useAtomValue(datasetAtom);

const colorMapAtom = useMemo(() => {
return focusAtom(datasetAtom, (optic) =>
optic.prop('settings').prop('colorMap')
);
}, [datasetAtom]);

const [colorMap, setColorMap] = useAtom(colorMapAtom);

const effectiveColorMap =
colorMap ?? dataset.data.sourceParams?.colormap_name ?? 'viridis';

return [effectiveColorMap, setColorMap];
return useAtom(colorMapAtom);
}

export const useTimelineDatasetAnalysis = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import { glsp, themeVal } from '@devseed-ui/theme-provider';
import { Link } from 'react-router-dom';
import { timelineDatasetsAtom } from '../../atoms/datasets';
import {
reconcileDatasets,
datasetLayers,
allExploreDatasets
} from '../../data-utils';
reconcileDatasets
} from '../../data-utils-no-faux-module';
import { datasetLayers,
allExploreDatasets} from '../../data-utils';
import RenderModalHeader from './header';

import ModalFooterRender from './footer';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Button, Icon } from "@trussworks/react-uswds";
import { Icon } from "@trussworks/react-uswds";
import { CollecticonDrop } from '@devseed-ui/collecticons';
import { sequentialColorMaps, divergingColorMaps, restColorMaps } from './colorMaps';

Expand Down Expand Up @@ -29,7 +29,7 @@ export const classifyColormap = (colormapName: string): 'sequential' | 'divergin
};

interface ColormapOptionsProps {
colorMap: string;
colorMap: string | undefined;
setColorMap: (colorMap: string) => void;
}

Expand All @@ -50,7 +50,7 @@ export const getColormapColors = (colormapName: string, isReversed: boolean): st
return isReversed ? colors.reduceRight((acc, color) => [...acc, color], []) : colors;
};

export function ColormapOptions({ colorMap, setColorMap}: ColormapOptionsProps) {
export function ColormapOptions({ colorMap = 'viridis', setColorMap}: ColormapOptionsProps) {
const initialIsReversed = colorMap.endsWith('_r');
const initialColorMap = normalizeColorMap(colorMap);

Expand All @@ -72,13 +72,13 @@ export function ColormapOptions({ colorMap, setColorMap}: ColormapOptionsProps)

if (colormapType === 'sequential') {
if (customColorMap) {
availableColormaps = [{ name: customColorMap, label: 'Default' }, ...CURATED_SEQUENTIAL_COLORMAPS.map(name => ({ name }))];
availableColormaps = [{ name: customColorMap }, ...CURATED_SEQUENTIAL_COLORMAPS.map(name => ({ name }))];
} else {
availableColormaps = CURATED_SEQUENTIAL_COLORMAPS.map(name => ({ name }));
}
} else if (colormapType === 'diverging') {
if (customColorMap) {
availableColormaps = [{ name: customColorMap, label: 'Default' }, ...CURATED_DIVERGING_COLORMAPS.map(name => ({ name }))];
availableColormaps = [{ name: customColorMap }, ...CURATED_DIVERGING_COLORMAPS.map(name => ({ name }))];
} else {
availableColormaps = CURATED_DIVERGING_COLORMAPS.map(name => ({ name }));
}
Expand All @@ -101,12 +101,6 @@ export function ColormapOptions({ colorMap, setColorMap}: ColormapOptionsProps)
setColorMap(isReversed ? `${baseColorMap}_r` : baseColorMap);
};

const handleResetAll = () => {
setIsReversed(false);
const baseColorMap = normalizeColorMap(selectedColorMap);
setColorMap(baseColorMap);
};

return (
<div className='colormap-options__container bg-white shadow-1 maxh-mobile-lg'>
<div className='display-flex flex-align-center text-gray-90 padding-2 font-heading-xs text-bold'><CollecticonDrop className='margin-right-1' /> Colormap options</div>
Expand All @@ -121,11 +115,10 @@ export function ColormapOptions({ colorMap, setColorMap}: ColormapOptionsProps)
)}
<input className='colormap-options__input' checked={isReversed} type='checkbox' readOnly />
</div>
<Button className='font-ui-3xs' onClick={handleResetAll} type='button' disabled={!isReversed} unstyled>Reset all</Button>
</div>

<div>
{availableColormaps.map(({ name, label }) => {
{availableColormaps.map(({ name }) => {
const previewColors = getColormapColors(name, isReversed);

return (
Expand All @@ -139,7 +132,7 @@ export function ColormapOptions({ colorMap, setColorMap}: ColormapOptionsProps)
style={{ background: `linear-gradient(to right, ${previewColors.join(', ')})` }}
/>
<label className='colormap-options__label text-gray-90 font-heading-xs flex-1'>
{label ? 'Default' : name}
{name}
</label>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ interface CardProps {
datasetAtom: PrimitiveAtom<TimelineDataset>;
isVisible: boolean | undefined;
setVisible: any;
colorMap: string;
colorMap: string | undefined;
setColorMap: (colorMap: string) => void;
onClickLayerInfo: () => void;
datasetLegend: LayerLegendCategorical | LayerLegendGradient | undefined;
Expand Down
4 changes: 1 addition & 3 deletions app/scripts/components/exploration/components/map/layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ interface LayerProps {

export function Layer(props: LayerProps) {
const { id: layerId, dataset, order, selectedDay, onStatusChange } = props;

const { isVisible, opacity } = dataset.settings;
const colorMap = dataset.settings.colorMap ?? dataset.data.sourceParams?.colormap_name ?? 'viridis';
const { isVisible, opacity, colorMap } = dataset.settings;

// The date needs to match the dataset's time density.
const relevantDate = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ function getInitialMetrics(data: DatasetLayer): DataMetric[] {
return foundMetrics;
}

function getInitialColorMap(dataset: DatasetLayer): string {
return dataset.sourceParams?.colormap_name ?? 'viridis';
}

export function reconcileDatasets(
ids: string[],
datasetsList: EnhancedDatasetLayer[],
Expand All @@ -75,15 +79,15 @@ export function reconcileDatasets(
if (!dataset) {
throw new Error(`Dataset [${id}] not found`);
}

return {
status: DatasetStatus.IDLE,
data: dataset,
error: null,
settings: {
isVisible: true,
opacity: 100,
analysisMetrics: getInitialMetrics(dataset)
analysisMetrics: getInitialMetrics(dataset),
colorMap: getInitialColorMap(dataset)
},
analysis: {
status: DatasetStatus.IDLE,
Expand Down
85 changes: 2 additions & 83 deletions app/scripts/components/exploration/data-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,10 @@ import eachMonthOfInterval from 'date-fns/eachMonthOfInterval';
import {
EnhancedDatasetLayer,
StacDatasetData,
TimeDensity,
TimelineDataset,
DatasetStatus
TimeDensity
} from './types.d.ts';
import {
DataMetric,
DATA_METRICS,
DEFAULT_DATA_METRICS
} from './components/datasets/analysis-metrics';
import { veda_faux_module_datasets } from '$data-layer/datasets';
import { DatasetLayer, DatasetData, VedaDatum } from '$types/veda';
import { DatasetData, VedaDatum } from '$types/veda';
import { utcString2userTzDate } from '$utils/date';

// @TODO: This file should be deprecated and merged with `data-utils-no-faux-module`
Expand Down Expand Up @@ -85,80 +78,6 @@ export const datasetLayers = Object.values(veda_faux_module_datasets).flatMap(
}
);

/**
* Returns an array of metrics based on the given Dataset Layer configuration.
* If the layer has metrics defined, it returns only the metrics that match the
* ids. Otherwise, it returns all available metrics.
*
* @param data - The Datase tLayer object to get metrics for.
* @returns An array of metrics objects.
*/
function getInitialMetrics(data: DatasetLayer): DataMetric[] {
const metricsIds = data.analysis?.metrics ?? [];

if (!metricsIds.length) {
return DEFAULT_DATA_METRICS;
}

const foundMetrics = metricsIds
.map((metric: string) => {
return DATA_METRICS.find((m) => m.id === metric)!;
})
.filter(Boolean);

return foundMetrics;
}

/**
* Converts the datasets to a format that can be used by the timeline, skipping
* the ones that have already been reconciled.
*
* @param ids The ids of the datasets to reconcile.
* @param datasetsList The list of datasets layers from VEDA
* @param reconciledDatasets The datasets that were already reconciled.
*/

// @TODO: Assuming that all the datasets are added only through this method
// We can find a dataset that a layer belongs to in this method
// Include it as a part of returned value

export function reconcileDatasets(
ids: string[],
datasetsList: EnhancedDatasetLayer[],
reconciledDatasets: TimelineDataset[]
): TimelineDataset[] {
return ids.map((id) => {
const alreadyReconciled = reconciledDatasets.find((d) => d.data.id === id);

if (alreadyReconciled) {
return alreadyReconciled;
}

const dataset = datasetsList.find((d) => d.id === id);

if (!dataset) {
throw new Error(`Dataset [${id}] not found`);
}

return {
status: DatasetStatus.IDLE,
data: dataset,
error: null,
settings: {
isVisible: true,
opacity: 100,
analysisMetrics: getInitialMetrics(dataset)
},
analysis: {
status: DatasetStatus.IDLE,
data: null,
error: null,
meta: {}
}
};
});
}

export function resolveLayerTemporalExtent(
datasetId: string,
datasetData: StacDatasetData
Expand Down
Loading