Skip to content
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
5 changes: 5 additions & 0 deletions src/GlobalStates/PlotStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type PlotState ={
maskValue: number;
cameraPosition: THREE.Vector3;
disablePointScale: boolean;
camera: THREE.Camera | undefined;

setQuality: (quality: number) => void;
setTimeScale: (timeScale : number) =>void;
Expand Down Expand Up @@ -119,8 +120,10 @@ type PlotState ={
setUseOrtho: (useOrtho: boolean) => void;
setFillValue: (fillValue: number | undefined) => void;
setCameraPosition: (cameraPosition: THREE.Vector3) => void;

}


export const usePlotStore = create<PlotState>((set, get) => ({
plotType: "volume",
pointSize: 5,
Expand Down Expand Up @@ -185,6 +188,7 @@ export const usePlotStore = create<PlotState>((set, get) => ({
borderWidth: 0.05,
cameraPosition: new THREE.Vector3(0, 0, 5),
disablePointScale: false,
camera: undefined,

setVTransferRange: (vTransferRange) => set({ vTransferRange }),
setVTransferScale: (vTransferScale) => set({ vTransferScale }),
Expand Down Expand Up @@ -242,4 +246,5 @@ export const usePlotStore = create<PlotState>((set, get) => ({
setUseOrtho: (useOrtho) => set({ useOrtho }),
setFillValue: (fillValue) => set({ fillValue }),
setCameraPosition: (cameraPosition) => set({ cameraPosition }),

}))
2 changes: 2 additions & 0 deletions src/GlobalStates/ZarrStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type ZarrState = {
fetchOptions: FetchStoreOptions | null;
abortController: AbortController | null;
fetchKey: number;
blobKey: string | undefined; // The key for the stored File blob for a local NC

setZSlice: (zSlice: [number , number | null]) => void;
setYSlice: (ySlice: [number , number | null]) => void;
Expand Down Expand Up @@ -63,6 +64,7 @@ export const useZarrStore = create<ZarrState>((set, get) => ({
fetchOptions: null,
abortController: null,
fetchKey: 0,
blobKey: undefined,

setZSlice: (zSlice) => set({ zSlice }),
setYSlice: (ySlice) => set({ ySlice }),
Expand Down
35 changes: 34 additions & 1 deletion src/components/StoreInitializer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
import { useSearchParams } from "next/navigation";
import { useGlobalStore } from "@/GlobalStates/GlobalStore";
import { useZarrStore } from '@/GlobalStates/ZarrStore';
import { usePlotStore } from "@/GlobalStates/PlotStore";
import { useShallow } from 'zustand/shallow';
import { isRemoteStore } from '@/utils/isRemoteStore';
import { loadNetCDF } from "@/utils/loadNetCDF";
import { loadFile } from "@/utils/IndexDB";
import { LoadLocalZarr } from "./ui/MainPanel/LocalZarr";

function StoreInitializerInner() {
const searchParams = useSearchParams();
Expand All @@ -17,11 +21,40 @@

useEffect(() => {
const store = searchParams.get("store");
let data = searchParams.get("data")

Check failure on line 24 in src/components/StoreInitializer.tsx

View workflow job for this annotation

GitHub Actions / core

'data' is never reassigned. Use 'const' instead
if (data){
try{
const fullObj = JSON.parse(data);
if (fullObj.zarrState.blobKey){ // If NC local must load file beforehand
const blobKey = fullObj.zarrState.blobKey
const isNC = fullObj.zarrState.useNC
loadFile(blobKey).then(cache =>{
if (!isNC){
LoadLocalZarr(cache?.blob as File[])
} else {
//@ts-ignore cache is what we want

Check failure on line 35 in src/components/StoreInitializer.tsx

View workflow job for this annotation

GitHub Actions / core

Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free
const file = cache.blob as File
loadNetCDF(file, file.name).then(() => {
useZarrStore.setState(fullObj.zarrState);
useGlobalStore.setState(fullObj.globalState);
usePlotStore.setState(fullObj.plotState);
})
}
})
} else {
useZarrStore.setState(fullObj.zarrState)
useGlobalStore.setState(fullObj.globalState)
usePlotStore.setState(fullObj.plotState)
}
} catch {
console.error('Something Failed :/')
}
}
Comment thread
TheJeran marked this conversation as resolved.
if (!store) {
setStoreFromURL(false);
return;
}

const isNC = searchParams.get("format") === "nc";
setUseNC(isNC);
setFetchNC(isNC);
Expand Down
6 changes: 3 additions & 3 deletions src/components/plots/AxisLines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ const CubeAxis = ({flipX, flipY, flipDown}: {flipX: boolean, flipY: boolean, fli
const zDimScale = zResolution/(zResolution-1)
const zValDelta = 1/(zResolution-1)

const xTitleOffset = useMemo(() => (dimNames[shapeLength - 1].length * AXIS_CONSTANTS.TITLE_FONT_SIZE_FACTOR / 2 + 0.1) * globalScale, [dimNames, globalScale]);
const yTitleOffset = useMemo(() => (dimNames[shapeLength - 2].length * AXIS_CONSTANTS.TITLE_FONT_SIZE_FACTOR / 2 + 0.1) * globalScale, [dimNames, globalScale]);
const zTitleOffset = useMemo(() => (dimNames[shapeLength - 3].length * AXIS_CONSTANTS.TITLE_FONT_SIZE_FACTOR / 2 + 0.1) * globalScale, [dimNames, globalScale]);
const xTitleOffset = useMemo(() => (dimNames[shapeLength - 1]?.length * AXIS_CONSTANTS.TITLE_FONT_SIZE_FACTOR / 2 + 0.1) * globalScale, [dimNames, globalScale]);
const yTitleOffset = useMemo(() => (dimNames[shapeLength - 2]?.length * AXIS_CONSTANTS.TITLE_FONT_SIZE_FACTOR / 2 + 0.1) * globalScale, [dimNames, globalScale]);
const zTitleOffset = useMemo(() => (dimNames[shapeLength - 3]?.length * AXIS_CONSTANTS.TITLE_FONT_SIZE_FACTOR / 2 + 0.1) * globalScale, [dimNames, globalScale]);
Comment thread
TheJeran marked this conversation as resolved.

return (
<group visible={plotType != 'sphere' && plotType != 'flat' && !hideAxis}>
Expand Down
11 changes: 11 additions & 0 deletions src/components/plots/Plot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Orbiter = ({isFlat} : {isFlat : boolean}) =>{
const hasMounted = useRef(false);
const cameraRef = useRef<THREE.Camera | null>(null)
const {set, camera, size} = useThree()

// Reset Camera Position and Target
useEffect(()=>{
if (!hasMounted.current) {
Expand Down Expand Up @@ -81,6 +82,7 @@ const Orbiter = ({isFlat} : {isFlat : boolean}) =>{
}
},[resetCamera, isFlat])

// ---- Switch from Perspective to Orthographic ---- //
useEffect(()=>{
if (hasMounted.current){
let newCamera;
Expand Down Expand Up @@ -117,6 +119,7 @@ const Orbiter = ({isFlat} : {isFlat : boolean}) =>{
}
},[useOrtho])

// ---- Move camera to position ---- //
useEffect(()=>{
const cam = cameraRef.current
const controls = orbitRef.current
Expand All @@ -136,6 +139,14 @@ const Orbiter = ({isFlat} : {isFlat : boolean}) =>{
}
},[cameraPosition])

// ---- Camera Ref for state saves ---- //
useEffect(()=>{
usePlotStore.setState({camera})
return () => {
usePlotStore.setState({camera: undefined})
}
},[camera])
Comment thread
TheJeran marked this conversation as resolved.

return (
<OrbitControls
ref={orbitRef}
Expand Down
1 change: 0 additions & 1 deletion src/components/ui/MainPanel/LocalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const LocalContent = ({
<LocalZarr
setShowLocal={setShowLocal ?? (() => {})}
setOpenVariables={onOpenDescription}
setInitStore={setInitStore}
/>
)}
</div>
Expand Down
40 changes: 22 additions & 18 deletions src/components/ui/MainPanel/LocalNetCDF.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import React, {ChangeEvent, useState} from 'react'
import { Input } from '../input'
import { useGlobalStore } from '@/GlobalStates/GlobalStore';
import { loadNetCDF, NETCDF_EXT_REGEX } from '@/utils/loadNetCDF';

import { saveFile } from '@/utils/IndexDB';
import {
Alert,
AlertDescription,
AlertTitle,
} from '@/components/ui/alert';
import { isMobile } from '../MobileUIHider';
import { useZarrStore } from '@/GlobalStates/ZarrStore';

interface LocalNCType {
setOpenVariables: (open: boolean) => void;
Expand All @@ -20,23 +21,26 @@ const LocalNetCDF = ({ setOpenVariables}:LocalNCType) => {
// const {ncModule} = useZarrStore.getState()
const [ncError, setError] = useState<string | null>(null);

const handleFileSelect = async (event: ChangeEvent<HTMLInputElement>) => {
setError(null);
const files = event.target.files;
if (!files || files.length === 0) { setStatus(null); return; }
const file = files[0];
if (!NETCDF_EXT_REGEX.test(file.name)) {
setError('Please select a valid NetCDF (.nc, .netcdf, .nc3, .nc4) file.');
return;
}
try {
await loadNetCDF(file, file.name);
setOpenVariables(true)

} catch (e) {
setError(`Failed to load file: ${e instanceof Error ? e.message : String(e)}`);
}
};
const handleFileSelect = async (event: ChangeEvent<HTMLInputElement>) => {
setError(null);
const files = event.target.files;
if (!files || files.length === 0) { setStatus(null); return; }
const file = files[0];
if (!NETCDF_EXT_REGEX.test(file.name)) {
setError('Please select a valid NetCDF (.nc, .netcdf, .nc3, .nc4) file.');
return;
}
try {
await loadNetCDF(file, file.name);
const blobKey = `local_${file.name}`
await saveFile(file, blobKey)
useZarrStore.setState({blobKey})
Comment thread
TheJeran marked this conversation as resolved.
console.log('Set Key?')
setOpenVariables(true)
} catch (e) {
setError(`Failed to load file: ${e instanceof Error ? e.message : String(e)}`);
}
};

return (
<div className="w-full">
Expand Down
71 changes: 38 additions & 33 deletions src/components/ui/MainPanel/LocalZarr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,16 @@ import { useZarrStore } from '@/GlobalStates/ZarrStore';
import { useGlobalStore } from '@/GlobalStates/GlobalStore';
import { Input } from '../input';
import ZarrParser from '@/components/zarr/ZarrParser';
import { saveFile } from '@/utils/IndexDB';

interface LocalZarrType {
setShowLocal: React.Dispatch<React.SetStateAction<boolean>>;
setOpenVariables: (open: boolean) => void;
setInitStore: (store: string) => void;
}

const LocalZarr = ({setShowLocal, setOpenVariables, setInitStore}:LocalZarrType) => {
const setCurrentStore = useZarrStore(state => state.setCurrentStore)
const {setStatus} = useGlobalStore.getState()
const handleFileSelect = async (event: ChangeEvent<HTMLInputElement>) => {
const files = event.target.files;
if (!files || files.length === 0) {
setStatus(null)
return;
}
// Create a Map to hold the Zarr store data
export async function LoadLocalZarr(files:File[]){
// Create a Map to hold the Zarr store data
const fileMap = new Map<string, File>();

// The base directory name will be the first part of the relative path
const baseDir = files[0].webkitRelativePath.split('/')[0];

Expand All @@ -35,7 +26,6 @@ const LocalZarr = ({setShowLocal, setOpenVariables, setInitStore}:LocalZarrType)
fileMap.set('/' + relativePath, file); // Zarrita looks for a leading slash before variables. Need to add it back
}
}

// Create a custom zarrita store from the Map
const customStore: zarr.AsyncReadable = {
async get(key: string): Promise<Uint8Array | undefined> {
Expand All @@ -48,37 +38,52 @@ const LocalZarr = ({setShowLocal, setOpenVariables, setInitStore}:LocalZarrType)
// Open the Zarr store using the custom store
let store = await zarr.withMaybeConsolidatedMetadata(customStore);
if (!('contents' in store)){
console.log("Trying to parse?")
// Metadata is missing. We will need to parse variables here.
store = await ZarrParser(files, customStore)
}
const gs = await zarr.open(store, {kind: 'group'});
setCurrentStore(gs);
setShowLocal(false);
setOpenVariables(true);
setInitStore(`local_${baseDir}`)
setStatus(null)
useZarrStore.setState({ useNC: false})
const blobKey = `local_${baseDir}`
useGlobalStore.setState({initStore:blobKey})
useZarrStore.setState({ useNC: false, blobKey, currentStore:gs})
} catch (error) {
setStatus(null)

if (error instanceof Error) {
console.log(`Error opening Zarr store: ${error.message}`);
} else {
console.log('An unknown error occurred when opening the Zarr store.');
}
}
};
return (
<div>
<Input type="file" id="filepicker"
className='hover:drop-shadow-md hover:scale-[110%]'
style={{width:'200px', cursor:'pointer'}}
// @ts-expect-error `webkitdirectory` is non-standard attribute. TS doesn't know about it. It's used for cross-browser compatibility.
directory=''
webkitdirectory='true'
onChange={handleFileSelect}
/>
</div>
)
}

const LocalZarr = ({setShowLocal, setOpenVariables}:LocalZarrType) => {
const {setStatus} = useGlobalStore.getState()
const handleFileSelect = async (event: ChangeEvent<HTMLInputElement>) => {
const files = event.target.files;
if (!files || files.length === 0) {
setStatus(null)
return;
}
const baseDir = files[0].webkitRelativePath.split('/')[0];
LoadLocalZarr(Array.from(files)).then(()=>{
saveFile(Array.from(files), `local_${baseDir}`)
setShowLocal(false);
setOpenVariables(true);
setStatus(null)
})
};
return (
<div>
<Input type="file" id="filepicker"
className='hover:drop-shadow-md hover:scale-[110%]'
style={{width:'200px', cursor:'pointer'}}
// @ts-expect-error `webkitdirectory` is non-standard attribute. TS doesn't know about it. It's used for cross-browser compatibility.
directory=''
webkitdirectory='true'
onChange={handleFileSelect}
/>
</div>
)
}

export default LocalZarr
Expand Down
2 changes: 2 additions & 0 deletions src/components/ui/NavBar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { cn } from "@/lib/utils";
import { useGlobalStore } from '@/GlobalStates/GlobalStore';
import { usePlotStore } from '@/GlobalStates/PlotStore';
import { ParameterExport } from "./ParameterExport";
import { Orthographic, Perspective } from "../Elements/Icons";
import PerformanceMode from "./PerformanceMode";

Expand Down Expand Up @@ -108,6 +109,7 @@ const Navbar = React.memo(function Navbar() {
</Button>
<PlotLineButton />
<ExportImageSettings />
<ParameterExport />
<PerformanceMode />
</div>
</div>
Expand Down
Loading
Loading