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
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ module.exports = {
{ allowConstantExport: true },
],
},
}
}
20 changes: 14 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
"scripts": {
"prChecks": "pnpm lint && pnpm buildRepo",
"buildRepo": "pnpm rmBuild && pnpm build",
"rmBuild": "pnpm -r exec rm -rf out",
"rmBuild": "pnpm -r exec rm -rf dist",
"test": "vitest run",
"dev": "vite --host",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 20",
"preview": "vite preview"
},
"dependencies": {
Expand All @@ -40,12 +40,20 @@
"zarrita": "^0.5.1"
},
"devDependencies": {
"@types/react": "^19.1.0",
"@eslint/js": "^9.24.0",
"@types/node": "^22.14.1",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@typescript-eslint/eslint-plugin": "^8.8.1",
"@typescript-eslint/parser": "^8.8.1",
"@vitejs/plugin-react": "^4.3.2",
"@typescript-eslint/eslint-plugin": "^8.30.1",
"@typescript-eslint/parser": "^8.30.1",
"@vitejs/plugin-react": "^4.4.0",
"eslint": "^8.57.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^16.0.0",
"typescript": "^5.6.2",
"typescript-eslint": "^8.30.1",
"vite": "^6.2.5"
}
}
6 changes: 3 additions & 3 deletions src/components/AboutModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const AboutModal = () => {
×
</button>
{/* <img src={logoSF} alt="SeasFire" width={"80%"}/> */}
<h1>ViZarrDev</h1>
<h1>ViZarrStores</h1>
<a> builds on the lessons learned from the visualization prototype from the SeasFire project. </a>

<p>
Expand All @@ -44,8 +44,8 @@ const AboutModal = () => {
Alonso, L., Gans, F., Karasante, I., Ahuja, A., Prapas, I., Kondylatos, S., Papoutsis, I., Panagiotou, E., Mihail, D., Cremer, F., Weber, U., & Carvalhais, N. (2023). SeasFire Cube: A Global Dataset for Seasonal Fire Modeling in the Earth System (0.3) [Data set]. Zenodo. https://doi.org/10.5281/zenodo.8055879
</p>
<p> <strong> Contact :</strong></p>
<a href="https://lazarusa.github.io/" target='_blank'>Lazaro Alonso &</a>
<a href="https://www.bgc-jena.mpg.de/person/jpoehls/2206" target='_blank'> Jeran Poehls</a>
<a href="https://lazarusa.github.io/" target='_blank' rel="noreferrer">Lazaro Alonso &</a>
<a href="https://www.bgc-jena.mpg.de/person/jpoehls/2206" target='_blank' rel="noreferrer"> Jeran Poehls</a>

<p>Max-Planck Institute for Biogeochemistry<br/>
Hans-Knöll Str. 10<br/>
Expand Down
27 changes: 19 additions & 8 deletions src/components/CanvasGeometry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { lightTheme } from '@/utils/levaTheme'
import { ArrayToTexture, DefaultCube } from './TextureMakers';
import { DataCube, PointCloud } from './PlotObjects';

console.log(DataCube)

const storeURL = "https://s3.bgc-jena.mpg.de:9000/esdl-esdc-v3.0.2/esdc-16d-2.5deg-46x72x1440-3.0.2.zarr"

Expand All @@ -28,16 +29,26 @@ export function CanvasGeometry() {
}
})
const [texture, setTexture] = useState<THREE.DataTexture | THREE.Data3DTexture | null>(null)
const [shape, setShape] = useState<THREE.Vector2 | THREE.Vector3>(new THREE.Vector3(2, 2, 2))

const [_shape, setShape] = useState<THREE.Vector3>(new THREE.Vector3(2, 2, 2))
// because, volTexture is expected to be a THREE.Vector3
useEffect(() => {
if (variable != "Default") {
//Need to add a check somewhere here to swap to 2D or 3D based on shape. Probably export two variables from GetArray
GetArray(storeURL, variable).then((data) => {
const [texture,shape] = ArrayToTexture(data)
setTexture(texture)
const shapeRatio = shape[1] / shape[2] * 2;
setShape(new THREE.Vector3(2, shapeRatio, 2))
GetArray(storeURL, variable).then((result) => {
// result now contains: { data: TypedArray, shape: number[], dtype: string }
const [texture, _shape] = ArrayToTexture({
data: result.data,
shape: result.shape
})
console.log(_shape)
if (texture instanceof THREE.DataTexture || texture instanceof THREE.Data3DTexture) {
setTexture(texture)
} else {
console.error("Invalid texture type returned from ArrayToTexture");
setTexture(null);
}
const shapeRatio = result.shape[1] / result.shape[2] * 2;
setShape(new THREE.Vector3(2, shapeRatio, 2));
})
}
else{
Expand All @@ -53,7 +64,7 @@ export function CanvasGeometry() {
<Canvas shadows camera={{ position: [4.5, 2, 4.5], fov: 50 }}
frameloop="demand"
>
{plotter == "volume" && <DataCube volTexture={texture} shape={shape}/>}
{plotter == "volume" && <DataCube volTexture={texture} shape={_shape}/>}
{plotter == "point-cloud" && <PointCloud texture={texture} />}
<Center top position={[-1, 0, 1]}>
{/* <mesh rotation={[0, Math.PI / 4, 0]}>
Expand Down
12 changes: 6 additions & 6 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import './Footer.css';
const Footer = () => (
<div className="footer">
<div className="large-screen-logo">
<a href="https://www.bgc-jena.mpg.de/en/bgi/mdi" target="_blank">
<a href="https://www.bgc-jena.mpg.de/en/bgi/mdi" target="_blank" rel="noreferrer">
<img src={logoBGC_MPI} alt="logoMPI" height={35}/>
</a>
</div>
<div className="small-screen-logos">
<a href="https://www.bgc-jena.mpg.de/en/bgi/mdi" target="_blank">
<a href="https://www.bgc-jena.mpg.de/en/bgi/mdi" target="_blank" rel="noreferrer">
<img src={logoBGC} alt="logoBGC" height={35}/>
</a>
</div>
<div className="expandable-text">
<p>Ⓒ <a href="https://github.com/EarthyScience/FireSight?tab=Apache-2.0-1-ov-file#readme" target="_blank">Apache License, Version 2.0</a></p>
<span>Contact :<a href="https://lazarusa.github.io/" target='_blank'>Lazaro Alonso</a>&
<a href="https://www.bgc-jena.mpg.de/person/jpoehls/2206" target='_blank'>Jeran Poehls</a>
<p>Ⓒ <a href="https://github.com/EarthyScience/FireSight?tab=Apache-2.0-1-ov-file#readme" target="_blank" rel="noreferrer">Apache License, Version 2.0</a></p>
<span>Contact :<a href="https://lazarusa.github.io/" target='_blank' rel="noreferrer">Lazaro Alonso</a>&
<a href="https://www.bgc-jena.mpg.de/person/jpoehls/2206" target='_blank' rel="noreferrer">Jeran Poehls</a>
</span>

</div>
<div className="small-screen-logos">
<a href="https://www.bgc-jena.mpg.de/en/bgi/home" target="_blank">
<a href="https://www.bgc-jena.mpg.de/en/bgi/home" target="_blank" rel="noreferrer">
<img src={logoMPI} alt="logoMPI" className="small-screen-logo" height={35}/>
</a>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './Navbar.css'
const Navbar = () => {
return (
<nav className="navbar">
<a href="https://github.com/EarthyScience/ViZarrDev" target="_blank">
<a href="https://github.com/EarthyScience/ViZarrDev" target="_blank" rel="noreferrer">
<img src={logoSeasFire} alt="ViZarrDev"/>
</a>
<AboutButton />
Expand Down
12 changes: 4 additions & 8 deletions src/components/PlotObjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ import vertexShader from '@/utils/shaders/vertex.glsl';
import fragmentShader from '@/utils/shaders/fragment.glsl';
import { useControls } from 'leva';
import { GetColorMapTexture } from '@/utils/colormap';
import { useThree } from '@react-three/fiber';
import pointVert from '@/utils/shaders/pointVertex.glsl';
import pointFrag from '@/utils/shaders/pointFrag.glsl';



const colormaps = ['viridis', 'plasma', 'inferno', 'magma', 'Accent', 'Blues',
'CMRmap', 'twilight', 'tab10', 'gist_earth', 'cividis',
'Spectral', 'gist_stern', 'gnuplot', 'gnuplot2', 'ocean', 'turbo',
Expand Down Expand Up @@ -121,11 +118,11 @@ export const DataCube = ({ volTexture, shape }: DataCubeProps ) => {

useEffect(()=>{
setColormap(GetColorMapTexture(colormap,cmap));
},[cmap])
},[cmap, colormap])

return (
<>
<mesh ref={meshRef} rotation-y={Math.PI / 2} geometry={geometry}>
<mesh ref={meshRef} rotation={[0, Math.PI / 2, 0]} geometry={geometry}>
<primitive attach="material" object={shaderMaterial} />
</mesh>
</>
Expand Down Expand Up @@ -179,8 +176,7 @@ export const PointCloud = ({texture} : PCProps )=>{
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const index = x + y * width + z * width * height;
const value = data[index] || 0;

const value = (data as number[])[index] || 0;
// Skip zero or invalid values if needed
if (value > 0) {
// Normalize coordinates to [-0.5, 0.5] range
Expand Down Expand Up @@ -222,7 +218,7 @@ export const PointCloud = ({texture} : PCProps )=>{

useEffect(()=>{
setColormap(GetColorMapTexture(colormap,cmap));
},[cmap])
},[cmap, colormap])
return (
<points geometry={geometry} material={shaderMaterial}/>
);
Expand Down
49 changes: 32 additions & 17 deletions src/components/TextureMakers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
import * as THREE from 'three'

interface Array {
data: Float32Array | Float64Array | Int32Array | Uint32Array;
shape: number[];
data: number[];
stride:number[]
}


// ? Please, try when possible to define the types of your variables. Otherwise building will fail.
function ArrayTo2D(array: Array){
//We assume there is no slicing here. That will occur in the ZarrLoader stage. This is just pure data transfer
const shape = array.shape;
const data = array.data;
const data = Array.from(array.data);

const width = shape[0];
const height = shape[1];
Expand Down Expand Up @@ -47,7 +46,7 @@ function ArrayTo2D(array: Array){

function ArrayTo3D(array: Array){
const shape = array.shape;
const data = array.data;
const data = Array.from(array.data);
const [lz,ly,lx] = shape


Expand Down Expand Up @@ -76,20 +75,36 @@ function ArrayTo3D(array: Array){

}

export function ArrayToTexture(array: Array){
const shape = array.shape;
const texture = shape.length == 3 ? ArrayTo3D(array) : ArrayTo2D(array);
return [texture, shape];
export function ArrayToTexture(array: Array) {
if (!array || !array.shape || !array.data) {
console.error('Invalid array data received');
return [DefaultCube(), [2, 2, 2]];
}

try {
const shape = array.shape;
const texture = shape.length === 3 ? ArrayTo3D(array) : ArrayTo2D(array);
return [texture, shape];
} catch (error) {
console.error('Error creating texture:', error);
return [DefaultCube(), [2, 2, 2]];
}
}

export function DefaultCube(){
const data = Array.from({ length: 1000 }, () => Math.random() < 0.2 ? NaN : Math.random());
const shape = [10,10,10]
const array = {
data,
shape,
stride:[1,1,1]
export function DefaultCube() {
// Create a Float32Array instead of regular array
const data = new Float32Array(1000);
// Fill with random values
for (let i = 0; i < data.length; i++) {
data[i] = Math.random() < 0.2 ? NaN : Math.random();
}
const texture = ArrayTo3D(array)
return texture

const shape = [10, 10, 10];
const array: Array = {
data,
shape
};

const texture = ArrayTo3D(array);
return texture;
}
72 changes: 46 additions & 26 deletions src/components/TimeSeries.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,56 @@
import * as THREE from 'three'
import { Canvas } from '@react-three/fiber';
import { Center, OrbitControls, Environment } from '@react-three/drei'
import { OrbitControls } from '@react-three/drei'
import { useMemo } from 'react';

interface TimeSeriesProps {
coords?: [number, number, number]; // [x, y, z] coordinates
data?: number[]; // Optional time series data
}



export function TimeSeries({coords} : ){
export function TimeSeries({ data = [] }: TimeSeriesProps) {
//This function will take in some coords, get the timeseries from zarr loader and create a new THREE scene with a static camera. Need to create a graph basically

const timeseries = useMemo(()=>{
return null
},[coords])

const lineObj = useMemo(()=>{
// ? just fixed interface, `coords` should be still be passed in.
const timeseries = useMemo(() => {
if (!data.length) return null;

// Convert data to normalized values between -1 and 1
const maxVal = Math.max(...data);
const minVal = Math.min(...data);
return data.map((val, index) => {
const normalizedY = ((val - minVal) / (maxVal - minVal)) * 2 - 1;
const normalizedX = (index / data.length) * 2 - 1;
return [normalizedX, normalizedY, 0];
}).flat();
}, [data]);

const lineObj = useMemo(() => {
//Need to convert whatever timeseries is into vectors. Depends on the camera and scene zoom.
//Currently this creates a new one each time coords changes. Will need to fix later
const points = timeseries;
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
if (!timeseries) return null;

const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
const obj = new THREE.Line(geometry,material);
return obj;
},[coords])


return(
<>
<Canvas>
<primitive object={lineObj}>
</Canvas>
</>
)
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(timeseries, 3));

const material = new THREE.LineBasicMaterial({
color: 0x00ff00,
linewidth: 2
});

return new THREE.Line(geometry, material);
}, [timeseries]);

return (
<div style={{ width: '100%', height: '300px' }}>
<Canvas
camera={{ position: [0, 0, 5], fov: 75 }}
style={{ background: '#f0f0f0' }}
>
{lineObj && <primitive object={lineObj} />}
<OrbitControls enableRotate={false} enableZoom={true} />
<gridHelper args={[2, 10]} rotation={[Math.PI / 2, 0, 0]} />
<axesHelper args={[1]} />
</Canvas>
</div>
);
}
Loading