Skip to content
Merged

Jp/UI #107

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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
},
"dependencies": {
"@lazarusa/react-tweakpane": "^0.9.0",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-slot": "^1.2.3",
"@react-spring/three": "^10.0.0",
Expand All @@ -38,6 +40,7 @@
"@types/webpack": "^5.28.5",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"glslify": "^7.1.1",
"jotai": "^2.12.3",
"js-colormaps-es": "^0.0.5",
Expand All @@ -46,8 +49,10 @@
"next-themes": "^0.4.6",
"quick-lru": "^7.0.1",
"random-words": "^2.0.1",
"rc-slider": "^11.1.8",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
"tailwind-merge": "^3.3.0",
"three": "^0.176.0",
"tweakpane": "^4.0.5",
Expand Down
24 changes: 10 additions & 14 deletions src/components/LandingHome.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';
import * as THREE from 'three'
THREE.Cache.enabled = true;
import { DataStores } from '@/components/zarr/DataStores'
import { GetZarrMetadata, GetVariableNames } from '@/components/zarr/GetMetadata';
import { ZarrDataset, GetStore } from '@/components/zarr/ZarrLoaderLRU';
import { useRef, useState } from 'react';
import VariableScroller from './ui/VariableScroller';
Expand All @@ -19,7 +19,7 @@ import { GetTitleDescription } from '@/components/zarr/GetMetadata';
// import { PaneManager } from '@/components/PaneManager';

export function LandingHome() {
const { bgcolor, fullmetadata, variables} = DataStores();

const [settings, setSettings] = useState({plotType: 'volume', cmap: 'Spectral', flipCmap: false });
const initStore = useGlobalStore(useShallow(state=>state.initStore))
const [zMeta, setZMeta] = useState<object[]>([])
Expand All @@ -31,6 +31,11 @@ export function LandingHome() {
GetTitleDescription(GetStore(initStore)).then((result) => {
if (isMounted) setTitleDescription(result);
});
const store = GetStore(initStore);
const fullmetadata = GetZarrMetadata(store);
const variables = GetVariableNames(fullmetadata);
fullmetadata.then(e=>setZMeta(e))
variables.then(e=> {setVariables(e)})
return () => { isMounted = false; };
}, [initStore]);

Expand All @@ -57,21 +62,14 @@ export function LandingHome() {

useEffect(()=>{
setColormap(GetColorMapTexture(colormap, settings.cmap, 1, "#000000", 0, settings.flipCmap));
},[settings.cmap, colormap, settings.flipCmap, setColormap])

useEffect(()=>{
variables.then(e=> setVariables(e))
fullmetadata.then(e=> setZMeta(e))
},[])
},[settings.cmap, settings.flipCmap])

//These values are passed to the Plot Component
const plotObj = useMemo(() => ({
plotType: settings.plotType,
ZarrDS,
variable,
bgcolor,
canvasWidth
}), [settings.plotType, ZarrDS, variable, bgcolor, canvasWidth]);
}), [settings.plotType, ZarrDS, variable, canvasWidth]);

//This is the data being passed down the plot tree
const analysisObj = useMemo(() => ({
Expand All @@ -84,12 +82,10 @@ export function LandingHome() {

return (
<>
{/* <PaneManager /> */}
<PaneStore variablesPromise={variables} onSettingsChange={setSettings} />
{canvasWidth < 10 && variable != "Default" && <ShowAnalysis onClick={()=>setCanvasWidth(window.innerWidth*.5)} canvasWidth={canvasWidth} />}
{canvasWidth > 10 && <MiddleSlider canvasWidth={canvasWidth} setCanvasWidth={setCanvasWidth}/>}
<Loading showLoading={showLoading} />
{canvasWidth > 10 && <Analysis values={analysisObj.values} variables={variables} />}
{canvasWidth > 10 && <Analysis values={analysisObj.values} />}
{variable === "Default" && <VariableScroller zMeta={zMeta}/>}
{variable != "Default" && <Plot values={plotObj} setShowLoading={setShowLoading} />}
{metadata && <Metadata data={metadata} /> }
Expand Down
26 changes: 6 additions & 20 deletions src/components/plots/Analysis.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-nocheck Analysis requires quite a lot of work to mesh with new UI. Will Monkey with that later
import React, { useEffect, useMemo, useRef } from 'react'
import { useState } from 'react'
import { Canvas } from '@react-three/fiber'
Expand All @@ -19,31 +22,12 @@ interface Array{
shape:number[],
stride:number[]
}
interface AnalysisParameters {
values: {
ZarrDS: ZarrDataset;
canvasWidth: number;
}
variables: Promise<string[]>
}

// This wrapper handles loading state
export function Analysis({ values, variables }: AnalysisParameters) {
const [optionsVariables, setOptionsVariables] = useState<{ text: string; value: string }[] | null>(null);

useEffect(() => {
getVariablesOptions(variables).then(setOptionsVariables);
}, [variables]);

if (!optionsVariables) return null;

return <AnalysisLoaded values={values} optionsVariables={optionsVariables} />;
}

// This renders only when data is ready and uses hooks safely
function AnalysisLoaded({ values, optionsVariables }: {
export function Analysis({ values }: {
values: { ZarrDS: ZarrDataset; canvasWidth: number };
optionsVariables: { text: string; value: string }[];
}) {
const {dimNames, dimArrays, dimUnits, setDimNames, setDimArrays, setDimUnits} = useGlobalStore(
useShallow(state=>({
Expand All @@ -55,6 +39,8 @@ function AnalysisLoaded({ values, optionsVariables }: {
setDimUnits: state.setDimUnits
})))


const variables = useGlobalStore(state => state.variables)
const {ZarrDS, canvasWidth} = values
const scaleObjRef = useRef<Record<string, { min: number; max: number }>>({});
const setFlipY = useGlobalStore(state=>state.setFlipY)
Expand Down
59 changes: 12 additions & 47 deletions src/components/plots/DataCube.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as THREE from 'three'
import { vertexShader, fragmentShader } from '@/components/textures/shaders';
import { usePaneInput, usePaneFolder, useSliderBlade, useTweakpane } from '@lazarusa/react-tweakpane'
import { createPaneContainer } from '@/components/ui';
import { useGlobalStore } from '@/utils/GlobalStates';
import { useGlobalStore, usePlotStore } from '@/utils/GlobalStates';
import { useShallow } from 'zustand/shallow';

interface DataCubeProps {
Expand All @@ -12,8 +12,16 @@ interface DataCubeProps {

export const DataCube = ({ volTexture }: DataCubeProps ) => {


const {shape, colormap, flipY} = useGlobalStore(useShallow(state=>({shape:state.shape, colormap:state.colormap, flipY:state.flipY}))) //We have to useShallow when returning an object instead of a state. I don't fully know the logic yet

const {valueRange, xRange, yRange, zRange, quality} = usePlotStore(useShallow(state => ({
valueRange: state.valueRange,
xRange: state.xRange,
yRange: state.yRange,
zRange: state.zRange,
quality: state.quality
})))
const paneContainer = createPaneContainer("plot-pane");
const pane = useTweakpane(
{
Expand Down Expand Up @@ -43,49 +51,6 @@ export const DataCube = ({ volTexture }: DataCubeProps ) => {
step: 25,
})

const [xMin] = useSliderBlade(pane, {
label: 'xmin',
value: -1,
min: -1,
max: 1,
step: 0.01,
})
const [xMax] = useSliderBlade(pane, {
label: 'xmax',
value: 1,
min: -1,
max: 1,
step: 0.01,
})
const [yMin] = useSliderBlade(pane, {
label: 'ymin',
value: -1,
min: -1,
max: 1,
step: 0.01,
})
const [yMax] = useSliderBlade(pane, {
label: 'ymax',
value: 1,
min: -1,
max: 1,
step: 0.01,
})
const [zMin] = useSliderBlade(pane, {
label: 'zmin',
value: -1,
min: -1,
max: 1,
step: 0.01,
})
const [zMax] = useSliderBlade(pane, {
label: 'zmax',
value: 1,
min: -1,
max: 1,
step: 0.01,
})

const [flip] = usePaneInput(
pane,
'flip',
Expand All @@ -103,9 +68,9 @@ export const DataCube = ({ volTexture }: DataCubeProps ) => {
cameraPos: { value: new THREE.Vector3() },
threshold: {value: threshold},
scale: {value: shape},
flatBounds:{value: new THREE.Vector4(xMin,xMax,yMin,yMax)},
vertBounds:{value: new THREE.Vector2(zMin,zMax)},
steps: { value: steps },
flatBounds:{value: new THREE.Vector4(xRange[0],xRange[1],zRange[0],zRange[1])},
vertBounds:{value: new THREE.Vector2(yRange[0],yRange[1])},
steps: { value: quality },
flip: {value: flip }
},
vertexShader,
Expand Down
22 changes: 10 additions & 12 deletions src/components/plots/Plot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,19 @@ import { PointCloud, UVCube, DataCube } from '@/components/plots';
import { Canvas, useThree } from '@react-three/fiber';
import { ArrayToTexture, DefaultCubeTexture } from '@/components/textures';
import { ZarrDataset } from '../zarr/ZarrLoaderLRU';
import { useGlobalStore } from '@/utils/GlobalStates';
import { useGlobalStore, usePlotStore } from '@/utils/GlobalStates';
import { useShallow } from 'zustand/shallow';

interface PlotParameters{
values:{
plotType:string;
ZarrDS: ZarrDataset;
variable:string;
bgcolor:string;
canvasWidth:number
}
setShowLoading: React.Dispatch<React.SetStateAction<boolean>>;

}


const Plot = ({values,setShowLoading}:PlotParameters) => {

const {
Expand All @@ -41,12 +38,13 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
setDimNames:state.setDimNames,
setDimUnits:state.setDimUnits}
)))

const colormap = useGlobalStore(state=>state.colormap)
const {plotType,ZarrDS,variable,bgcolor,canvasWidth} = values;

const {ZarrDS,variable,canvasWidth} = values;
const plotType = usePlotStore(state => state.plotType)

const [texture, setTexture] = useState<THREE.DataTexture | THREE.Data3DTexture | null>(null)
const [currentBg, setCurrentBg] = useState(bgcolor || 'var(--background)')
// const [currentBg, setCurrentBg] = useState(bgcolor || 'var(--background)')
const [show, setShow] = useState<boolean>(true)

const [windowWidth, setWindowWidth] = useState<number>(0);
Expand All @@ -63,7 +61,7 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'data-theme') {
setCurrentBg('var(--background)')
// setCurrentBg('var(--background)')
}
})
})
Expand All @@ -76,9 +74,9 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
}, [])

// Update background when bgcolor changes
useEffect(() => {
setCurrentBg(bgcolor || 'var(--background)')
}, [bgcolor])
// useEffect(() => {
// setCurrentBg(bgcolor || 'var(--background)')
// }, [bgcolor])

//DATA LOADING
useEffect(() => {
Expand Down Expand Up @@ -151,7 +149,7 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
<Canvas camera={{ position: [-4.5, 3, 4.5], fov: 50 }}
frameloop="demand"
style={{
background: currentBg
// background: currentBg
}}
>
{/* Volume Plots */}
Expand Down
43 changes: 9 additions & 34 deletions src/components/plots/PointCloud.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { useMemo } from 'react'
import { pointFrag, pointVert } from '@/components/textures/shaders'
import { usePaneInput, usePaneFolder, useSliderBlade, useTweakpane } from '@lazarusa/react-tweakpane'
import { createPaneContainer } from '@/components/ui';
import { useGlobalStore } from '@/utils/GlobalStates';
import { useGlobalStore, usePlotStore } from '@/utils/GlobalStates';
import { useShallow } from 'zustand/shallow';

interface PCProps {
texture: THREE.Data3DTexture | THREE.DataTexture | null,
Expand All @@ -16,39 +17,13 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{
const {texture, colormap } = textures;
const paneContainer = createPaneContainer("plot-cloud");
const flipY = useGlobalStore(state=>state.flipY)
const pane = useTweakpane(
{
scalePoints: false,
},
{
title: 'Point cloud',
container: paneContainer ?? undefined,
expanded: false,
}
);

const {scalePoints, scaleIntensity, pointSize} = usePlotStore(useShallow(state => ({
scalePoints: state.scalePoints,
scaleIntensity: state.scaleIntensity,
pointSize: state.pointSize
})))

const [pointScale] = useSliderBlade(pane, {
label: 'Point Size',
value: 1,
min: 1,
max: 100,
step: 1,
})
const [scalePoints] = usePaneInput(
pane,
'scalePoints',
{
label: 'Scale Points By Value',
value: false
}
)
const [scaleIntensity] = useSliderBlade(pane, {
label: 'Scale Intensity',
value: 2,
min: 1,
max: 10,
step: 0.2,
})
//Extract data and shape from Data3DTexture
const { data, width, height, depth } = useMemo(() => {
if (!(texture instanceof THREE.Data3DTexture)) {
Expand Down Expand Up @@ -104,7 +79,7 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{
const shaderMaterial = new THREE.ShaderMaterial({
glslVersion: THREE.GLSL3,
uniforms: {
pointSize: {value: pointScale},
pointSize: {value: pointSize},
cmap: {value: colormap},
scalePoints:{value: scalePoints},
scaleIntensity: {value: scaleIntensity}
Expand Down
8 changes: 2 additions & 6 deletions src/components/textures/colormap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,12 @@ export function GetColorMapTexture(
colData[lastIndex + 2] = to_nan[2];
colData[lastIndex + 3] = nan_alpha;
if (texture) {
// Update the existing texture data
(texture.image.data as Uint8Array).set(colData);
texture.needsUpdate = true;
return texture;
} else {
texture.dispose()
}
// Create a new texture if not already available
const newTexture = new THREE.DataTexture(colData, rgbv.length + 1, 1, THREE.RGBAFormat);
newTexture.needsUpdate = true;
return newTexture;
}
}

// export function genRand(count: number) {
Expand Down
Loading