Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
78e9966
Supporting divergent colomaps
nakul-py Aug 29, 2025
63bcb15
critical value only for divergent
nakul-py Aug 29, 2025
e9ecb40
Divergent with min-max
nakul-py Sep 2, 2025
2e2f37b
changes
nakul-py Sep 5, 2025
67faef4
lint fix
nakul-py Sep 5, 2025
1af0c01
support singleband psuedocolor
nakul-py Sep 5, 2025
19ed962
pre-populating values
nakul-py Sep 8, 2025
dbeb780
making radius work wit min and max
nakul-py Sep 9, 2025
c1fbede
gives colors a sequance
nakul-py Sep 10, 2025
b478a85
Simplify call to useColorMapList effect
mfisher87 Sep 12, 2025
df7df8f
Remove type assertion
mfisher87 Sep 12, 2025
4c86aaf
Update selectedRamp state initialization
nakul-py Sep 14, 2025
8374c71
Refactor getColorMapList to use objectEntries for improved readability
nakul-py Sep 15, 2025
c5735c4
Refactor ColorRamp components to improve prop naming and structure; a…
nakul-py Sep 16, 2025
fe3465a
Refactor ColorRamp type usage to improve type safety and consistency …
nakul-py Sep 17, 2025
5199cb4
Update ColorRampOptions to require numberOfShades and selectedMode fo…
nakul-py Sep 17, 2025
63c1185
formatting
nakul-py Sep 17, 2025
f9108cb
Refactor ColorRamp and LegendItem component and critical value calcul…
nakul-py Sep 18, 2025
c643d52
Enable color ramp labels to display over light color ramps
mfisher87 Sep 18, 2025
437bcf0
Remove unnecessary cast
mfisher87 Sep 18, 2025
20ee921
making Critical value readonly and fixing colorRamp hover effect
nakul-py Sep 19, 2025
422580b
using min and max instead of all values
nakul-py Sep 19, 2025
60e643f
Refactor: Extract reversal checkbox into CanvasSelectComponent
mfisher87 Sep 19, 2025
29b4b9c
WIP: remove hardcoded min/max values
mfisher87 Sep 19, 2025
37d946a
Refactor: Improve layout and state management in color ramp components
nakul-py Sep 20, 2025
a928f56
lint fix
nakul-py Sep 20, 2025
b283268
making Use actual range button work with actual data
nakul-py Sep 21, 2025
8e9b604
Making categorized rendertype work with use actual range button
nakul-py Sep 22, 2025
f2bc41f
debug
nakul-py Sep 22, 2025
317142d
removing duplicate min/max
nakul-py Sep 22, 2025
4af515d
Move classification-stop options near the classify button
mfisher87 Sep 22, 2025
a39b547
Add visual separator between colormap/classification and other symbol…
mfisher87 Sep 22, 2025
e9de64d
Simplify expression of calculateEqualIntervalBreaks function
mfisher87 Sep 22, 2025
b874d0f
Making modes work
nakul-py Sep 23, 2025
e8f1db6
Move the "Use actual range" button to right, display more prominent w…
mfisher87 Sep 23, 2025
aaf19d4
Fix subtle shift in UI when displaying warning
mfisher87 Sep 23, 2025
b30b727
Lint :bell:
mfisher87 Sep 23, 2025
f985d6f
Improve name of rampNames module, remove unused COLOR_RAMP_NAMES
mfisher87 Sep 23, 2025
25183fc
refactoring
nakul-py Oct 1, 2025
504a687
Add reverse option to color ramp rendering
nakul-py Oct 1, 2025
2b5223b
Use disabled property to style input fields
mfisher87 Oct 1, 2025
928278a
Improve label of "use actual range" button
mfisher87 Oct 1, 2025
345af02
Improve conditions to disable min/max controls
mfisher87 Oct 1, 2025
cc0901f
Skip rendering the minmax controls if rendertype incorrect
mfisher87 Oct 1, 2025
18abc0e
Leave props packed in "props" object
mfisher87 Oct 1, 2025
78c5ca9
Fixup critical value display
mfisher87 Oct 1, 2025
6ec6d16
Save "reverse", "min", and "max" into symbology state in shared model
mfisher87 Oct 1, 2025
44b352e
WIP Fix loading of reverse/min/max values from shared model
mfisher87 Oct 1, 2025
273b7f5
min and max succesfully loading from shared model or lint fix
nakul-py Oct 2, 2025
ec77af3
Refactor warning in ColorRampValueControls and min/max handling in S…
nakul-py Oct 3, 2025
9f56575
Load cached min/max values for selected band in SingleBandPseudoColor
nakul-py Oct 3, 2025
b433b1d
Use implicit undefined state default
mfisher87 Oct 3, 2025
c67144a
Remove obsolete comment
mfisher87 Oct 3, 2025
5de88cc
Fix symbology screen crashing when opening for a new layer
mfisher87 Oct 3, 2025
5eb2a4c
Get the min/max geotiff values from symbology state
mfisher87 Oct 3, 2025
cf7fe08
Remove min/max source fields
mfisher87 Oct 3, 2025
3033b51
Don't initialize min/max from user input when adding layer
mfisher87 Oct 3, 2025
d1c7ce9
Remove console.logs
mfisher87 Oct 3, 2025
443d195
Set the OpenLayers Source object with min/max from symbology info
mfisher87 Oct 3, 2025
4755f5e
fix min/max values fallback
nakul-py Oct 4, 2025
9b55f00
Adding min/max caliculation when loading symbology.
nakul-py Oct 7, 2025
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
25 changes: 6 additions & 19 deletions packages/base/src/dialogs/symbology/classificationModes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,13 @@ export namespace VectorClassifications {
};

export const calculateEqualIntervalBreaks = (
Copy link
Member

@mfisher87 mfisher87 Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We refactored this so that calculating maximum and minimum from the data values is no longer the responsibility of this function; that happens externally.

values: number[],
nClasses: number,
) => {
const minimum = Math.min(...values);
const maximum = Math.max(...values);

const breaks: number[] = [];
const step = (maximum - minimum) / nClasses;

let value = minimum;

for (let i = 0; i < nClasses; i++) {
value += step;
breaks.push(value);
}

breaks[nClasses - 1] = maximum;

return breaks;
};
minimum: number,
maximum: number,
): number[] =>
Array.from({ length: nClasses }, (_, i) => {
return minimum + (i / (nClasses - 1)) * (maximum - minimum);
});

export const calculateJenksBreaks = (values: number[], nClasses: number) => {
const maximum = Math.max(...values);
Expand Down
80 changes: 10 additions & 70 deletions packages/base/src/dialogs/symbology/colorRampUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,37 @@ import colormap from 'colormap';
import colorScale from 'colormap/colorScale.js';
import { useEffect } from 'react';

import { COLOR_RAMP_DEFINITIONS } from '@/src/dialogs/symbology/colorRamps';
import rawCmocean from '@/src/dialogs/symbology/components/color_ramp/cmocean.json';

export interface IColorMap {
name: ColorRampName;
colors: string[];
}
import { objectEntries } from '@/src/tools';
import { IColorMap } from '@/src/types';

const { __license__: _, ...cmocean } = rawCmocean;

Object.assign(colorScale, cmocean);

export const COLOR_RAMP_NAMES = [
'jet',
// 'hsv', 11 steps min
'hot',
'cool',
'spring',
'summer',
'autumn',
'winter',
'bone',
'copper',
'greys',
'YiGnBu',
'greens',
'YiOrRd',
'bluered',
'RdBu',
// 'picnic', 11 steps min
'rainbow',
'portland',
'blackbody',
'earth',
'electric',
'viridis',
'inferno',
'magma',
'plasma',
'warm',
// 'rainbow-soft', 11 steps min
'bathymetry',
'cdom',
'chlorophyll',
'density',
'freesurface-blue',
'freesurface-red',
'oxygen',
'par',
'phase',
'salinity',
'temperature',
'turbidity',
'velocity-blue',
'velocity-green',
// 'cubehelix' 16 steps min
'ice',
'oxy',
'matter',
'amp',
'tempo',
'rain',
'topo',
'balance',
'delta',
'curl',
'diff',
'tarn',
] as const;

export type ColorRampName = (typeof COLOR_RAMP_NAMES)[number];

export const getColorMapList = (): IColorMap[] => {
const colorMapList: IColorMap[] = [];

COLOR_RAMP_NAMES.forEach(name => {
const colorRamp = colormap({
for (const [name, definition] of objectEntries(COLOR_RAMP_DEFINITIONS)) {
const colors = colormap({
colormap: name,
nshades: 255,
format: 'rgbaString',
});

colorMapList.push({ name, colors: colorRamp });
});
colorMapList.push({ name, colors, definition });
}

return colorMapList;
};

/**
* Hook that loads and sets color maps.
*/
export const useColorMapList = (setColorMaps: (maps: IColorMap[]) => void) => {
export const useColorMapList = (
setColorMaps: React.Dispatch<React.SetStateAction<IColorMap[]>>,
) => {
useEffect(() => {
setColorMaps(getColorMapList());
}, [setColorMaps]);
Expand Down
59 changes: 59 additions & 0 deletions packages/base/src/dialogs/symbology/colorRamps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { IColorRampDefinition } from '@/src/types';

export const COLOR_RAMP_DEFINITIONS = {
// 'rainbow-soft': {type: 'Cyclic'}, 11 steps min
// 'hsv': {type: 'Cyclic'}, 11 steps min
phase: { type: 'Cyclic' },
jet: { type: 'Sequential' },
hot: { type: 'Sequential' },
cool: { type: 'Sequential' },
spring: { type: 'Sequential' },
summer: { type: 'Sequential' },
autumn: { type: 'Sequential' },
winter: { type: 'Sequential' },
bone: { type: 'Sequential' },
copper: { type: 'Sequential' },
greys: { type: 'Sequential' },
YiGnBu: { type: 'Sequential' },
greens: { type: 'Sequential' },
YiOrRd: { type: 'Sequential' },
bluered: { type: 'Sequential' },
RdBu: { type: 'Sequential' },
rainbow: { type: 'Sequential' },
portland: { type: 'Sequential' },
blackbody: { type: 'Sequential' },
earth: { type: 'Sequential' },
electric: { type: 'Sequential' },
viridis: { type: 'Sequential' },
inferno: { type: 'Sequential' },
magma: { type: 'Sequential' },
plasma: { type: 'Sequential' },
warm: { type: 'Sequential' },
bathymetry: { type: 'Sequential' },
cdom: { type: 'Sequential' },
chlorophyll: { type: 'Sequential' },
density: { type: 'Sequential' },
'freesurface-blue': { type: 'Sequential' },
'freesurface-red': { type: 'Sequential' },
oxygen: { type: 'Sequential' },
par: { type: 'Sequential' },
salinity: { type: 'Sequential' },
temperature: { type: 'Sequential' },
turbidity: { type: 'Sequential' },
'velocity-blue': { type: 'Sequential' },
'velocity-green': { type: 'Sequential' },
// 'cubehelix': {type: 'Sequential'}, 16 steps min
ice: { type: 'Sequential' },
oxy: { type: 'Sequential' },
matter: { type: 'Sequential' },
amp: { type: 'Sequential' },
tempo: { type: 'Sequential' },
rain: { type: 'Sequential' },
topo: { type: 'Sequential' },
// 'picnic': {type: 'Divergent', criticalValue: 0.5 }, 11 steps min
balance: { type: 'Divergent', criticalValue: 0.5 },
delta: { type: 'Divergent', criticalValue: 0.5 },
curl: { type: 'Divergent', criticalValue: 0.5 },
diff: { type: 'Divergent', criticalValue: 0.5 },
tarn: { type: 'Divergent', criticalValue: 0.5 },
} as const satisfies { [key: string]: IColorRampDefinition };
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import { Button } from '@jupyterlab/ui-components';
import React, { useEffect, useRef, useState } from 'react';

import { useColorMapList } from '@/src/dialogs/symbology/colorRampUtils';
import { IColorMap } from '@/src/types';
import ColorRampEntry from './ColorRampEntry';

export interface IColorMap {
name: string;
colors: string[];
}

interface ICanvasSelectComponentProps {
selectedRamp: string;
setSelected: (item: any) => void;
reverse: boolean;
setReverse: React.Dispatch<React.SetStateAction<boolean>>;
}

const CanvasSelectComponent: React.FC<ICanvasSelectComponentProps> = ({
selectedRamp,
setSelected,
reverse,
setReverse,
}) => {
const containerRef = useRef<HTMLDivElement>(null);
const [isOpen, setIsOpen] = useState(false);
Expand All @@ -28,7 +28,7 @@ const CanvasSelectComponent: React.FC<ICanvasSelectComponentProps> = ({
if (colorMaps.length > 0) {
updateCanvas(selectedRamp);
}
}, [selectedRamp]);
}, [selectedRamp, colorMaps, reverse]);

const toggleDropdown = () => {
setIsOpen(!isOpen);
Expand Down Expand Up @@ -67,7 +67,7 @@ const CanvasSelectComponent: React.FC<ICanvasSelectComponentProps> = ({
for (let i = 0; i <= 255; i++) {
ctx.beginPath();

const color = ramp[0].colors[i];
const color = reverse ? ramp[0].colors[255 - i] : ramp[0].colors[i];
ctx.fillStyle = color;

ctx.fillRect(i * 2, 0, 2, 50);
Expand Down Expand Up @@ -99,9 +99,25 @@ const CanvasSelectComponent: React.FC<ICanvasSelectComponentProps> = ({
className={`jp-gis-color-ramp-dropdown ${isOpen ? 'jp-gis-open' : ''}`}
>
{colorMaps.map((item, index) => (
<ColorRampEntry index={index} colorMap={item} onClick={selectItem} />
<ColorRampEntry
key={item.name}
index={index}
colorMap={item}
onClick={selectItem}
/>
))}
</div>

<div className="jp-gis-symbology-row">
<label className="jp-gis-inline-label">
<input
type="checkbox"
checked={reverse}
onChange={e => setReverse(e.target.checked)}
/>
Reverse Color Ramp
</label>
</div>
</div>
);
};
Expand Down
Loading
Loading