From 79a7885a384b378eb831dcce04fa1366615db8f9 Mon Sep 17 00:00:00 2001 From: Nakul Date: Thu, 20 Nov 2025 21:41:23 +0530 Subject: [PATCH] fixing singleband selector bug --- .../symbology/hooks/useGetMultiBandInfo.ts | 80 +++++++++++++++++++ ...GetBandInfo.ts => useGetSingleBandInfo.ts} | 28 +++---- .../tiff_layer/components/BandRow.tsx | 24 ++++-- .../tiff_layer/types/MultibandColor.tsx | 4 +- .../types/SingleBandPseudoColor.tsx | 10 +-- 5 files changed, 114 insertions(+), 32 deletions(-) create mode 100644 packages/base/src/dialogs/symbology/hooks/useGetMultiBandInfo.ts rename packages/base/src/dialogs/symbology/hooks/{useGetBandInfo.ts => useGetSingleBandInfo.ts} (76%) diff --git a/packages/base/src/dialogs/symbology/hooks/useGetMultiBandInfo.ts b/packages/base/src/dialogs/symbology/hooks/useGetMultiBandInfo.ts new file mode 100644 index 000000000..d48536c0e --- /dev/null +++ b/packages/base/src/dialogs/symbology/hooks/useGetMultiBandInfo.ts @@ -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([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(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; diff --git a/packages/base/src/dialogs/symbology/hooks/useGetBandInfo.ts b/packages/base/src/dialogs/symbology/hooks/useGetSingleBandInfo.ts similarity index 76% rename from packages/base/src/dialogs/symbology/hooks/useGetBandInfo.ts rename to packages/base/src/dialogs/symbology/hooks/useGetSingleBandInfo.ts index fd1074eb3..dd09a7784 100644 --- a/packages/base/src/dialogs/symbology/hooks/useGetBandInfo.ts +++ b/packages/base/src/dialogs/symbology/hooks/useGetSingleBandInfo.ts @@ -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: { @@ -20,9 +13,9 @@ export interface IBandRow { }; } -const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => { - const [bandRows, setBandRows] = useState([]); - const [loading, setLoading] = useState(false); +const useGetSingleBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => { + const [bandRows, setBandRows] = useState([]); + const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const fetchBandInfo = async () => { @@ -30,13 +23,11 @@ const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => { 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; } @@ -67,9 +58,10 @@ 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, stats: { minimum: sourceInfo.min ?? 0, maximum: sourceInfo.max ?? 100, @@ -77,9 +69,9 @@ const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => { }); } - setBandRows(bandsArr); + setBandRows(bands); } catch (err: any) { - setError(`Error fetching band info: ${err.message}`); + setError(`Error fetching bands: ${err.message}`); } finally { setLoading(false); } @@ -92,4 +84,4 @@ const useGetBandInfo = (model: IJupyterGISModel, layer: IJGISLayer) => { return { bandRows, setBandRows, loading, error }; }; -export default useGetBandInfo; +export default useGetSingleBandInfo; diff --git a/packages/base/src/dialogs/symbology/tiff_layer/components/BandRow.tsx b/packages/base/src/dialogs/symbology/tiff_layer/components/BandRow.tsx index 62036c54b..ffd9ec8f7 100644 --- a/packages/base/src/dialogs/symbology/tiff_layer/components/BandRow.tsx +++ b/packages/base/src/dialogs/symbology/tiff_layer/components/BandRow.tsx @@ -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; } @@ -31,8 +34,15 @@ const BandRow: React.FC = ({ 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 }; @@ -49,7 +59,7 @@ const BandRow: React.FC = ({ }; const setNewBands = () => { - const newBandRows = [...bandRows]; + const newBandRows = [...bandRows] as ISingleBandRow[]; newBandRows[index].stats.minimum = minValue; newBandRows[index].stats.maximum = maxValue; setBandRows(newBandRows); diff --git a/packages/base/src/dialogs/symbology/tiff_layer/types/MultibandColor.tsx b/packages/base/src/dialogs/symbology/tiff_layer/types/MultibandColor.tsx index 6465a8584..58501091c 100644 --- a/packages/base/src/dialogs/symbology/tiff_layer/types/MultibandColor.tsx +++ b/packages/base/src/dialogs/symbology/tiff_layer/types/MultibandColor.tsx @@ -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'; @@ -30,7 +30,7 @@ const MultibandColor: React.FC = ({ return; } - const { bandRows, setBandRows, loading } = useGetBandInfo(model, layer); + const { bandRows, setBandRows, loading } = useGetMultiBandInfo(model, layer); const [selectedBands, setSelectedBands] = useState({ red: 1, diff --git a/packages/base/src/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.tsx b/packages/base/src/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.tsx index 177e3561b..53b59aeb4 100644 --- a/packages/base/src/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.tsx +++ b/packages/base/src/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.tsx @@ -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, @@ -48,7 +48,7 @@ const SingleBandPseudoColor: React.FC = ({ const stateDb = GlobalStateDbManager.getInstance().getStateDb(); - const { bandRows, setBandRows, loading } = useGetBandInfo(model, layer); + const { bandRows, setBandRows, loading } = useGetSingleBandInfo(model, layer); const [layerState, setLayerState] = useState(); const [selectedBand, setSelectedBand] = useState(1); @@ -60,7 +60,7 @@ const SingleBandPseudoColor: React.FC = ({ >(); const stopRowsRef = useRef(); - const bandRowsRef = useRef([]); + const bandRowsRef = useRef([]); const selectedFunctionRef = useRef(); const colorRampOptionsRef = useRef(); const selectedBandRef = useRef();