Skip to content
Open
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
80 changes: 80 additions & 0 deletions packages/base/src/dialogs/symbology/hooks/useGetMultiBandInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { IJGISLayer, IJupyterGISModel } from '@jupytergis/schema';
import { fromUrl, fromBlob } from 'geotiff';
import { useEffect, useState } from 'react';

import { loadFile } from '@/src/tools';

export interface IMultiBandRow {
band: number;
colorInterpretation?: string;
}

const useGetMultiBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => {
const [bandRows, setBandRows] = useState<IMultiBandRow[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const fetchBandList = async () => {
setLoading(true);
setError(null);

try {
const source = model.getSource(layer?.parameters?.source);
const sourceInfo = source?.parameters?.urls[0];

if (!sourceInfo?.url) {
setError('No source URL found.');
setLoading(false);
return;
}

let tiff;
if (
sourceInfo.url.startsWith('http') ||
sourceInfo.url.startsWith('https')
) {
// Handle remote GeoTIFF file
tiff = await fromUrl(sourceInfo.url);
} else {
// Handle local GeoTIFF file
const preloadedFile = await loadFile({
filepath: sourceInfo.url,
type: 'GeoTiffSource',
model,
});

if (!preloadedFile.file) {
setError('Failed to load local file.');
setLoading(false);
return;
}

tiff = await fromBlob(preloadedFile.file);
}

const image = await tiff.getImage();
const numberOfBands = image.getSamplesPerPixel();

const rows: IMultiBandRow[] = [];
for (let i = 0; i < numberOfBands; i++) {
rows.push({
band: i,
});
}

setBandRows(rows);
} catch (err: any) {
setError(`Error fetching bands: ${err.message}`);
} finally {
setLoading(false);
}
};

useEffect(() => {
fetchBandList();
}, []);

return { bandRows, setBandRows, loading, error };
};

export default useGetMultiBandInfo;
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@ import { useEffect, useState } from 'react';

import { loadFile } from '@/src/tools';

export interface IBandHistogram {
buckets: number[];
count: number;
max: number;
min: number;
}

export interface IBandRow {
export interface ISingleBandRow {
band: number;
colorInterpretation?: string;
stats: {
Expand All @@ -20,23 +13,21 @@ export interface IBandRow {
};
}

const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => {
const [bandRows, setBandRows] = useState<IBandRow[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const useGetSingleBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => {
const [bandRows, setBandRows] = useState<ISingleBandRow[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const fetchBandInfo = async () => {
setLoading(true);
setError(null);

try {
const bandsArr: IBandRow[] = [];
const source = model.getSource(layer?.parameters?.source);
const sourceInfo = source?.parameters?.urls[0];

if (!sourceInfo?.url) {
setError('No source URL found.');
setLoading(false);
return;
}

Expand Down Expand Up @@ -67,19 +58,20 @@ const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => {
const image = await tiff.getImage();
const numberOfBands = image.getSamplesPerPixel();

const bands: ISingleBandRow[] = [];
for (let i = 0; i < numberOfBands; i++) {
bandsArr.push({
band: i,
bands.push({
band: i + 1,
Copy link
Member

Choose a reason for hiding this comment

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

This is the core of the fix, right? Are the rest of the changes necessary to fix this bug? Apologies, I've forgotten some of the context around this issue :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this is the core fix. Rest of changes is also necessary because if we fix only in the useGetBandInfo so the Singleband bug teleport to Multiband because we are using common hook in both useGetBandInfo. More info here #912 (comment)

stats: {
minimum: sourceInfo.min ?? 0,
maximum: sourceInfo.max ?? 100,
},
});
}

setBandRows(bandsArr);
setBandRows(bands);
} catch (err: any) {
setError(`Error fetching band info: ${err.message}`);
setError(`Error fetching bands: ${err.message}`);
} finally {
setLoading(false);
}
Expand All @@ -92,4 +84,4 @@ const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => {
return { bandRows, setBandRows, loading, error };
};

export default useGetBandInfo;
export default useGetSingleBandInfo;
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React, { useState } from 'react';

import { IBandRow } from '@/src/dialogs/symbology/hooks/useGetBandInfo';
import { IMultiBandRow } from '@/src/dialogs/symbology/hooks/useGetMultiBandInfo';
import { ISingleBandRow } from '@/src/dialogs/symbology/hooks/useGetSingleBandInfo';

type BandRowType = ISingleBandRow | IMultiBandRow;

interface IBandRowProps {
label: string;
index: number;
bandRow: IBandRow;
bandRows: IBandRow[];
bandRow: BandRowType;
bandRows: BandRowType[];
setSelectedBand: (band: number) => void;
setBandRows: (bandRows: IBandRow[]) => void;
setBandRows: (bandRows: ISingleBandRow[]) => void;
isMultibandColor?: boolean;
}

Expand All @@ -31,8 +34,15 @@ const BandRow: React.FC<IBandRowProps> = ({
setBandRows,
isMultibandColor,
}) => {
const [minValue, setMinValue] = useState(bandRow?.stats.minimum);
const [maxValue, setMaxValue] = useState(bandRow?.stats.maximum);
const isSingle = !isMultibandColor;

const [minValue, setMinValue] = useState(
isSingle ? (bandRow as ISingleBandRow)?.stats.minimum : 0,
);

const [maxValue, setMaxValue] = useState(
isSingle ? (bandRow as ISingleBandRow)?.stats.maximum : 100,
);

const handleMinValueChange = (event: {
target: { value: string | number };
Expand All @@ -49,7 +59,7 @@ const BandRow: React.FC<IBandRowProps> = ({
};

const setNewBands = () => {
const newBandRows = [...bandRows];
const newBandRows = [...bandRows] as ISingleBandRow[];
newBandRows[index].stats.minimum = minValue;
newBandRows[index].stats.maximum = maxValue;
setBandRows(newBandRows);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IWebGlLayer } from '@jupytergis/schema';
import { ExpressionValue } from 'ol/expr/expression';
import React, { useEffect, useRef, useState } from 'react';

import useGetBandInfo from '@/src/dialogs/symbology/hooks/useGetBandInfo';
import useGetMultiBandInfo from '@/src/dialogs/symbology/hooks/useGetMultiBandInfo';
import { ISymbologyDialogProps } from '@/src/dialogs/symbology/symbologyDialog';
import BandRow from '@/src/dialogs/symbology/tiff_layer/components/BandRow';
import { LoadingOverlay } from '@/src/shared/components/loading';
Expand Down Expand Up @@ -30,7 +30,7 @@ const MultibandColor: React.FC<ISymbologyDialogProps> = ({
return;
}

const { bandRows, setBandRows, loading } = useGetBandInfo(model, layer);
const { bandRows, setBandRows, loading } = useGetMultiBandInfo(model, layer);

const [selectedBands, setSelectedBands] = useState<ISelectedBands>({
red: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import ColorRampControls, {
ColorRampControlsOptions,
} from '@/src/dialogs/symbology/components/color_ramp/ColorRampControls';
import StopRow from '@/src/dialogs/symbology/components/color_stops/StopRow';
import useGetBandInfo, {
IBandRow,
} from '@/src/dialogs/symbology/hooks/useGetBandInfo';
import useGetSingleBandInfo, {
ISingleBandRow,
} from '@/src/dialogs/symbology/hooks/useGetSingleBandInfo';
import {
IStopRow,
ISymbologyDialogProps,
Expand Down Expand Up @@ -48,7 +48,7 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({

const stateDb = GlobalStateDbManager.getInstance().getStateDb();

const { bandRows, setBandRows, loading } = useGetBandInfo(model, layer);
const { bandRows, setBandRows, loading } = useGetSingleBandInfo(model, layer);

const [layerState, setLayerState] = useState<ReadonlyJSONObject>();
const [selectedBand, setSelectedBand] = useState(1);
Expand All @@ -60,7 +60,7 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({
>();

const stopRowsRef = useRef<IStopRow[]>();
const bandRowsRef = useRef<IBandRow[]>([]);
const bandRowsRef = useRef<ISingleBandRow[]>([]);
const selectedFunctionRef = useRef<InterpolationType>();
const colorRampOptionsRef = useRef<ColorRampControlsOptions | undefined>();
const selectedBandRef = useRef<number>();
Expand Down
Loading