From 118ebebb76d627148baa13af5f755edd948f23e7 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva Date: Wed, 25 Mar 2026 04:32:24 +0000 Subject: [PATCH 01/20] Skill v1 --- .../skills/create-prognostic-wrapper/SKILL.md | 943 ++++++++++++++++++ 1 file changed, 943 insertions(+) create mode 100644 .claude/skills/create-prognostic-wrapper/SKILL.md diff --git a/.claude/skills/create-prognostic-wrapper/SKILL.md b/.claude/skills/create-prognostic-wrapper/SKILL.md new file mode 100644 index 000000000..6f1fca9b5 --- /dev/null +++ b/.claude/skills/create-prognostic-wrapper/SKILL.md @@ -0,0 +1,943 @@ +--- +name: create-prognostic-wrapper +description: Create a new Earth2Studio prognostic model (px) wrapper from a reference inference script or repository +argument-hint: URL or local path to reference inference script/repo (optional — will be asked if not provided) +--- + +# Create Prognostic Model Wrapper + +Create a new Earth2Studio prognostic model wrapper by following every step below in order. +Each confirmation gate marked **[CONFIRM]** requires explicit user approval before proceeding. + +--- + +## Step 0 — Obtain Reference Script / Repository + +If `$ARGUMENTS` is provided, use it as the reference inference script or repository. + +- If it is a URL, use WebFetch to retrieve the content. +- If it is a local file path, read it directly. + +If `$ARGUMENTS` is empty or not provided, ask the user: + +> Please provide a reference inference script or +> repository URL/path that demonstrates how this model +> runs inference. This will be used to understand the +> model architecture, dependencies, input/output shapes, +> and variable mapping. + +Store the reference code content for use in subsequent steps. + +--- + +## Step 1 — Examine Reference & Propose Dependencies + +### 1a. Analyze the reference code + +Examine the reference inference script/repo to identify: + +- **Python packages** required (e.g., `torch`, `onnxruntime`, `einops`, `timm`, custom packages) +- **Model architecture** (PyTorch, ONNX, JAX, etc.) +- **Input/output tensor shapes** and variable names +- **Time step** of the model (e.g., 6h, 24h) +- **Spatial resolution** (lat/lon grid dimensions and spacing) +- **Checkpoint format** (`.pt`, `.onnx`, `.safetensors`, etc.) + +### 1b. Propose pyproject.toml dependency group + +Propose a new optional dependency group for `pyproject.toml`. Follow the existing pattern: + +```toml +# In [project.optional-dependencies] section of pyproject.toml +model-name = [ + "package1>=version", + "package2", +] +``` + +The group name should be lowercase-hyphenated (e.g., `pangu`, `aurora`, `stormcast`). + +Look at the existing groups in `pyproject.toml` +(lines ~59-257) for reference on naming and version +pinning conventions. + +**Also propose adding the new group to the `all` aggregate** in the appropriate line (px models line). + +### **[CONFIRM — Dependencies]** + +Present to the user: + +1. The proposed dependency group name +2. The list of packages with versions +3. Ask if the packages and group name look correct + +--- + +## Step 2 — Add Dependencies to pyproject.toml + +After confirmation, edit `pyproject.toml`: + +1. Add the new optional dependency group in alphabetical order + among the per-model extras +2. Add the group to the `all` aggregate (in the px models line) + +--- + +## Step 3 — Create Skeleton Class File + +### 3a. Determine class name and file name + +Based on the model name from the reference, propose: + +- **Class name**: PascalCase (e.g., `Pangu24`, `Aurora`, `StormCast`) +- **File name**: lowercase with underscores + (e.g., `pangu.py`, `aurora.py`, `stormcast.py`) +- **File path**: `earth2studio/models/px/.py` + +### 3b. Write skeleton with pseudocode + +Create the file with the full structure but pseudocode +implementations. Every `.py` file in `earth2studio/` +**must** start with this license header: + +```python +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +``` + +The skeleton must use **triple inheritance** and follow this exact structure: + +```python +from collections import OrderedDict +from collections.abc import Iterator + +import numpy as np +import torch + +from earth2studio.models.auto import AutoModelMixin, Package +from earth2studio.models.batch import batch_coords, batch_func +from earth2studio.models.px.base import PrognosticModel +from earth2studio.models.px.utils import PrognosticMixin +from earth2studio.utils import handshake_coords, handshake_dim +from earth2studio.utils.imports import ( + OptionalDependencyFailure, + check_optional_dependencies, +) +from earth2studio.utils.type import CoordSystem + +# Optional dependency imports (try/except pattern) +try: + import optional_package +except ImportError: + OptionalDependencyFailure("model-name") + optional_package = None + +VARIABLES = [...] # List of variable names from E2STUDIO_VOCAB + +class ModelName(torch.nn.Module, AutoModelMixin, PrognosticMixin): + """One-line description. + + Extended description of the model, its source, and any relevant details. + + Parameters + ---------- + core_model : torch.nn.Module + Core model instance + ...additional params... + + Note + ---- + For more information see: + """ + + def __init__(self, core_model, ...): + super().__init__() + # TODO: Initialize model + self.register_buffer("device_buffer", torch.empty(0)) + pass + + def input_coords(self) -> CoordSystem: + # TODO: Define input coordinates + pass + + @batch_coords() + def output_coords(self, input_coords: CoordSystem) -> CoordSystem: + # TODO: Define output coordinates + pass + + @batch_func() + def __call__(self, x: torch.Tensor, coords: CoordSystem) -> tuple[torch.Tensor, CoordSystem]: + # TODO: Single step forward + pass + + @batch_func() + def create_iterator( + self, + x: torch.Tensor, + coords: CoordSystem, + ) -> Iterator[tuple[torch.Tensor, CoordSystem]]: + # TODO: Time integration iterator + pass + + def to(self, device: torch.device | str) -> PrognosticModel: + # TODO: Device management + pass + + @classmethod + def load_default_package(cls) -> Package: + # TODO: Default checkpoint location + pass + + @classmethod + @check_optional_dependencies() + def load_model(cls, package: Package) -> PrognosticModel: + # TODO: Load model from package + pass +``` + +### **[CONFIRM — Skeleton]** + +Present to the user: + +1. The proposed class name +2. The proposed file name and path +3. Ask if these are acceptable + +--- + +## Step 4 — Implement Coordinate System + +### 4a. Map variables to E2STUDIO_VOCAB + +Read `earth2studio/lexicon/base.py` and verify every +variable the model uses exists in `E2STUDIO_VOCAB`. +The vocab contains 282 entries including: + +| Category | Examples | +|---|---| +| Surface wind | `u10m`, `v10m`, `ws10m`, `u100m`, `v100m` | +| Surface temp | `t2m`, `d2m`, `sst`, `skt` | +| Humidity | `r2m`, `q2m`, `tcwv` | +| Pressure | `sp`, `msl` | +| Precipitation | `tp`, `lsp`, `cp`, `tp06` | +| Pressure-level | `u50`-`u1000`, `v50`-`v1000`, `z50`-`z1000` | +| Cloud/radiation | `tcc`, `rlut`, `rsut` | + +Pressure levels available: 50, 100, 150, 200, 250, +300, 400, 500, 600, 700, 850, 925, 1000. + +If a variable in the reference model does NOT exist +in `E2STUDIO_VOCAB`, flag it to the user and discuss +whether to: + +- Map it to an existing vocab entry +- Propose adding a new vocab entry (separate step) + +### 4b. Implement input_coords + +```python +def input_coords(self) -> CoordSystem: + """Input coordinate system of the prognostic model. + + Returns + ------- + CoordSystem + Coordinate system dictionary + """ + return OrderedDict({ + "batch": np.empty(0), # MUST be first, MUST be np.empty(0) + "time": np.empty(0), # Dynamic time dimension + "lead_time": np.array([np.timedelta64(0, "h")]), # Initial lead time (0h) + "variable": np.array(VARIABLES), + "lat": np.linspace(90, -90, num_lat, endpoint=...), # From reference + "lon": np.linspace(0, 360, num_lon, endpoint=False), # From reference + }) +``` + +**Rules:** + +- `batch` is always first with `np.empty(0)` +- `time` is `np.empty(0)` (dynamic) +- `lead_time` starts at `np.timedelta64(0, "h")` + unless the model requires history (multiple past + time steps) +- If the model needs history, `lead_time` should + contain negative timedeltas (e.g., `[-6h, 0h]`) +- `lat` typically goes from 90 to -90 (north to south) +- `lon` typically goes from 0 to 360 + +### 4c. Implement output_coords + +```python +@batch_coords() +def output_coords(self, input_coords: CoordSystem) -> CoordSystem: + """Output coordinate system. + + Parameters + ---------- + input_coords : CoordSystem + Input coordinates to validate and transform + + Returns + ------- + CoordSystem + Output coordinates with updated lead_time + + Raises + ------ + ValueError + If input coordinates are invalid + """ + target_input_coords = self.input_coords() + + # Validate dimensions exist at correct indices + handshake_dim(input_coords, "lead_time", 2) + handshake_dim(input_coords, "variable", 3) + handshake_dim(input_coords, "lat", 4) + handshake_dim(input_coords, "lon", 5) + + # Validate coordinate values match + handshake_coords(input_coords, target_input_coords, "variable") + handshake_coords(input_coords, target_input_coords, "lat") + handshake_coords(input_coords, target_input_coords, "lon") + + output_coords = input_coords.copy() + output_coords["lead_time"] = input_coords["lead_time"] + np.array([self._time_step]) + return output_coords +``` + +### **[CONFIRM — Coordinates]** + +Present to the user: + +1. The variable list and any mapping issues with + `E2STUDIO_VOCAB` +2. The spatial dimensions (lat/lon grid size and spacing) +3. Whether the model needs history (multiple lead times + in input) +4. The model time step (e.g., 6h, 24h) + +--- + +## Step 5 — Implement Forward Pass + +### 5a. Implement `__call__` + +```python +@batch_func() +def __call__( + self, + x: torch.Tensor, + coords: CoordSystem, +) -> tuple[torch.Tensor, CoordSystem]: + """Run prognostic model 1 step. + + Parameters + ---------- + x : torch.Tensor + Input tensor + coords : CoordSystem + Input coordinate system + + Returns + ------- + tuple[torch.Tensor, CoordSystem] + Output tensor and coordinates one time step ahead + """ + target_input_coords = self.input_coords() + handshake_coords(coords, target_input_coords, "variable") + handshake_dim(coords, "variable", 3) + + # Move to device + device = self.device_buffer.device + x = x.to(device) + + # Run forward pass + # TODO: Reshape input tensor for the core model + # TODO: Call core model + # TODO: Reshape output tensor back to earth2studio format + + out_coords = self.output_coords(coords) + return output, out_coords +``` + +Key implementation notes: + +- The `@batch_func()` decorator handles the batch + dimension — inside `__call__`, `x` has shape + `(batch, time, lead_time, variable, lat, lon)` +- Reshape from earth2studio's + `(batch, time, lead_time, variable, lat, lon)` to + whatever the core model expects +- Reshape back to + `(batch, time, lead_time, variable, lat, lon)` after + forward pass +- All tensor operations should happen on GPU when + possible + +### 5b. Implement create_iterator + +```python +@batch_func() +def create_iterator( + self, + x: torch.Tensor, + coords: CoordSystem, +) -> Iterator[tuple[torch.Tensor, CoordSystem]]: + """Create time-integration iterator. + + Parameters + ---------- + x : torch.Tensor + Initial condition tensor + coords : CoordSystem + Initial coordinate system + + Yields + ------ + tuple[torch.Tensor, CoordSystem] + Predicted state and coordinates at each time step + """ + # MUST yield initial condition first (step 0) + yield x, coords + + # Time integration loop (runs indefinitely) + current_x = x + current_coords = coords + while True: + # Apply front hook (for perturbation injection, etc.) + current_x, current_coords = self.front_hook(current_x, current_coords) + + # Forward step + current_x, current_coords = self.__call__(current_x, current_coords) + + # Apply rear hook (for post-processing, etc.) + current_x, current_coords = self.rear_hook(current_x, current_coords) + + yield current_x, current_coords +``` + +### **[CONFIRM — Forward Pass]** + +Show the user the pseudocode for `__call__` +(especially the reshape logic) and `create_iterator`. +Ask: + +1. Does the tensor reshaping logic look correct for + this model? +2. Are there any special considerations (e.g., multiple + ONNX models, interleaved time steps)? + +--- + +## Step 6 — Implement Model Loading + +### 6a. Implement load_default_package + +```python +@classmethod +def load_default_package(cls) -> Package: + """Default pre-trained model package on . + + Returns + ------- + Package + Model package + """ + return Package( + "hf://org/repo", # or ngc://, s3://, local path + cache_options={ + "cache_storage": Package.default_cache("model_name"), + "same_names": True, + }, + ) +``` + +### 6b. Implement load_model + +```python +@classmethod +@check_optional_dependencies() +def load_model( + cls, + package: Package, +) -> PrognosticModel: + """Load prognostic model from package. + + Parameters + ---------- + package : Package + Model package with checkpoint files + + Returns + ------- + PrognosticModel + Loaded model instance + """ + # Resolve checkpoint files + checkpoint_path = package.resolve("model.pt") + + # Load model + core_model = torch.load(checkpoint_path, map_location="cpu", weights_only=False) + core_model.eval() + + return cls(core_model) +``` + +**Key patterns:** + +- Use `package.resolve("filename")` to get cached + file paths +- Load with `map_location="cpu"` then let user call + `.to(device)` +- Set model to `eval()` mode +- Do NOT over-populate `load_model()` API — only + expose essential parameters +- Use `@check_optional_dependencies()` if the model + has optional deps + +### 6c. Implement .to() + +```python +def to(self, device: torch.device | str) -> PrognosticModel: + """Move model to device. + + Parameters + ---------- + device : torch.device | str + Target device + + Returns + ------- + PrognosticModel + Model on target device + """ + super().to(device) + # If using ONNX Runtime, destroy and recreate session on new device + # If using PyTorch, super().to(device) handles it + return self +``` + +### **[CONFIRM — Model Loading]** + +Present to the user: + +1. The checkpoint URL/path for `load_default_package` +2. The checkpoint file names and loading logic +3. Whether there are multiple checkpoint files +4. The `.to()` implementation (especially if ONNX or + non-PyTorch backend) + +--- + +## Step 7 — Register the Model + +### 7a. Add to `__init__.py` + +Edit `earth2studio/models/px/__init__.py`: + +- Add import in alphabetical order: + `from earth2studio.models.px. import ` + +### 7b. Verify pyproject.toml + +Confirm the dependency group was added in Step 2 and is included in the `all` aggregate. + +--- + +## Step 8 — Verify Style, Documentation, Format & Lint + +Before testing, verify the wrapper passes all code quality checks. + +### 8a. Run formatting + +```bash +make format +``` + +This runs `black` on the codebase. Fix any formatting issues in the new wrapper file and test file. + +### 8b. Run linting + +```bash +make lint +``` + +This runs `ruff` and `mypy`. Common issues to watch +for: + +- Missing type annotations on public functions +- Unused imports +- Import ordering issues +- Type errors from incorrect return types or missing + `CoordSystem` annotations + +Fix all errors before proceeding. + +### 8c. Check license headers + +```bash +make license +``` + +Verify that both the wrapper file +(`earth2studio/models/px/.py`) and the test +file (`test/models/px/test_.py`) have the +correct SPDX Apache-2.0 license header. + +### 8d. Verify documentation + +Check that: + +- The class docstring follows NumPy-style formatting + with `Parameters`, `Note`, etc. +- All public methods (`__call__`, `create_iterator`, + `input_coords`, `output_coords`, `to`, + `load_default_package`, `load_model`) have complete + docstrings with `Parameters`, `Returns`, `Raises` + sections as applicable +- Type hints are present on all public method + signatures + +If any checks fail, fix the issues and re-run until all pass cleanly. + +--- + +## Step 9 — Test Forward Pass with Random Data + +Write and run a quick smoke test script: + +```python +import torch +import numpy as np +from earth2studio.models.px import ModelName + +# Load model (or construct with dummy weights for testing) +model = ModelName(...) # Use dummy/test weights if real ones aren't available +model = model.to("cuda" if torch.cuda.is_available() else "cpu") + +# Get input coords +input_coords = model.input_coords() + +# Create random input tensor +shape = tuple(max(len(v), 1) for v in input_coords.values()) +x = torch.randn(shape) + +# Test __call__ +output, out_coords = model(x, input_coords) +print(f"Input shape: {x.shape}") +print(f"Output shape: {output.shape}") +print(f"Output lead_time: {out_coords['lead_time']}") + +# Test create_iterator (3 steps) +iterator = model.create_iterator(x, input_coords) +for i, (step_x, step_coords) in enumerate(iterator): + print(f"Step {i}: shape={step_x.shape}, lead_time={step_coords['lead_time']}") + if i >= 3: + break +``` + +Report results to the user. + +--- + +## Step 10 — Test Data Fetch with Random Source + +Test that the model's coordinate system works with Earth2Studio's data pipeline: + +```python +import numpy as np +from earth2studio.data import Random, fetch_data +from earth2studio.models.px import ModelName + +model = ModelName(...) + +# Create time array +time = np.array([np.datetime64("2024-01-01T00:00")]) + +# Fetch data using model's input coords +input_coords = model.input_coords() +input_coords["time"] = time +ds = Random(input_coords) +x, coords = fetch_data(ds, time, input_coords["variable"]) + +print(f"Fetched data shape: {x.shape}") +print(f"Variables: {input_coords['variable']}") +``` + +Report results to the user. This validates the coordinate system is compatible with the data pipeline. + +--- + +## Step 11 — Write Pytest Unit Tests + +Create `test/models/px/test_.py` following the existing test patterns. + +### Test file structure + +```python +# License header (same SPDX Apache-2.0 header as above) + +import gc +from collections import OrderedDict +from collections.abc import Iterable + +import numpy as np +import pytest +import torch + +from earth2studio.data import Random, fetch_data +from earth2studio.models.auto import Package +from earth2studio.models.px import ModelName +from earth2studio.utils import handshake_dim + + +class PhooModelName(torch.nn.Module): + """Dummy model that performs a simple deterministic operation.""" + + def __init__(self): + super().__init__() + + def forward(self, x): + return x + 1 # Simple deterministic operation for testing + + +@pytest.fixture(scope="class") +def test_package(tmp_path_factory): + """Create a dummy model package for testing.""" + tmp_path = tmp_path_factory.mktemp("data") + # Export dummy model to checkpoint format + model = PhooModelName() + torch.save(model, tmp_path / "model.pt") + return Package(str(tmp_path)) + + +class TestModelNameMock: + @pytest.mark.parametrize( + "time", + [ + np.array([ + np.datetime64("1999-10-11T12:00"), + np.datetime64("2001-06-04T00:00"), + ]), + ], + ) + @pytest.mark.parametrize( + "device", + [ + "cpu", + pytest.param( + "cuda:0", + marks=pytest.mark.skipif( + not torch.cuda.is_available(), reason="No GPU" + ), + ), + ], + ) + def test_model_call(self, test_package, time, device): + """Test single forward pass.""" + model = ModelName.load_model(test_package) + model = model.to(device) + + # Fetch input data + dc = model.input_coords() + dc["time"] = time + ds = Random(dc) + x, coords = fetch_data(ds, time, dc["variable"], device=device) + + # Run forward + out, out_coords = model(x, coords) + + # Validate output + assert out.shape == x.shape + assert isinstance(out_coords, OrderedDict) + handshake_dim(out_coords, "variable", 3) + # Additional model-specific assertions + + @pytest.mark.parametrize("ensemble", [1, 2]) + @pytest.mark.parametrize( + "device", + [ + "cpu", + pytest.param( + "cuda:0", + marks=pytest.mark.skipif( + not torch.cuda.is_available(), reason="No GPU" + ), + ), + ], + ) + def test_model_iter(self, test_package, ensemble, device): + """Test iterator produces correct sequence.""" + model = ModelName.load_model(test_package) + model = model.to(device) + + # Create input + time = np.array([np.datetime64("2024-01-01T00:00")]) + dc = model.input_coords() + dc["time"] = time + ds = Random(dc) + x, coords = fetch_data(ds, time, dc["variable"], device=device) + + # Add ensemble dim + x = x.unsqueeze(0).repeat(ensemble, *([1] * x.ndim)) + coords["ensemble"] = np.arange(ensemble) + coords.move_to_end("ensemble", last=False) + + # Test iterator + iterator = model.create_iterator(x, coords) + assert isinstance(iterator, Iterable) + + # Skip initial condition + next(iterator) + + for i, (step_x, step_coords) in enumerate(iterator): + assert step_x.shape[0] == ensemble + if i >= 4: + break + + del model + gc.collect() + if device != "cpu": + torch.cuda.empty_cache() + + @pytest.mark.parametrize( + "coords", + [ + OrderedDict({ + "batch": np.empty(0), + "time": np.empty(0), + "lead_time": np.array([np.timedelta64(0, "h")]), + "variable": np.array(["wrong_var"]), + "lat": np.linspace(90, -90, 10), + "lon": np.linspace(0, 360, 20), + }), + ], + ) + def test_model_exceptions(self, test_package, coords): + """Test model raises on invalid coordinates.""" + model = ModelName.load_model(test_package) + x = torch.randn( + 1, 1, 1, + len(coords["variable"]), + len(coords["lat"]), + len(coords["lon"]), + ) + with pytest.raises((KeyError, ValueError)): + model(x, coords) + + +@pytest.mark.package +def test_model_package(): + """Integration test with real model weights.""" + model = ModelName.from_pretrained() + input_coords = model.input_coords() + time = np.array([np.datetime64("2024-01-01T00:00")]) + input_coords["time"] = time + ds = Random(input_coords) + x, coords = fetch_data(ds, time, input_coords["variable"]) + model = model.to("cuda" if torch.cuda.is_available() else "cpu") + x = x.to(model.device_buffer.device) + out, out_coords = model(x, coords) + assert out.shape == x.shape +``` + +Adapt the dummy model (`PhooModelName`) to match the +actual model's input/output interface so the wrapper's +reshaping logic is exercised. + +--- + +## Step 12 — Provide Side-by-Side Comparison Scripts + +Present two scripts to the user: + +### Reference script (without Earth2Studio) + +Reconstruct a minimal inference script based on the original reference code: + +```python +# Reference inference (no Earth2Studio) +import torch +# ... original model imports ... + +# Load model +model = OriginalModel.from_pretrained("path/to/checkpoint") +model.eval().cuda() + +# Prepare input +input_data = ... # Load/prepare input data per original repo instructions + +# Run inference +with torch.no_grad(): + output = model(input_data) + +print(f"Output shape: {output.shape}") +``` + +### Earth2Studio equivalent + +```python +# Earth2Studio inference +import torch +import numpy as np +from earth2studio.models.px import ModelName +from earth2studio.data import Random, fetch_data # or GFS, ERA5, etc. + +# Load model +model = ModelName.from_pretrained() +model = model.to("cuda") + +# Prepare input via Earth2Studio data pipeline +time = np.array([np.datetime64("2024-01-01T00:00")]) +input_coords = model.input_coords() +input_coords["time"] = time +ds = Random(input_coords) # Replace with real data source +x, coords = fetch_data(ds, time, input_coords["variable"], device="cuda") + +# Single step +with torch.no_grad(): + output, out_coords = model(x, coords) + +print(f"Output shape: {output.shape}") +print(f"Lead time: {out_coords['lead_time']}") + +# Multi-step forecast +iterator = model.create_iterator(x, coords) +for i, (step_x, step_coords) in enumerate(iterator): + print(f"Step {i}: lead_time={step_coords['lead_time']}") + if i >= 10: + break +``` + +### **[CONFIRM — Comparison Scripts]** + +Ask the user to compare the two scripts and verify the +Earth2Studio version is functionally equivalent to the +reference. + +--- + +## Reminders + +- **DO NOT** make a general base class with intent to reuse the wrapper across models +- **DO NOT** over-populate the `load_model()` API — only expose essential parameters +- **DO** add the model to `docs/modules/models.rst` + in the `earth2studio.models.px` section + (alphabetical order) +- **DO** use `loguru.logger` for logging, never `print()`, inside `earth2studio/` +- **DO** ensure all public functions have full type hints +- **DO** run formatting (`make format`) and linting (`make lint`) before finalizing From f24cbfff9780cb295ad00ccc5f974c31c16899cd Mon Sep 17 00:00:00 2001 From: Nicholas Geneva Date: Thu, 26 Mar 2026 00:23:15 +0000 Subject: [PATCH 02/20] Adding gencast mini --- .../skills/create-prognostic-wrapper/SKILL.md | 162 ++- CHANGELOG.md | 4 +- docs/modules/models_px.rst | 1 + earth2studio/lexicon/base.py | 1 + earth2studio/models/px/__init__.py | 8 +- earth2studio/models/px/gencast_mini.py | 1034 +++++++++++++++++ pyproject.toml | 9 +- test/models/px/test_gencast_mini.py | 371 ++++++ uv.lock | 14 +- 9 files changed, 1573 insertions(+), 31 deletions(-) create mode 100644 earth2studio/models/px/gencast_mini.py create mode 100644 test/models/px/test_gencast_mini.py diff --git a/.claude/skills/create-prognostic-wrapper/SKILL.md b/.claude/skills/create-prognostic-wrapper/SKILL.md index 6f1fca9b5..a3a90bfc1 100644 --- a/.claude/skills/create-prognostic-wrapper/SKILL.md +++ b/.claude/skills/create-prognostic-wrapper/SKILL.md @@ -7,7 +7,13 @@ argument-hint: URL or local path to reference inference script/repo (optional # Create Prognostic Model Wrapper Create a new Earth2Studio prognostic model wrapper by following every step below in order. -Each confirmation gate marked **[CONFIRM]** requires explicit user approval before proceeding. +Each confirmation gate marked by starting with: + +```markdown +### **[CONFIRM — ]** +``` + +requires explicit user approval before proceeding. --- @@ -118,7 +124,30 @@ implementations. Every `.py` file in `earth2studio/` # limitations under the License. ``` -The skeleton must use **triple inheritance** and follow this exact structure: +The skeleton must use **triple inheritance** and follow this exact structure. + +**Method ordering** — methods in the class must appear in +this canonical order: + +1. `__init__` — constructor +2. `input_coords` — input coordinate system +3. `output_coords` — output coordinate system (decorated + `@batch_coords()`) +4. `load_default_package` — classmethod returning default + `Package` +5. `load_model` — classmethod loading model from package +6. `to` — device management (optional for pure + `torch.nn.Module` wrappers where `super().to()` is + sufficient; only needed for ONNX, JAX, or other + non-PyTorch state) +7. Any private/support methods (e.g., helper functions for + data conversion, JAX setup, normalization, etc.) +8. `__call__` — single-step forward (decorated + `@batch_func()`) +9. `_default_generator` — batch-decorated generator used + by `create_iterator` (decorated `@batch_func()`) +10. `create_iterator` — public time-integration entry point + that delegates to `_default_generator` ```python from collections import OrderedDict @@ -150,7 +179,8 @@ VARIABLES = [...] # List of variable names from E2STUDIO_VOCAB class ModelName(torch.nn.Module, AutoModelMixin, PrognosticMixin): """One-line description. - Extended description of the model, its source, and any relevant details. + Extended description of the model, its source, + and any relevant details. Parameters ---------- @@ -163,48 +193,81 @@ class ModelName(torch.nn.Module, AutoModelMixin, PrognosticMixin): For more information see: <link to paper/repo> """ + # 1. Constructor def __init__(self, core_model, ...): super().__init__() # TODO: Initialize model - self.register_buffer("device_buffer", torch.empty(0)) + self.register_buffer( + "device_buffer", torch.empty(0) + ) pass + # 2. Input coordinates def input_coords(self) -> CoordSystem: # TODO: Define input coordinates pass + # 3. Output coordinates @batch_coords() - def output_coords(self, input_coords: CoordSystem) -> CoordSystem: + def output_coords( + self, input_coords: CoordSystem, + ) -> CoordSystem: # TODO: Define output coordinates pass + # 4. Default package location + @classmethod + def load_default_package(cls) -> Package: + # TODO: Default checkpoint location + pass + + # 5. Load model from package + @classmethod + @check_optional_dependencies() + def load_model( + cls, package: Package, + ) -> PrognosticModel: + # TODO: Load model from package + pass + + # 6. Device management (optional — see note below) + def to( + self, device: torch.device | str, + ) -> PrognosticModel: + # TODO: Device management + pass + + # 7. Private/support methods go here + # e.g., _load_checkpoint(), _prepare_input(), etc. + + # 8. Single step forward @batch_func() - def __call__(self, x: torch.Tensor, coords: CoordSystem) -> tuple[torch.Tensor, CoordSystem]: + def __call__( + self, + x: torch.Tensor, + coords: CoordSystem, + ) -> tuple[torch.Tensor, CoordSystem]: # TODO: Single step forward pass + # 9. Batch-decorated generator @batch_func() - def create_iterator( + def _default_generator( self, x: torch.Tensor, coords: CoordSystem, ) -> Iterator[tuple[torch.Tensor, CoordSystem]]: - # TODO: Time integration iterator + # TODO: Yield initial condition, then loop pass - def to(self, device: torch.device | str) -> PrognosticModel: - # TODO: Device management - pass - - @classmethod - def load_default_package(cls) -> Package: - # TODO: Default checkpoint location - pass - - @classmethod - @check_optional_dependencies() - def load_model(cls, package: Package) -> PrognosticModel: - # TODO: Load model from package + # 10. Public iterator entry point + def create_iterator( + self, + x: torch.Tensor, + coords: CoordSystem, + ) -> Iterator[tuple[torch.Tensor, CoordSystem]]: + # TODO: Setup, then yield from + # self._default_generator(x, coords) pass ``` @@ -511,6 +574,15 @@ def load_model( ### 6c. Implement .to() +> **Note:** When the wrapper inherits from `torch.nn.Module`, +> `super().to(device)` already handles moving all registered +> parameters, buffers, and sub-modules. A custom `to()` +> override is only needed when there is non-PyTorch state to +> manage (e.g., ONNX Runtime sessions that must be destroyed +> and recreated on a new device, or JAX device placement). +> If `super().to(device)` is sufficient, you can omit the +> override entirely. + ```python def to(self, device: torch.device | str) -> PrognosticModel: """Move model to device. @@ -861,6 +933,54 @@ reshaping logic is exercised. --- +## Step 11b — Run Tests + +### 11b-i. Run mock tests (no package flag) + +First, run the unit tests that use mocked / dummy models. +These do **not** require downloading real checkpoints and +should run quickly on any machine: + +```bash +uv run python -m pytest test/models/px/test_<filename>.py \ + -m "not package" -v +``` + +All mock tests must pass before proceeding. Fix any +failures and re-run until green. + +### 11b-ii. Run the package integration test + +Once the mock tests pass, run the `@pytest.mark.package` +test which exercises `from_pretrained()` with real model +weights: + +```bash +uv run python -m pytest test/models/px/test_<filename>.py \ + -m "package" -v +``` + +### **[CONFIRM — Package Test]** + +Before executing the package test, warn the user: + +> The package / integration test will: +> +> - **Download the model checkpoint** (may be several GB) +> to the local cache +> - **Require GPU compute** for models that need CUDA +> (the test will skip on CPU-only machines if +> `torch.cuda.is_available()` is `False`) +> - Take significantly longer than the mock tests +> +> Do you want to proceed with the package test? + +Only run the package test after the user confirms. Report +the results back to the user. If the package test fails, +debug and fix the wrapper or test, then re-run. + +--- + ## Step 12 — Provide Side-by-Side Comparison Scripts Present two scripts to the user: diff --git a/CHANGELOG.md b/CHANGELOG.md index f8e03f0ee..9468241d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.14.0a0] - xxxx-xx-xx +## [0.14.0a0] - 2026-04-xx ### Added +- Added GenCast 1 degree Mini model + ### Changed ### Deprecated diff --git a/docs/modules/models_px.rst b/docs/modules/models_px.rst index 1dae3d78d..1def4736c 100644 --- a/docs/modules/models_px.rst +++ b/docs/modules/models_px.rst @@ -47,6 +47,7 @@ Thus are typically used to generate forecast predictions. FCN3 FengWu FuXi + GenCastMini GraphCastOperational GraphCastSmall InterpModAFNO diff --git a/earth2studio/lexicon/base.py b/earth2studio/lexicon/base.py index f118a78cf..88f5fdac2 100644 --- a/earth2studio/lexicon/base.py +++ b/earth2studio/lexicon/base.py @@ -58,6 +58,7 @@ def __contains__(cls, val: object) -> bool: "tpp": "total precipitation probability", "tpi": "total precipitation index", "tp06": "total precipitation accumulated over past 6 hours (m)", + "tp12": "total precipitation accumulated over past 12 hours (m)", "cp06": "convective precipitation accumulated over past 6 hours (m)", "tpf": "total precipitation flux (kg m-2 s-1)", "tcc": "total cloud cover (0 - 1)", diff --git a/earth2studio/models/px/__init__.py b/earth2studio/models/px/__init__.py index 97e6f4ca4..91db0eba6 100644 --- a/earth2studio/models/px/__init__.py +++ b/earth2studio/models/px/__init__.py @@ -30,6 +30,7 @@ from earth2studio.models.px.fcn3 import FCN3 from earth2studio.models.px.fengwu import FengWu from earth2studio.models.px.fuxi import FuXi +from earth2studio.models.px.gencast_mini import GenCastMini from earth2studio.models.px.graphcast_operational import GraphCastOperational from earth2studio.models.px.graphcast_small import GraphCastSmall from earth2studio.models.px.interpmodafno import InterpModAFNO @@ -38,10 +39,3 @@ from earth2studio.models.px.sfno import SFNO from earth2studio.models.px.stormcast import StormCast from earth2studio.models.px.stormscope import StormScopeGOES, StormScopeMRMS - -# TODO: Remove upon physics-nemo update... -# package turned on logging of warnings in 1.1.0, this is silencing them -warnings.filterwarnings("ignore") -warnings.filterwarnings("ignore", category=SyntaxWarning) -warnings.filterwarnings("ignore", category=DeprecationWarning) -warnings.filterwarnings("ignore", category=FutureWarning) diff --git a/earth2studio/models/px/gencast_mini.py b/earth2studio/models/px/gencast_mini.py new file mode 100644 index 000000000..a8e35418c --- /dev/null +++ b/earth2studio/models/px/gencast_mini.py @@ -0,0 +1,1034 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import dataclasses +import functools +from collections import OrderedDict +from collections.abc import Callable, Generator, Iterator +from typing import Any + +import numpy as np +import torch +import xarray as xr + +from earth2studio.lexicon.wb2 import WB2Lexicon +from earth2studio.models.auto import AutoModelMixin, Package +from earth2studio.models.batch import batch_coords, batch_func +from earth2studio.models.px.base import PrognosticModel +from earth2studio.models.px.utils import PrognosticMixin +from earth2studio.utils import handshake_coords +from earth2studio.utils.coords import map_coords +from earth2studio.utils.imports import ( + OptionalDependencyFailure, + check_optional_dependencies, +) +from earth2studio.utils.type import CoordSystem + +try: + import chex + import haiku as hk + import jax + import jax.numpy as jnp + from graphcast import ( + checkpoint, + data_utils, + gencast, + graphcast, + nan_cleaning, + normalization, + rollout, + xarray_jax, + ) +except ImportError: + OptionalDependencyFailure("gencast") + hk = None + jax = None + jnp = None + chex = None + checkpoint = None + data_utils = None + gencast = None + graphcast = None + nan_cleaning = None + normalization = None + rollout = None + xarray_jax = None + +# Input variables: 5 surface + 6x13 atmospheric (no precipitation in inputs) +INPUT_SURFACE_VARIABLES = [ + "t2m", + "msl", + "u10m", + "v10m", + "sst", +] + +# Output adds tp12 to surface variables +OUTPUT_SURFACE_VARIABLES = [ + "t2m", + "msl", + "u10m", + "v10m", + "sst", + "tp12", +] + +ATMOS_VARIABLES = [ + "t", + "z", + "u", + "v", + "w", + "q", +] + +PRESSURE_LEVELS = [50, 100, 150, 200, 250, 300, 400, 500, 600, 700, 850, 925, 1000] + +# Build full variable lists: surface + atmospheric (var + level) +INPUT_VARIABLES = INPUT_SURFACE_VARIABLES + [ + f"{var}{level}" for var in ATMOS_VARIABLES for level in PRESSURE_LEVELS +] + +OUTPUT_VARIABLES = OUTPUT_SURFACE_VARIABLES + [ + f"{var}{level}" for var in ATMOS_VARIABLES for level in PRESSURE_LEVELS +] + +# Forcing variables (GenCast does NOT use toa_incident_solar_radiation) +GENERATED_FORCING_VARS = ( + "year_progress_sin", + "year_progress_cos", + "day_progress_sin", + "day_progress_cos", +) + +INV_VOCAB = {v: k for k, v in WB2Lexicon.VOCAB.items()} + + +@check_optional_dependencies() +class GenCastMini(torch.nn.Module, AutoModelMixin, PrognosticMixin): + """GenCast Mini diffusion-based weather prediction model. + + A stochastic weather prediction model based on conditional diffusion that predicts + in 12-hour time steps. GenCast uses a denoiser architecture with a Sparse + Transformer processor and DPM-Solver++ 2S sampling. This mini variant operates at + 1.0-degree (181x360) resolution with 13 pressure levels. + + Unlike deterministic models such as GraphCast, GenCast produces stochastic + predictions (different random seeds yield different ensemble members). The model + takes 2 input frames (t-12h and t) and predicts 12 hours ahead. + + This is the mini variant trained on ERA5 reanalysis data (pre-2019), offering + significantly lower memory requirements (~16 GB vRAM) compared to the full + 0.25-degree operational model. This wrapper runs the model with operational inputs + which includes a zero 12hr total precipitation input. + + Note + ---- + This model and checkpoint are based on the GenCast architecture from DeepMind. + For more information see the following references: + + - https://arxiv.org/abs/2312.15796 + - https://github.com/google-deepmind/graphcast + - https://www.nature.com/articles/s41586-024-08252-9 + + Warning + ------- + We encourage users to familiarize themselves with the license restrictions of this + model's checkpoints. + + Parameters + ---------- + ckpt : gencast.CheckPoint + Model checkpoint containing weights and configuration + diffs_stddev_by_level : xr.Dataset + Standard deviation of differences by level for normalization + mean_by_level : xr.Dataset + Mean values by level for normalization + stddev_by_level : xr.Dataset + Standard deviation by level for normalization + min_by_level : xr.Dataset + Minimum values by level for NaN cleaning + land_sea_mask : np.ndarray + Land-sea mask on lat-lon grid + geopotential_at_surface : np.ndarray + Geopotential at surface on lat-lon grid + sst_nan_mask : np.ndarray + Boolean mask indicating where SST values are NaN (ocean vs land) + seed : int, optional + Random seed for JAX PRNG key used in stochastic sampling, by default 0 + + Badges + ------ + region:global class:mrf product:wind product:precip product:temp product:atmos + year:2024 gpu:40gb + """ + + def __init__( + self, + ckpt: "gencast.CheckPoint", + diffs_stddev_by_level: xr.Dataset, + mean_by_level: xr.Dataset, + stddev_by_level: xr.Dataset, + min_by_level: xr.Dataset, + land_sea_mask: np.ndarray, + geopotential_at_surface: np.ndarray, + sst_nan_mask: np.ndarray, + seed: int = 0, + ): + super().__init__() + + self.ckpt = ckpt + self.diffs_stddev_by_level = diffs_stddev_by_level + self.mean_by_level = mean_by_level + self.stddev_by_level = stddev_by_level + self.min_by_level = min_by_level + self.land_sea_mask = land_sea_mask + self.geopotential_at_surface = geopotential_at_surface + self.sst_nan_mask = sst_nan_mask + self.prng_key = jax.random.PRNGKey(seed) + + self.run_forward = self._load_run_forward_from_checkpoint() + + n_lat = land_sea_mask.shape[0] + n_lon = land_sea_mask.shape[1] + + self._input_coords = OrderedDict( + { + "batch": np.empty(0), + "time": np.empty(0), + "lead_time": np.array( + [ + np.timedelta64(-12, "h"), + np.timedelta64(0, "h"), + ] + ), + "variable": np.array(INPUT_VARIABLES), + "lat": np.linspace(90, -90, n_lat, endpoint=True), + "lon": np.linspace(0, 360, n_lon, endpoint=False), + } + ) + + self._output_coords = OrderedDict( + { + "batch": np.empty(0), + "time": np.empty(0), + "lead_time": np.array([np.timedelta64(12, "h")]), + "variable": np.array(OUTPUT_VARIABLES), + "lat": np.linspace(90, -90, n_lat, endpoint=True), + "lon": np.linspace(0, 360, n_lon, endpoint=False), + } + ) + + self.register_buffer("device_buffer", torch.empty(0)) + + def input_coords(self) -> CoordSystem: + """Input coordinate system of the prognostic model. + + Returns + ------- + CoordSystem + Coordinate system dictionary + """ + return self._input_coords.copy() + + @batch_coords() + def output_coords( + self, + input_coords: CoordSystem, + ) -> CoordSystem: + """Output coordinate system of the prognostic model. + + Parameters + ---------- + input_coords : CoordSystem + Input coordinate system to transform into output_coords + + Returns + ------- + CoordSystem + Coordinate system dictionary + """ + output_coords = self._output_coords.copy() + + output_coords["batch"] = input_coords["batch"] + output_coords["time"] = input_coords["time"] + + output_coords["lead_time"] = ( + input_coords["lead_time"][-1] + output_coords["lead_time"] + ) + + return output_coords + + @classmethod + def load_default_package(cls) -> Package: + """Load default pre-trained GenCast Mini model package from Google Cloud. + + Returns + ------- + Package + Model package + """ + return Package( + "gs://dm_graphcast/gencast", + cache_options={ + "cache_storage": Package.default_cache("gencast"), + "same_names": True, + }, + ) + + @classmethod + @check_optional_dependencies() + def load_model( + cls, + package: Package, + ) -> PrognosticModel: + """Load prognostic model from package. + + Parameters + ---------- + package : Package + Package to load model from + + Returns + ------- + PrognosticModel + Prognostic model + """ + # Load normalization stats + diffs_stddev_by_level = xr.load_dataset( + package.resolve("stats/diffs_stddev_by_level.nc") + ).compute() + mean_by_level = xr.load_dataset( + package.resolve("stats/mean_by_level.nc") + ).compute() + stddev_by_level = xr.load_dataset( + package.resolve("stats/stddev_by_level.nc") + ).compute() + min_by_level = xr.load_dataset( + package.resolve("stats/min_by_level.nc") + ).compute() + + # Load checkpoint + params_path = package.resolve("params/GenCast 1p0deg Mini <2019.npz") + with open(params_path, "rb") as f: + ckpt = checkpoint.load(f, gencast.CheckPoint) + + # Load static fields from sample dataset (same pattern as GraphCast) + sample_input = xr.load_dataset( + package.resolve( + "dataset/source-era5_date-2019-03-29_res-1.0_levels-13_steps-01.nc" + ) + ) + land_sea_mask = sample_input["land_sea_mask"].values + geopotential_at_surface = sample_input["geopotential_at_surface"].values + # SST NaN mask: True where ocean (valid SST), False where land (NaN) + sst_nan_mask = ~np.isnan(sample_input["sea_surface_temperature"].values[0, 0]) + + return cls( + ckpt, + diffs_stddev_by_level, + mean_by_level, + stddev_by_level, + min_by_level, + land_sea_mask, + geopotential_at_surface, + sst_nan_mask, + ) + + # ------------------------------------------------------------------------- + # Private / support methods + # ------------------------------------------------------------------------- + + def _load_run_forward_from_checkpoint(self) -> Callable: + """Build GenCast inference function from checkpoint. + + This function is based on the inference pipeline from: + https://github.com/google-deepmind/graphcast + + License info: + + # Copyright 2023 DeepMind Technologies Limited. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS-IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + Returns + ------- + Callable + Function that takes (rng, inputs, targets_template, forcings) + """ + state: dict = {} + params = self.ckpt.params + task_config = self.ckpt.task_config + sampler_config = self.ckpt.sampler_config + noise_config = self.ckpt.noise_config + noise_encoder_config = self.ckpt.noise_encoder_config + + # Replace SplashAttention with TriBlockDiag for GPU compatibility + splash_spt_cfg = ( + self.ckpt.denoiser_architecture_config.sparse_transformer_config + ) + tbd_spt_cfg = dataclasses.replace( + splash_spt_cfg, attention_type="triblockdiag_mha", mask_type="full" + ) + denoiser_architecture_config = dataclasses.replace( + self.ckpt.denoiser_architecture_config, + sparse_transformer_config=tbd_spt_cfg, + ) + + # Monkey-patch xarray_jax to handle JAX tracers inside jax.lax.fori_loop. + # GenCast's diffusion sampler (DPM-Solver++2S) uses fori_loop which + # turns loop variables into DynamicJaxprTracer. The upstream + # JaxArrayWrapper.__array_ufunc__ rejects these tracers because + # DynamicJaxprTracer is not jax.typing.ArrayLike. + # This is an upstream bug: https://github.com/google-deepmind/graphcast/issues/203 + # We intercept NotImplemented and fall back to the JAX operation directly. + _original_array_ufunc = xarray_jax.JaxArrayWrapper.__array_ufunc__ + + # Map numpy ufuncs to their JAX equivalents so we can operate + # on JAX tracers without triggering numpy's __array__ conversion. + _UFUNC_TO_JAX: dict[np.ufunc, Any] = { + np.multiply: jnp.multiply, + np.add: jnp.add, + np.subtract: jnp.subtract, + np.divide: jnp.divide, + np.true_divide: jnp.true_divide, + np.negative: jnp.negative, + np.sqrt: jnp.sqrt, + np.square: jnp.square, + np.abs: jnp.abs, + np.log: jnp.log, + np.exp: jnp.exp, + np.power: jnp.power, + np.maximum: jnp.maximum, + np.minimum: jnp.minimum, + } + + def _patched_array_ufunc( + self: "xarray_jax.JaxArrayWrapper", + ufunc: np.ufunc, + method: str, + *inputs: Any, + **kwargs: Any, + ) -> Any: + result = _original_array_ufunc(self, ufunc, method, *inputs, **kwargs) + if result is NotImplemented: + jax_fn = _UFUNC_TO_JAX.get(ufunc) + if jax_fn is None: + return NotImplemented + jax_inputs = [ + i.jax_array if isinstance(i, xarray_jax.JaxArrayWrapper) else i + for i in inputs + ] + return xarray_jax.JaxArrayWrapper(jax_fn(*jax_inputs, **kwargs)) + return result + + xarray_jax.JaxArrayWrapper.__array_ufunc__ = _patched_array_ufunc + + def construct_wrapped_gencast( + task_config: "graphcast.TaskConfig", + denoiser_architecture_config: "gencast.DenoiserArchitectureConfig", + sampler_config: "gencast.SamplerConfig", + noise_config: "gencast.NoiseConfig", + noise_encoder_config: "gencast.NoiseEncoderConfig", + ) -> "gencast.GenCast": + """Construct GenCast predictor with normalization and NaN cleaning.""" + predictor = gencast.GenCast( + task_config=task_config, + denoiser_architecture_config=denoiser_architecture_config, + sampler_config=sampler_config, + noise_config=noise_config, + noise_encoder_config=noise_encoder_config, + ) + + predictor = normalization.InputsAndResiduals( + predictor, + diffs_stddev_by_level=self.diffs_stddev_by_level, + mean_by_level=self.mean_by_level, + stddev_by_level=self.stddev_by_level, + ) + + predictor = nan_cleaning.NaNCleaner( + predictor=predictor, + reintroduce_nans=True, + fill_value=self.min_by_level, + var_to_clean="sea_surface_temperature", + ) + + return predictor + + @hk.transform_with_state + def run_forward( + task_config: "graphcast.TaskConfig", + denoiser_architecture_config: "gencast.DenoiserArchitectureConfig", + sampler_config: "gencast.SamplerConfig", + noise_config: "gencast.NoiseConfig", + noise_encoder_config: "gencast.NoiseEncoderConfig", + inputs: xr.Dataset, + targets_template: xr.Dataset, + forcings: xr.Dataset, + ) -> xr.Dataset: + predictor = construct_wrapped_gencast( + task_config, + denoiser_architecture_config, + sampler_config, + noise_config, + noise_encoder_config, + ) + return predictor( + inputs, targets_template=targets_template, forcings=forcings + ) + + def with_configs(fn: Callable) -> Callable: + return functools.partial( + fn, + task_config=task_config, + denoiser_architecture_config=denoiser_architecture_config, + sampler_config=sampler_config, + noise_config=noise_config, + noise_encoder_config=noise_encoder_config, + ) + + def with_params(fn: Callable) -> Callable: + return functools.partial(fn, params=params, state=state) + + def drop_state(fn: Callable) -> Callable: + return lambda **kw: fn(**kw)[0] + + return drop_state(with_params(with_configs(run_forward.apply))) + + def _chunked_prediction_generator( + self, + predictor_fn: Callable, + rng: "chex.PRNGKey", + inputs: xr.Dataset, + targets_template: xr.Dataset, + forcings: xr.Dataset, + ) -> Generator[xr.Dataset, None, None]: + """Autoregressive prediction generator for GenCast. + + This function is based on the rollout logic from: + https://github.com/google-deepmind/graphcast + + License info: + + # Copyright 2023 DeepMind Technologies Limited. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS-IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + Parameters + ---------- + predictor_fn : Callable + JIT-compiled GenCast forward function + rng : chex.PRNGKey + JAX PRNG key for stochastic sampling + inputs : xr.Dataset + Initial condition dataset (2 frames) + targets_template : xr.Dataset + Template for target predictions (NaN-filled) + forcings : xr.Dataset + Forcing variables dataset + + Yields + ------ + xr.Dataset + Prediction for each 12-hour time step + """ + inputs = xr.Dataset(inputs) + targets_template = xr.Dataset(targets_template) + forcings = xr.Dataset(forcings) + + targets_chunk_time = targets_template.time.isel(time=slice(0, 1)) + current_inputs = inputs + + def split_rng_fn( + rng: "chex.PRNGKey", + ) -> tuple["chex.PRNGKey", "chex.PRNGKey"]: + rng1, rng2 = jax.random.split(rng) + return rng1, rng2 + + index = 0 + while True: + # Update forcings time coordinate + forcings = forcings.assign_coords(time=targets_chunk_time) + forcings = forcings.compute() + + # Make prediction for this step + rng, this_rng = split_rng_fn(rng) + predictions = predictor_fn( + rng=this_rng, + inputs=current_inputs, + targets_template=targets_template, + forcings=forcings, + ) + next_frame = xr.merge([predictions, forcings]) + + # Update inputs for next step + next_inputs = rollout._get_next_inputs(current_inputs, next_frame) + next_inputs = next_inputs.assign_coords(time=current_inputs.coords["time"]) + current_inputs = next_inputs + + # Assign actual time coordinates to predictions + predictions = predictions.assign_coords( + time=targets_template.coords["time"] + index * np.timedelta64(12, "h") + ) + yield predictions + del predictions + + # Recompute forcings for next step + # GenCast only uses generated forcings (year/day progress) + # which are derived from datetime coordinates + datetime_offset = np.timedelta64((index + 1) * 12, "h") + current_datetime = current_inputs.coords.get( + "datetime", current_inputs.coords["time"] + ) + + # Build minimal batch for forcing computation + batch = current_inputs.copy() + # Ensure datetime has (batch, time) dims for add_derived_vars + new_datetime = current_datetime.values + datetime_offset + if new_datetime.ndim == 1 and "batch" in batch.dims: + new_datetime = np.expand_dims(new_datetime, axis=0) + batch = batch.assign_coords( + datetime=( + (("batch", "time"), new_datetime) + if "batch" in batch.dims + else current_datetime + datetime_offset + ) + ) + + # Drop old forcing vars if present + force_vars = list(GENERATED_FORCING_VARS) + [ + "year_progress", + "day_progress", + ] + for fvar in force_vars: + if fvar in batch: + batch = batch.drop_vars(fvar) + + # Recompute derived forcing variables + data_utils.add_derived_vars(batch) + batch = batch.compute() + + # Extract new forcings + forcings = batch.isel(time=slice(-1, None))[list(GENERATED_FORCING_VARS)] + forcings = forcings.reset_coords("datetime", drop=True) + forcings = forcings.compute() + + index += 1 + + def iterator_result_to_tensor(self, dataset: xr.Dataset) -> torch.Tensor: + """Convert an iterator result xarray Dataset to a torch Tensor. + + Parameters + ---------- + dataset : xr.Dataset + xarray Dataset from JAX GenCast prediction + + Returns + ------- + torch.Tensor + Output tensor with shape matching earth2studio conventions + """ + for var in list(dataset.data_vars): + if "level" in dataset[var].dims: + for level in dataset[var].level: + dataset[f"{var}::{level.values}"] = dataset[var].sel(level=level) + dataset = dataset.drop_vars(var) + else: + dataset = dataset.rename({var: f"{var}::"}) + dataset = dataset.drop_dims("level") + + if len(dataset.time) > 1: + # Coming from __call__ + dataset = dataset.rename({"time": "lead_time"}) + dataset = dataset.expand_dims(dim="time") + else: + dataset = dataset.expand_dims(dim="lead_time") + + if "ensemble" in dataset.dims: + dataset = dataset.squeeze("batch", drop=True) + + dataset = dataset.rename({key: INV_VOCAB[key] for key in dataset.data_vars}) + + if "batch" in dataset.dims: + dataarray = ( + dataset[self._output_coords["variable"]] + .to_dataarray() + .T.transpose( + ..., "batch", "time", "lead_time", "variable", "lat", "lon" + ) + ) + else: + dataarray = ( + dataset[self._output_coords["variable"]] + .to_dataarray() + .T.transpose(..., "time", "lead_time", "variable", "lat", "lon") + ) + + out = torch.from_numpy(dataarray.to_numpy().copy()) + # Flip lat from ascending (-90->90, JAX native) to (90->-90) + out = out.flip(-2) + return out + + @staticmethod + def get_jax_device_from_tensor(x: torch.Tensor) -> "jax.Device": + """From a tensor, get device and corresponding JAX device. + + Parameters + ---------- + x : torch.Tensor + Input tensor + + Returns + ------- + jax.Device + Corresponding JAX device + """ + device_id = x.get_device() + if device_id == -1: # -1 is CPU + device = jax.devices("cpu")[0] + else: + device = jax.devices("gpu")[device_id] + return device + + def from_dataarray_to_dataset( + self, data: xr.DataArray, lead_time: int = 12, hour_steps: int = 12 + ) -> tuple[xr.Dataset, list[str]]: + """Convert earth2studio DataArray to xarray Dataset for JAX model. + + Parameters + ---------- + data : xr.DataArray + Input data array from earth2studio + lead_time : int, optional + Forecast lead time in hours, by default 12 + hour_steps : int, optional + Time step size in hours, by default 12 + + Returns + ------- + tuple[xr.Dataset, list[str]] + xarray Dataset suitable for GenCast and list of target lead times + """ + if len(data.time.values) > 1: + raise TypeError("GenCast model only supports 1 init_time.") + + # Convert lead_time dim to absolute time + if "lead_time" in data.dims: + data["lead_time"] = [ + data.time.values[0] + level for level in data.lead_time.values + ] + data = data.isel(time=0).reset_coords("time", drop=True) + data = data.rename({"lead_time": "time"}) + + lead_times = range(hour_steps, lead_time + hour_steps, hour_steps) + target_lead_times = [f"{h}h" for h in lead_times] + time_deltas = np.concatenate( + ( + self._input_coords["lead_time"], + [np.timedelta64(h, "h") for h in lead_times], + ) + ) + + # 2nd date is center (t=0) + if len(data.time.values) == 1: + start_date = (data.time.values + data.lead_time.values)[1] + else: + start_date = data.time.values[1] + all_datetimes = [start_date + time_delta for time_delta in time_deltas] + + data = data.to_dataset(dim="variable") + data = data.rename({key: WB2Lexicon.VOCAB[key] for key in data.data_vars}) + out_data = xr.Dataset( + coords={ + "time": all_datetimes[0:2], + "lat": data.lat, + "lon": data.lon, + "level": PRESSURE_LEVELS, + } + ) + + # Reassemble pressure levels + pressure_level_vars: dict[str, list[xr.DataArray]] = {} + for var in data.data_vars: + arco_variable, level = var.split("::") + if level: + if arco_variable not in pressure_level_vars: + pressure_level_vars[arco_variable] = [ + data[var].expand_dims(dim=dict(level=[int(level)])) + ] + else: + pressure_level_vars[arco_variable] += [ + data[var].expand_dims(dim=dict(level=[int(level)])) + ] + else: + out_data[arco_variable] = data[var] + for var in pressure_level_vars: + out_data[var] = xr.concat(pressure_level_vars[var], dim="level") + + # Set up time coordinates for data_utils.extract_inputs_targets_forcings + out_data = out_data.assign_coords( + datetime=all_datetimes[: len(out_data.time.values)] + ) + out_data = out_data.assign_coords(time=time_deltas[: len(out_data.time.values)]) + out_data["datetime"] = out_data.datetime.expand_dims(dict(batch=1)) + + # Add batch dimension + for var in out_data.data_vars: + if "batch" not in out_data[var].dims: + out_data[var] = out_data[var].expand_dims(dict(batch=1)) + + # Pad times for target template + out_data = out_data.pad(pad_width=dict(time=(0, len(lead_times)))) + out_data = out_data.assign_coords( + coords=dict( + time=time_deltas, + datetime=(("batch", "time"), [all_datetimes]), + ) + ) + + # Reindex lat ascending (south-to-north) for JAX model + out_data = out_data.reindex(lat=sorted(out_data.lat.values)) + out_data = out_data.transpose("batch", "time", "level", "lat", "lon", ...) + + # Add zero tp12 (GenCast does not need precipitation in inputs) + shape = out_data["2m_temperature"].shape + dims = out_data["2m_temperature"].dims + tp_coords = {dim: out_data["2m_temperature"].coords[dim] for dim in dims} + out_data["total_precipitation_12hr"] = xr.DataArray( + np.zeros(shape, dtype=np.float32), dims=dims, coords=tp_coords + ) + + # Add static fields + out_data["land_sea_mask"] = xr.DataArray( + self.land_sea_mask, dims=("lat", "lon") + ) + out_data["geopotential_at_surface"] = xr.DataArray( + self.geopotential_at_surface, dims=("lat", "lon") + ) + + # Apply SST NaN mask + sst_mask_da = xr.DataArray( + self.sst_nan_mask, + dims=("lat", "lon"), + coords={"lat": out_data.lat, "lon": out_data.lon}, + ) + out_data["sea_surface_temperature"] = out_data["sea_surface_temperature"].where( + sst_mask_da + ) + + # Cast all to float32 + for var in out_data.data_vars: + out_data[var] = out_data[var].astype(np.float32) + + return out_data, target_lead_times + + # ------------------------------------------------------------------------- + # Forward pass and iteration + # ------------------------------------------------------------------------- + + @batch_func() + def __call__( + self, + x: torch.Tensor, + coords: CoordSystem, + ) -> tuple[torch.Tensor, CoordSystem]: + """Runs prognostic model 1 step. + + Parameters + ---------- + x : torch.Tensor + Input tensor + coords : CoordSystem + Input coordinate system + + Returns + ------- + tuple[torch.Tensor, CoordSystem] + Output tensor and coordinate system 12 hours in the future + """ + device = x.device + + with jax.default_device(self.get_jax_device_from_tensor(x)): + x, coords = map_coords(x, coords, self.input_coords()) + + # Validate spatial dimensions match expected grid + target_input_coords = self.input_coords() + handshake_coords(coords, target_input_coords, "lat") + handshake_coords(coords, target_input_coords, "lon") + + time_dim = list(coords.keys()).index("time") + n_times = len(coords["time"]) + results = [] + for t in range(n_times): + x_t = x.narrow(time_dim, t, 1) + coords_t = coords.copy() + coords_t["time"] = coords["time"][t : t + 1] + + data, target_lead_times = self.from_dataarray_to_dataset( + xr.DataArray(x_t.cpu(), coords=coords_t), 12 + ) + + inputs, targets, forcings = data_utils.extract_inputs_targets_forcings( + data, + target_lead_times=target_lead_times, + **dataclasses.asdict(self.ckpt.task_config), + ) + + predictions = rollout.chunked_prediction( + self.run_forward, + rng=self.prng_key, + inputs=inputs, + targets_template=targets * np.nan, + forcings=forcings, + ) + results.append(self.iterator_result_to_tensor(predictions)) + + out = torch.cat(results, dim=1) if n_times > 1 else results[0] + output_coords = self.output_coords(coords) + + out = out.to(device) + + return out, output_coords + + @batch_func() + def _default_generator( + self, + x: torch.Tensor, + coords: CoordSystem, + ) -> Generator[tuple[torch.Tensor, CoordSystem]]: + """Default generator for time-stepping through iterator results. + + Parameters + ---------- + x : torch.Tensor + Input tensor + coords : CoordSystem + Input coordinate system + + Yields + ------ + tuple[torch.Tensor, CoordSystem] + Output tensor and coordinate system at each time step + """ + coords = coords.copy() + coords_out = self.output_coords(coords) + + device = x.device + + # First yield: return last input frame with zeros for tp12 + coords_out["lead_time"] = coords["lead_time"][1:] + # x shape: (batch, time, lead_time=2, n_input_vars, lat, lon) + # Take last lead_time frame for input vars, add zero tp12 column + out_input = x[:, :, 1:, ...] # (batch, time, 1, n_input_vars, lat, lon) + + # Find SST index in input variables to insert tp12 after it + # Output order: t2m, msl, u10m, v10m, sst, tp12, then atmos + # Input order: t2m, msl, u10m, v10m, sst, then atmos + # Insert a zero slice at index 5 (after sst) for tp12 + tp12_zeros = torch.zeros_like(out_input[:, :, :, :1, ...]) + out = torch.cat( + (out_input[:, :, :, :5, ...], tp12_zeros, out_input[:, :, :, 5:, ...]), + dim=3, + ) + yield out, coords_out + + while True: + coords = self.output_coords(coords) + + # Get next prediction from all time iterators + results = [ + self.iterator_result_to_tensor(next(it)) for it in self.iterators + ] + x = torch.cat(results, dim=1) if len(results) > 1 else results[0] + + x, coords = self.rear_hook(x, coords) + + x = x.to(device) + + coords = coords.copy() + yield x, coords + + def create_iterator( + self, x: torch.Tensor, coords: CoordSystem + ) -> Iterator[tuple[torch.Tensor, CoordSystem]]: + """Creates a iterator which can be used to perform time-integration of the + prognostic model. Will return the initial condition first (0th step). + + Parameters + ---------- + x : torch.Tensor + Input tensor + coords : CoordSystem + Input coordinate system + + Yields + ------ + Iterator[tuple[torch.Tensor, CoordSystem]] + Iterator that generates time-steps of the prognostic model container the + output data tensor and coordinate system dictionary. + """ + with jax.default_device(self.get_jax_device_from_tensor(x)): + time_dim = list(coords.keys()).index("time") + n_times = len(coords["time"]) + self.iterators = [] + + for t in range(n_times): + x_t = x.narrow(time_dim, t, 1) + coords_t = coords.copy() + coords_t["time"] = coords["time"][t : t + 1] + + batch, target_lead_times = self.from_dataarray_to_dataset( + xr.DataArray(x_t.cpu(), coords=coords_t), 12 + ) + + inputs, targets, forcings = data_utils.extract_inputs_targets_forcings( + batch, + target_lead_times=target_lead_times, + **dataclasses.asdict(self.ckpt.task_config), + ) + + self.iterators.append( + self._chunked_prediction_generator( + predictor_fn=self.run_forward, + rng=self.prng_key, + inputs=inputs, + targets_template=targets * np.nan, + forcings=forcings, + ) + ) + + yield from self._default_generator(x, coords) diff --git a/pyproject.toml b/pyproject.toml index fe3f81f45..0a40fbadf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,6 +165,13 @@ fuxi = [ "onnxscript", "onnxruntime-gpu>=1.21.0", ] +gencast = [ + "graphcast", + "dm-haiku>=0.0.14", + "jax[cuda12]>=0.4.26", + "flax>=0.10.6", + "dm-tree>=0.1.9", +] graphcast = [ "graphcast", "dm-haiku>=0.0.14", @@ -251,7 +258,7 @@ da-stormcast = [ # All, must not have conflicts all = [ "earth2studio[data,perturbation,statistics,utils,serve]", - "earth2studio[aifs,aifsens,atlas,aurora,dlesym,dlwp,fcn,fcn3,fengwu,interp-modafno,pangu,stormcast,sfno,stormscope,graphcast]", + "earth2studio[aifs,aifsens,atlas,aurora,dlesym,dlwp,fcn,fcn3,fengwu,gencast,interp-modafno,pangu,stormcast,sfno,stormscope,graphcast]", "earth2studio[cbottle,climatenet,corrdiff,precip-afno,cyclone,precip-afno-v2,solarradiation-afno,windgust-afno]", "earth2studio[da-interp,da-stormcast,da-healda]", ] diff --git a/test/models/px/test_gencast_mini.py b/test/models/px/test_gencast_mini.py new file mode 100644 index 000000000..fad38fd68 --- /dev/null +++ b/test/models/px/test_gencast_mini.py @@ -0,0 +1,371 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from collections import OrderedDict +from collections.abc import Iterable +from unittest import mock + +import numpy as np +import pytest +import torch +import xarray as xr + +try: + from graphcast import denoiser, graphcast + from graphcast import gencast as gencast_module +except ImportError: + pytest.importorskip("graphcast") + +from earth2studio.data import Random, fetch_data +from earth2studio.models.px.gencast_mini import ( + ATMOS_VARIABLES, + GENERATED_FORCING_VARS, + INPUT_VARIABLES, + OUTPUT_VARIABLES, + PRESSURE_LEVELS, + GenCastMini, +) +from earth2studio.utils import handshake_dim + +# GenCast-specific variable lists (matching graphcast module names) +GENCAST_TARGET_SURFACE_VARS = ( + "2m_temperature", + "mean_sea_level_pressure", + "10m_u_component_of_wind", + "10m_v_component_of_wind", + "sea_surface_temperature", + "total_precipitation_12hr", +) + +GENCAST_TARGET_SURFACE_NO_PRECIP_VARS = ( + "2m_temperature", + "mean_sea_level_pressure", + "10m_u_component_of_wind", + "10m_v_component_of_wind", + "sea_surface_temperature", +) + +GENCAST_TARGET_ATMOS_VARS = ( + "temperature", + "geopotential", + "u_component_of_wind", + "v_component_of_wind", + "vertical_velocity", + "specific_humidity", +) + +GENCAST_STATIC_VARS = ("geopotential_at_surface", "land_sea_mask") + + +def mocked_chunked_prediction_generator( + predictor_fn, + rng, + inputs, + targets_template, + forcings, +): + yield targets_template.isel(time=[0]) + while True: + yield targets_template.isel(time=[0]) + + +def mocked_chunked_prediction( + predictor_fn, + rng, + inputs, + targets_template, + forcings, + num_steps_per_chunk=None, + verbose=None, +): + return targets_template + + +def _build_fake_ckpt(n_lat: int, n_lon: int): + """Build a fake GenCast checkpoint for testing.""" + # Use the GenCast TASK config from the graphcast module + task_config = graphcast.TaskConfig( + input_variables=( + GENCAST_TARGET_SURFACE_NO_PRECIP_VARS + + graphcast.TARGET_ATMOSPHERIC_VARS + + tuple(GENERATED_FORCING_VARS) + + GENCAST_STATIC_VARS + ), + target_variables=( + GENCAST_TARGET_SURFACE_VARS + graphcast.TARGET_ATMOSPHERIC_VARS + ), + forcing_variables=tuple(GENERATED_FORCING_VARS), + pressure_levels=graphcast.PRESSURE_LEVELS_WEATHERBENCH_13, + input_duration="24h", + ) + + # Build a minimal DenoiserArchitectureConfig + # SparseTransformerConfig and DenoiserArchitectureConfig live in the + # ``denoiser`` module, not ``gencast``. + sparse_transformer_config = denoiser.SparseTransformerConfig( + attention_k_hop=4, + d_model=512, + num_layers=2, + num_heads=4, + attention_type="triblockdiag_mha", + mask_type="full", + ) + denoiser_architecture_config = denoiser.DenoiserArchitectureConfig( + sparse_transformer_config=sparse_transformer_config, + mesh_size=4, + latent_size=512, + ) + + sampler_config = gencast_module.SamplerConfig() + noise_config = gencast_module.NoiseConfig() + noise_encoder_config = denoiser.NoiseEncoderConfig() + + class CKPT: + def __init__(self): + self.params = {} + self.task_config = task_config + self.denoiser_architecture_config = denoiser_architecture_config + self.sampler_config = sampler_config + self.noise_config = noise_config + self.noise_encoder_config = noise_encoder_config + self.description = "test" + self.license = "test" + + return CKPT() + + +def _build_fake_stats(n_levels: int = 13): + """Build fake normalization stats datasets.""" + pressure_levels = list(graphcast.PRESSURE_LEVELS_WEATHERBENCH_13) + + static_data = {} + for v in ( + GENCAST_TARGET_ATMOS_VARS + + GENCAST_TARGET_SURFACE_VARS + + tuple(GENERATED_FORCING_VARS) + ): + if v in GENCAST_TARGET_ATMOS_VARS: + static_data[v] = ("level", np.ones(n_levels, dtype=np.float32)) + else: + static_data[v] = np.float32(1.0) + + coords = {"level": pressure_levels} + diffs_stddev = xr.Dataset(static_data, coords=coords) + mean = xr.Dataset(static_data, coords=coords) + stddev = xr.Dataset(static_data, coords=coords) + min_vals = xr.Dataset(static_data, coords=coords) + + return diffs_stddev, mean, stddev, min_vals + + +# ===== 1.0-degree (181x360) tests ===== + + +@pytest.fixture +def mock_GenCastMini_model(): + n_lat, n_lon = 181, 360 + ckpt = _build_fake_ckpt(n_lat, n_lon) + diffs_stddev, mean, stddev, min_vals = _build_fake_stats() + + p = GenCastMini( + ckpt, + diffs_stddev, + mean, + stddev, + min_vals, + np.ones((n_lat, n_lon), dtype=np.float32), + np.ones((n_lat, n_lon), dtype=np.float32), + np.ones((n_lat, n_lon), dtype=bool), + ) + + # Mock the iterator to avoid needing real JAX inference + p._chunked_prediction_generator = mocked_chunked_prediction_generator + + return p + + +@pytest.mark.parametrize( + "time", + [ + np.array([np.datetime64("2010-01-01T00:00")]), + np.array( + [np.datetime64("2010-01-01T00:00"), np.datetime64("2010-01-02T00:00")] + ), + ], +) +@pytest.mark.parametrize("device", ["cpu", "cuda:0"]) +@mock.patch("graphcast.rollout.chunked_prediction", mocked_chunked_prediction) +def test_gencast_mini_call(time, device, mock_GenCastMini_model): + + p = mock_GenCastMini_model.to(device) + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + + # Initialize Data Source + r = Random(dc) + + # Get Data and convert to tensor, coords + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + out, out_coords = p(x, coords) + assert out.shape == torch.Size([len(time), 1, 84, 181, 360]) + assert (out_coords["variable"] == p.output_coords(coords)["variable"]).all() + assert (out_coords["time"] == time).all() + handshake_dim(out_coords, "lon", 4) + handshake_dim(out_coords, "lat", 3) + handshake_dim(out_coords, "variable", 2) + handshake_dim(out_coords, "lead_time", 1) + handshake_dim(out_coords, "time", 0) + + +@pytest.mark.parametrize( + "ensemble", + [1, 2], +) +@pytest.mark.parametrize("device", ["cpu", "cuda:0"]) +@mock.patch( + "graphcast.rollout.chunked_prediction_generator", + mocked_chunked_prediction_generator, +) +def test_gencast_mini_iter(ensemble, device, mock_GenCastMini_model): + time = np.array([np.datetime64("1993-04-05T00:00")]) + p = mock_GenCastMini_model.to(device) + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + # Initialize Data Source + r = Random(dc) + + # Get Data and convert to tensor, coords + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + # Add ensemble to front + x = x.unsqueeze(0).repeat(ensemble, 1, 1, 1, 1, 1) + coords.update({"ensemble": np.arange(ensemble)}) + coords.move_to_end("ensemble", last=False) + + p_iter = p.create_iterator(x, coords) + + if not isinstance(time, Iterable): + time = [time] + + # Get generator + input, input_coords = next(p_iter) # Skip first which should return the input + assert input_coords["lead_time"] == np.timedelta64(0, "h") + assert input.shape == torch.Size( + [ensemble, len(time), 1, 84, 181, 360] + ) # 84 output vars, tp12 included + assert len(input.shape) == 6 + for i, (out, out_coords) in enumerate(p_iter): + assert len(out.shape) == 6 + assert out.shape == torch.Size([ensemble, len(time), 1, 84, 181, 360]) + assert (out_coords["variable"] == p.output_coords(coords)["variable"]).all() + assert (out_coords["ensemble"] == np.arange(ensemble)).all() + assert (out_coords["time"] == time).all() + assert out_coords["lead_time"] == np.timedelta64(12 * (i + 1), "h") + + if i > 5: + break + + +@pytest.mark.parametrize( + "dc", + [ + OrderedDict({"lat": np.random.randn(180)}), + OrderedDict({"lat": np.random.randn(180), "phoo": np.random.randn(360)}), + ], +) +@pytest.mark.parametrize("device", ["cuda:0"]) +def test_gencast_mini_exceptions(dc, device, mock_GenCastMini_model): + time = np.array([np.datetime64("1993-04-05T00:00")]) + p = mock_GenCastMini_model.to(device) + # Initialize Data Source + r = Random(dc) + + # Get Data and convert to tensor, coords + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + with pytest.raises((KeyError, ValueError)): + p(x, coords) + + +def test_gencast_mini_variables(): + """Test that variable lists are consistent.""" + assert len(INPUT_VARIABLES) == 83 # 5 surface + 6*13 atmos + assert len(OUTPUT_VARIABLES) == 84 # 6 surface (with tp12) + 6*13 atmos + assert len(PRESSURE_LEVELS) == 13 + assert len(ATMOS_VARIABLES) == 6 + # tp12 is in output but not input + assert "tp12" not in INPUT_VARIABLES + assert "tp12" in OUTPUT_VARIABLES + + +@pytest.fixture(scope="function") +def model() -> GenCastMini: + package = GenCastMini.load_default_package() + p = GenCastMini.load_model(package) + return p + + +@pytest.mark.package +@pytest.mark.parametrize("device", ["cuda:0"]) +def test_gencast_mini_package(model, device): + torch.cuda.empty_cache() + time = np.array([np.datetime64("1993-04-05T00:00")]) + # Test the cached model package gencast mini + p = model.to(device) + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + # Initialize Data Source + r = Random(dc) + + # Get Data and convert to tensor, coords + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + # Check iter + p_iter = p.create_iterator(x, coords) + for i in range(3): + out, out_coords = next(p_iter) + + if not isinstance(time, Iterable): + time = [time] + + assert out.shape == torch.Size([len(time), 1, 84, 181, 360]) + assert (out_coords["variable"] == p.output_coords(coords)["variable"]).all() + assert (out_coords["time"] == time).all() + handshake_dim(out_coords, "lon", 4) + handshake_dim(out_coords, "lat", 3) + handshake_dim(out_coords, "variable", 2) + handshake_dim(out_coords, "lead_time", 1) + handshake_dim(out_coords, "time", 0) diff --git a/uv.lock b/uv.lock index 9f43a927b..67585fa8b 100644 --- a/uv.lock +++ b/uv.lock @@ -1787,6 +1787,13 @@ fuxi = [ { name = "onnxruntime-gpu" }, { name = "onnxscript" }, ] +gencast = [ + { name = "dm-haiku" }, + { name = "dm-tree" }, + { name = "flax" }, + { name = "graphcast" }, + { name = "jax", extra = ["cuda12"] }, +] graphcast = [ { name = "dm-haiku" }, { name = "dm-tree" }, @@ -1936,8 +1943,10 @@ requires-dist = [ { name = "cupy-cuda12x", marker = "extra == 'da-interp'", specifier = "<14.0.0" }, { name = "cupy-cuda12x", marker = "extra == 'da-stormcast'", specifier = "<14.0.0" }, { name = "dm-haiku", marker = "extra == 'all'", specifier = ">=0.0.14" }, + { name = "dm-haiku", marker = "extra == 'gencast'", specifier = ">=0.0.14" }, { name = "dm-haiku", marker = "extra == 'graphcast'", specifier = ">=0.0.14" }, { name = "dm-tree", marker = "extra == 'all'", specifier = ">=0.1.9" }, + { name = "dm-tree", marker = "extra == 'gencast'", specifier = ">=0.1.9" }, { name = "dm-tree", marker = "extra == 'graphcast'", specifier = ">=0.1.9" }, { name = "earth2grid", marker = "extra == 'all'", git = "https://github.com/NVlabs/earth2grid.git?rev=11dcf1b0787a7eb6a8497a3a5a5e1fdcc31232d3" }, { name = "earth2grid", marker = "extra == 'cbottle'", git = "https://github.com/NVlabs/earth2grid.git?rev=11dcf1b0787a7eb6a8497a3a5a5e1fdcc31232d3" }, @@ -1968,6 +1977,7 @@ requires-dist = [ { name = "flash-attn", marker = "extra == 'aifsens'" }, { name = "flash-attn", marker = "extra == 'all'" }, { name = "flax", marker = "extra == 'all'", specifier = ">=0.10.6" }, + { name = "flax", marker = "extra == 'gencast'", specifier = ">=0.10.6" }, { name = "flax", marker = "extra == 'graphcast'", specifier = ">=0.10.6" }, { name = "fme", marker = "extra == 'ace2'", git = "https://github.com/ai2cm/ace.git?rev=e211cad3e1a5cff0fa84e8d2f0ee67042eff3d4d" }, { name = "fsspec", specifier = ">=2024.2.0" }, @@ -1975,6 +1985,7 @@ requires-dist = [ { name = "globus-sdk", marker = "extra == 'all'", specifier = "<4.0.0" }, { name = "globus-sdk", marker = "extra == 'data'", specifier = "<4.0.0" }, { name = "graphcast", marker = "extra == 'all'", git = "https://github.com/google-deepmind/graphcast.git?rev=7077d40a36db6541e3ed72ccaed1c0d202fa6014" }, + { name = "graphcast", marker = "extra == 'gencast'", git = "https://github.com/google-deepmind/graphcast.git?rev=7077d40a36db6541e3ed72ccaed1c0d202fa6014" }, { name = "graphcast", marker = "extra == 'graphcast'", git = "https://github.com/google-deepmind/graphcast.git?rev=7077d40a36db6541e3ed72ccaed1c0d202fa6014" }, { name = "h5netcdf", specifier = ">=1.0.0" }, { name = "h5py", specifier = ">=3.2.0" }, @@ -1994,6 +2005,7 @@ requires-dist = [ { name = "intake-esgf", marker = "extra == 'all'", specifier = ">=2025.9.26" }, { name = "intake-esgf", marker = "extra == 'data'", specifier = ">=2025.9.26" }, { name = "jax", extras = ["cuda12"], marker = "extra == 'all'", specifier = ">=0.4.26" }, + { name = "jax", extras = ["cuda12"], marker = "extra == 'gencast'", specifier = ">=0.4.26" }, { name = "jax", extras = ["cuda12"], marker = "extra == 'graphcast'", specifier = ">=0.4.26" }, { name = "loguru" }, { name = "makani", marker = "extra == 'all'", git = "https://github.com/NVIDIA/makani.git?rev=b38fcb2799d7dbc146fa60459f3f9823394a8bf1" }, @@ -2125,7 +2137,7 @@ requires-dist = [ { name = "xarray", extras = ["parallel"], specifier = ">=2023.1.0" }, { name = "zarr", specifier = ">=3.1.0" }, ] -provides-extras = ["ace2", "aifs", "aifsens", "all", "atlas", "aurora", "cbottle", "climatenet", "corrdiff", "cyclone", "da-healda", "da-interp", "da-stormcast", "data", "derived", "dlesym", "dlwp", "fcn", "fcn3", "fengwu", "fuxi", "graphcast", "interp-modafno", "pangu", "perturbation", "precip-afno", "precip-afno-v2", "serve", "sfno", "solarradiation-afno", "statistics", "stormcast", "stormscope", "utils", "windgust-afno"] +provides-extras = ["ace2", "aifs", "aifsens", "all", "atlas", "aurora", "cbottle", "climatenet", "corrdiff", "cyclone", "da-healda", "da-interp", "da-stormcast", "data", "derived", "dlesym", "dlwp", "fcn", "fcn3", "fengwu", "fuxi", "gencast", "graphcast", "interp-modafno", "pangu", "perturbation", "precip-afno", "precip-afno-v2", "serve", "sfno", "solarradiation-afno", "statistics", "stormcast", "stormscope", "utils", "windgust-afno"] [package.metadata.requires-dev] build = [ From 85028915537382fe2fb955c7d82036e9fe1234ca Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Thu, 26 Mar 2026 00:27:22 +0000 Subject: [PATCH 03/20] Removing prints --- earth2studio/models/nn/atlas.py | 5 ++++- earth2studio/serve/client/client.py | 2 -- earth2studio/serve/server/config.py | 12 ------------ 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/earth2studio/models/nn/atlas.py b/earth2studio/models/nn/atlas.py index 671bebb7a..a3250fcd5 100644 --- a/earth2studio/models/nn/atlas.py +++ b/earth2studio/models/nn/atlas.py @@ -24,6 +24,7 @@ import torch import torch.nn as nn import torch.nn.functional as F +from loguru import logger from torch.nn.attention import SDPBackend, sdpa_kernel from earth2studio.utils.imports import ( @@ -729,7 +730,9 @@ def sample( kept_samples += 1 if verbose: - print(f"Sampling step: {j+1}. Time: {default_timer() - physical_time}") + logger.debug( + f"Sampling step: {j+1}. Time: {default_timer() - physical_time}" + ) if keep_every is not None: return out diff --git a/earth2studio/serve/client/client.py b/earth2studio/serve/client/client.py index ecbaa6eec..3693955d2 100644 --- a/earth2studio/serve/client/client.py +++ b/earth2studio/serve/client/client.py @@ -69,8 +69,6 @@ class Earth2StudioClient: -------- >>> client = Earth2StudioClient(base_url="http://localhost:8000") >>> health = client.health_check() - >>> print(health.status) - healthy With authentication: diff --git a/earth2studio/serve/server/config.py b/earth2studio/serve/server/config.py index 8b485a2d4..418616475 100644 --- a/earth2studio/serve/server/config.py +++ b/earth2studio/serve/server/config.py @@ -450,12 +450,6 @@ def get_config() -> AppConfig: Returns: AppConfig: The application configuration - - Example: - >>> from earth2studio.serve.server.config import get_config - >>> config = get_config() - >>> print(config.redis.host) - 'localhost' """ return get_config_manager().config @@ -489,11 +483,5 @@ def get_workflow_config(name: str) -> dict[str, Any]: Returns: dict[str, Any]: The workflow configuration - - Example: - >>> from earth2studio.serve.server.config import get_workflow_config - >>> config = get_workflow_config("deterministic_earth2_workflow") - >>> print(config["model_type"]) - 'fcn' """ return get_config_manager().workflow_config.get(name, {}) From c09b145c87e22df85357c8c742934824b2d355ff Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Thu, 26 Mar 2026 03:11:17 +0000 Subject: [PATCH 04/20] udpates --- earth2studio/models/px/__init__.py | 4 + earth2studio/models/px/gencast_mini.py | 117 ++++++++++++++++++------- test/models/px/test_gencast_mini.py | 2 + 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/earth2studio/models/px/__init__.py b/earth2studio/models/px/__init__.py index 91db0eba6..2b360dce3 100644 --- a/earth2studio/models/px/__init__.py +++ b/earth2studio/models/px/__init__.py @@ -39,3 +39,7 @@ from earth2studio.models.px.sfno import SFNO from earth2studio.models.px.stormcast import StormCast from earth2studio.models.px.stormscope import StormScopeGOES, StormScopeMRMS + +# Silence warning spam from various models +warnings.filterwarnings("ignore") +warnings.filterwarnings("ignore", category=FutureWarning) diff --git a/earth2studio/models/px/gencast_mini.py b/earth2studio/models/px/gencast_mini.py index a8e35418c..e38b76366 100644 --- a/earth2studio/models/px/gencast_mini.py +++ b/earth2studio/models/px/gencast_mini.py @@ -14,8 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +import contextlib import dataclasses import functools +import io from collections import OrderedDict from collections.abc import Callable, Generator, Iterator from typing import Any @@ -167,8 +169,14 @@ class GenCastMini(torch.nn.Module, AutoModelMixin, PrognosticMixin): Geopotential at surface on lat-lon grid sst_nan_mask : np.ndarray Boolean mask indicating where SST values are NaN (ocean vs land) - seed : int, optional - Random seed for JAX PRNG key used in stochastic sampling, by default 0 + seed : int | None, optional + Random seed for JAX PRNG key used in stochastic sampling, by default 0. + If None, a random seed is generated each time the model is called, + producing fully non-reproducible stochastic forecasts. + jit_compile : bool, optional + JIT-compile the model forward pass, requires 24GB of host RAM. JIT compilation + adds a one-time cost (several minutes for the first call) but makes subsequent + calls significantly faster, by default True. Badges ------ @@ -186,7 +194,8 @@ def __init__( land_sea_mask: np.ndarray, geopotential_at_surface: np.ndarray, sst_nan_mask: np.ndarray, - seed: int = 0, + seed: int | None = 0, + jit_compile: bool = True, ): super().__init__() @@ -198,9 +207,11 @@ def __init__( self.land_sea_mask = land_sea_mask self.geopotential_at_surface = geopotential_at_surface self.sst_nan_mask = sst_nan_mask - self.prng_key = jax.random.PRNGKey(seed) + self.seed = seed - self.run_forward = self._load_run_forward_from_checkpoint() + self.run_forward = self._load_run_forward_from_checkpoint( + jit_compile=jit_compile + ) n_lat = land_sea_mask.shape[0] n_lon = land_sea_mask.shape[1] @@ -294,6 +305,8 @@ def load_default_package(cls) -> Package: def load_model( cls, package: Package, + jit_compile: bool = True, + seed: int | None = 0, ) -> PrognosticModel: """Load prognostic model from package. @@ -301,6 +314,11 @@ def load_model( ---------- package : Package Package to load model from + jit_compile : bool, optional + JIT-compile the model forward pass with, by default True. + seed : int | None, optional + Random seed for stochastic sampling, by default 0. If None, + produces fully non-reproducible forecasts. Returns ------- @@ -346,13 +364,15 @@ def load_model( land_sea_mask, geopotential_at_surface, sst_nan_mask, + seed=seed, + jit_compile=jit_compile, ) # ------------------------------------------------------------------------- # Private / support methods # ------------------------------------------------------------------------- - def _load_run_forward_from_checkpoint(self) -> Callable: + def _load_run_forward_from_checkpoint(self, jit_compile: bool = True) -> Callable: """Build GenCast inference function from checkpoint. This function is based on the inference pipeline from: @@ -517,7 +537,10 @@ def with_params(fn: Callable) -> Callable: def drop_state(fn: Callable) -> Callable: return lambda **kw: fn(**kw)[0] - return drop_state(with_params(with_configs(run_forward.apply))) + fn = drop_state(with_params(with_configs(run_forward.apply))) + if jit_compile: + fn = jax.jit(fn) + return fn def _chunked_prediction_generator( self, @@ -526,6 +549,7 @@ def _chunked_prediction_generator( inputs: xr.Dataset, targets_template: xr.Dataset, forcings: xr.Dataset, + init_datetime: np.ndarray, ) -> Generator[xr.Dataset, None, None]: """Autoregressive prediction generator for GenCast. @@ -560,6 +584,9 @@ def _chunked_prediction_generator( Template for target predictions (NaN-filled) forcings : xr.Dataset Forcing variables dataset + init_datetime : np.ndarray + Absolute datetime(s) for the initial condition (t=0 reference). + Used to compute correct forcing variables (day/year progress) at each step. Yields ------ @@ -585,14 +612,15 @@ def split_rng_fn( forcings = forcings.assign_coords(time=targets_chunk_time) forcings = forcings.compute() - # Make prediction for this step + # Make prediction for this step (suppress graphcast debug prints) rng, this_rng = split_rng_fn(rng) - predictions = predictor_fn( - rng=this_rng, - inputs=current_inputs, - targets_template=targets_template, - forcings=forcings, - ) + with contextlib.redirect_stdout(io.StringIO()): + predictions = predictor_fn( + rng=this_rng, + inputs=current_inputs, + targets_template=targets_template, + forcings=forcings, + ) next_frame = xr.merge([predictions, forcings]) # Update inputs for next step @@ -607,25 +635,32 @@ def split_rng_fn( yield predictions del predictions - # Recompute forcings for next step + # Recompute forcings for the NEXT step. # GenCast only uses generated forcings (year/day progress) - # which are derived from datetime coordinates - datetime_offset = np.timedelta64((index + 1) * 12, "h") - current_datetime = current_inputs.coords.get( - "datetime", current_inputs.coords["time"] + # which are derived from datetime coordinates. + # Forcings must be at the TARGET time (not input time). + # The next step (index+1) targets T0 + (index+2)*12h, + # so we build a two-frame window at + # [T0 + (index+1)*12h, T0 + (index+2)*12h] + # and extract the last frame for the target-time forcing. + step_datetimes = np.array( + [ + init_datetime + np.timedelta64((index + 1) * 12, "h"), + init_datetime + np.timedelta64((index + 2) * 12, "h"), + ] ) # Build minimal batch for forcing computation batch = current_inputs.copy() - # Ensure datetime has (batch, time) dims for add_derived_vars - new_datetime = current_datetime.values + datetime_offset - if new_datetime.ndim == 1 and "batch" in batch.dims: - new_datetime = np.expand_dims(new_datetime, axis=0) + if step_datetimes.ndim == 1 and "batch" in batch.dims: + step_datetimes_2d = np.expand_dims(step_datetimes, axis=0) + else: + step_datetimes_2d = step_datetimes batch = batch.assign_coords( datetime=( - (("batch", "time"), new_datetime) + (("batch", "time"), step_datetimes_2d) if "batch" in batch.dims - else current_datetime + datetime_offset + else ("time", step_datetimes) ) ) @@ -908,13 +943,20 @@ def __call__( **dataclasses.asdict(self.ckpt.task_config), ) - predictions = rollout.chunked_prediction( - self.run_forward, - rng=self.prng_key, - inputs=inputs, - targets_template=targets * np.nan, - forcings=forcings, - ) + # Create a fresh PRNG key for each time step + if self.seed is not None: + step_rng = jax.random.fold_in(jax.random.PRNGKey(self.seed), t) + else: + step_rng = jax.random.PRNGKey(np.random.randint(0, 2**31)) + # Silence print out from graphcast package for this model + with contextlib.redirect_stdout(io.StringIO()): + predictions = rollout.chunked_prediction( + self.run_forward, + rng=step_rng, + inputs=inputs, + targets_template=targets * np.nan, + forcings=forcings, + ) results.append(self.iterator_result_to_tensor(predictions)) out = torch.cat(results, dim=1) if n_times > 1 else results[0] @@ -1014,20 +1056,27 @@ def create_iterator( batch, target_lead_times = self.from_dataarray_to_dataset( xr.DataArray(x_t.cpu(), coords=coords_t), 12 ) - + init_datetime = batch.coords["datetime"].values[0, 1] inputs, targets, forcings = data_utils.extract_inputs_targets_forcings( batch, target_lead_times=target_lead_times, **dataclasses.asdict(self.ckpt.task_config), ) + # Create a fresh PRNG key for each time iterator. + # If seed is set, use fold_in for reproducible per-iterator keys. + if self.seed is not None: + iter_rng = jax.random.fold_in(jax.random.PRNGKey(self.seed), t) + else: + iter_rng = jax.random.PRNGKey(np.random.randint(0, 2**31)) self.iterators.append( self._chunked_prediction_generator( predictor_fn=self.run_forward, - rng=self.prng_key, + rng=iter_rng, inputs=inputs, targets_template=targets * np.nan, forcings=forcings, + init_datetime=init_datetime, ) ) diff --git a/test/models/px/test_gencast_mini.py b/test/models/px/test_gencast_mini.py index fad38fd68..984e9a717 100644 --- a/test/models/px/test_gencast_mini.py +++ b/test/models/px/test_gencast_mini.py @@ -76,6 +76,7 @@ def mocked_chunked_prediction_generator( inputs, targets_template, forcings, + init_datetime=None, ): yield targets_template.isel(time=[0]) while True: @@ -189,6 +190,7 @@ def mock_GenCastMini_model(): np.ones((n_lat, n_lon), dtype=np.float32), np.ones((n_lat, n_lon), dtype=np.float32), np.ones((n_lat, n_lon), dtype=bool), + jit_compile=False, ) # Mock the iterator to avoid needing real JAX inference From 3867650bbc5cec191402eff066c7ff8ea54ca522 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Thu, 26 Mar 2026 04:29:53 +0000 Subject: [PATCH 05/20] Final fixes --- earth2studio/models/px/gencast_mini.py | 76 +++++++++++--------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/earth2studio/models/px/gencast_mini.py b/earth2studio/models/px/gencast_mini.py index e38b76366..57c24a0a4 100644 --- a/earth2studio/models/px/gencast_mini.py +++ b/earth2studio/models/px/gencast_mini.py @@ -181,7 +181,7 @@ class GenCastMini(torch.nn.Module, AutoModelMixin, PrognosticMixin): Badges ------ region:global class:mrf product:wind product:precip product:temp product:atmos - year:2024 gpu:40gb + product:ocean year:2024 gpu:40gb """ def __init__( @@ -489,7 +489,7 @@ def construct_wrapped_gencast( mean_by_level=self.mean_by_level, stddev_by_level=self.stddev_by_level, ) - + # Applies ERA5 NaN masking to SST fields for consistency predictor = nan_cleaning.NaNCleaner( predictor=predictor, reintroduce_nans=True, @@ -635,52 +635,40 @@ def split_rng_fn( yield predictions del predictions - # Recompute forcings for the NEXT step. - # GenCast only uses generated forcings (year/day progress) - # which are derived from datetime coordinates. - # Forcings must be at the TARGET time (not input time). - # The next step (index+1) targets T0 + (index+2)*12h, - # so we build a two-frame window at - # [T0 + (index+1)*12h, T0 + (index+2)*12h] - # and extract the last frame for the target-time forcing. - step_datetimes = np.array( - [ - init_datetime + np.timedelta64((index + 1) * 12, "h"), - init_datetime + np.timedelta64((index + 2) * 12, "h"), - ] - ) + # Compute forcings for the NEXT step directly from + # datetime, matching the notebook's precomputed approach. + # The next step (index+1) targets T0 + (index+2)*12h. + next_target_dt = init_datetime + np.timedelta64((index + 2) * 12, "h") + next_dt = np.atleast_1d(next_target_dt) + seconds = next_dt.astype("datetime64[s]").astype(np.int64) + lon = current_inputs.coords["lon"].data - # Build minimal batch for forcing computation - batch = current_inputs.copy() - if step_datetimes.ndim == 1 and "batch" in batch.dims: - step_datetimes_2d = np.expand_dims(step_datetimes, axis=0) - else: - step_datetimes_2d = step_datetimes - batch = batch.assign_coords( - datetime=( - (("batch", "time"), step_datetimes_2d) - if "batch" in batch.dims - else ("time", step_datetimes) - ) - ) + has_batch = "batch" in current_inputs.dims + batch_dim = ("batch",) if has_batch else () - # Drop old forcing vars if present - force_vars = list(GENERATED_FORCING_VARS) + [ - "year_progress", - "day_progress", - ] - for fvar in force_vars: - if fvar in batch: - batch = batch.drop_vars(fvar) + year_progress = data_utils.get_year_progress(seconds) + day_progress = data_utils.get_day_progress(seconds, lon) - # Recompute derived forcing variables - data_utils.add_derived_vars(batch) - batch = batch.compute() + if has_batch: + year_progress = year_progress[np.newaxis] + day_progress = day_progress[np.newaxis] - # Extract new forcings - forcings = batch.isel(time=slice(-1, None))[list(GENERATED_FORCING_VARS)] - forcings = forcings.reset_coords("datetime", drop=True) - forcings = forcings.compute() + year_feats = data_utils.featurize_progress( + "year_progress", batch_dim + ("time",), year_progress + ) + day_feats = data_utils.featurize_progress( + "day_progress", + batch_dim + ("time",) + current_inputs.coords["lon"].dims, + day_progress, + ) + + forcings = xr.Dataset( + { + k: v + for k, v in {**year_feats, **day_feats}.items() + if k in GENERATED_FORCING_VARS + } + ) index += 1 From 51ada581cf0795c8957c09383e05f29c8c982856 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Thu, 26 Mar 2026 04:42:13 +0000 Subject: [PATCH 06/20] Greptile --- earth2studio/models/px/gencast_mini.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/earth2studio/models/px/gencast_mini.py b/earth2studio/models/px/gencast_mini.py index 57c24a0a4..25279d687 100644 --- a/earth2studio/models/px/gencast_mini.py +++ b/earth2studio/models/px/gencast_mini.py @@ -787,10 +787,7 @@ def from_dataarray_to_dataset( ) # 2nd date is center (t=0) - if len(data.time.values) == 1: - start_date = (data.time.values + data.lead_time.values)[1] - else: - start_date = data.time.values[1] + start_date = data.time.values[1] all_datetimes = [start_date + time_delta for time_delta in time_deltas] data = data.to_dataset(dim="variable") @@ -959,6 +956,7 @@ def _default_generator( self, x: torch.Tensor, coords: CoordSystem, + iterators: list[Generator[xr.Dataset, None, None]] | None = None, ) -> Generator[tuple[torch.Tensor, CoordSystem]]: """Default generator for time-stepping through iterator results. @@ -968,12 +966,16 @@ def _default_generator( Input tensor coords : CoordSystem Input coordinate system + iterators : list[Generator[xr.Dataset, None, None]] | None, optional + List of per-time autoregressive prediction generators, by default None Yields ------ tuple[torch.Tensor, CoordSystem] Output tensor and coordinate system at each time step """ + if iterators is None: + iterators = [] coords = coords.copy() coords_out = self.output_coords(coords) @@ -1000,9 +1002,7 @@ def _default_generator( coords = self.output_coords(coords) # Get next prediction from all time iterators - results = [ - self.iterator_result_to_tensor(next(it)) for it in self.iterators - ] + results = [self.iterator_result_to_tensor(next(it)) for it in iterators] x = torch.cat(results, dim=1) if len(results) > 1 else results[0] x, coords = self.rear_hook(x, coords) @@ -1034,7 +1034,7 @@ def create_iterator( with jax.default_device(self.get_jax_device_from_tensor(x)): time_dim = list(coords.keys()).index("time") n_times = len(coords["time"]) - self.iterators = [] + iterators = [] for t in range(n_times): x_t = x.narrow(time_dim, t, 1) @@ -1057,7 +1057,7 @@ def create_iterator( iter_rng = jax.random.fold_in(jax.random.PRNGKey(self.seed), t) else: iter_rng = jax.random.PRNGKey(np.random.randint(0, 2**31)) - self.iterators.append( + iterators.append( self._chunked_prediction_generator( predictor_fn=self.run_forward, rng=iter_rng, @@ -1068,4 +1068,4 @@ def create_iterator( ) ) - yield from self._default_generator(x, coords) + yield from self._default_generator(x, coords, iterators) From 764c8d5db917f0d58dbd2ac7ee89a9b831ed55c9 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Thu, 26 Mar 2026 04:44:00 +0000 Subject: [PATCH 07/20] Greptile --- earth2studio/models/px/gencast_mini.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/earth2studio/models/px/gencast_mini.py b/earth2studio/models/px/gencast_mini.py index 25279d687..4f2bb5a5e 100644 --- a/earth2studio/models/px/gencast_mini.py +++ b/earth2studio/models/px/gencast_mini.py @@ -956,7 +956,6 @@ def _default_generator( self, x: torch.Tensor, coords: CoordSystem, - iterators: list[Generator[xr.Dataset, None, None]] | None = None, ) -> Generator[tuple[torch.Tensor, CoordSystem]]: """Default generator for time-stepping through iterator results. @@ -966,16 +965,12 @@ def _default_generator( Input tensor coords : CoordSystem Input coordinate system - iterators : list[Generator[xr.Dataset, None, None]] | None, optional - List of per-time autoregressive prediction generators, by default None Yields ------ tuple[torch.Tensor, CoordSystem] Output tensor and coordinate system at each time step """ - if iterators is None: - iterators = [] coords = coords.copy() coords_out = self.output_coords(coords) @@ -1002,7 +997,9 @@ def _default_generator( coords = self.output_coords(coords) # Get next prediction from all time iterators - results = [self.iterator_result_to_tensor(next(it)) for it in iterators] + results = [ + self.iterator_result_to_tensor(next(it)) for it in self._iterators + ] x = torch.cat(results, dim=1) if len(results) > 1 else results[0] x, coords = self.rear_hook(x, coords) @@ -1034,7 +1031,7 @@ def create_iterator( with jax.default_device(self.get_jax_device_from_tensor(x)): time_dim = list(coords.keys()).index("time") n_times = len(coords["time"]) - iterators = [] + self._iterators: list[Generator[xr.Dataset, None, None]] = [] for t in range(n_times): x_t = x.narrow(time_dim, t, 1) @@ -1057,7 +1054,7 @@ def create_iterator( iter_rng = jax.random.fold_in(jax.random.PRNGKey(self.seed), t) else: iter_rng = jax.random.PRNGKey(np.random.randint(0, 2**31)) - iterators.append( + self._iterators.append( self._chunked_prediction_generator( predictor_fn=self.run_forward, rng=iter_rng, @@ -1068,4 +1065,4 @@ def create_iterator( ) ) - yield from self._default_generator(x, coords, iterators) + yield from self._default_generator(x, coords) From 23187ad0179f4e301768ec221bd28803f92c2673 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Mon, 30 Mar 2026 06:13:26 +0000 Subject: [PATCH 08/20] Init --- CHANGELOG.md | 1 + docs/modules/models_px.rst | 1 + earth2studio/data/__init__.py | 1 + earth2studio/data/ace2.py | 5 +- earth2studio/data/samudrace.py | 249 ++++++++ earth2studio/lexicon/__init__.py | 1 + earth2studio/lexicon/base.py | 10 + earth2studio/lexicon/samudrace.py | 154 +++++ earth2studio/models/px/__init__.py | 1 + earth2studio/models/px/samudrace.py | 949 ++++++++++++++++++++++++++++ pyproject.toml | 21 + test/models/px/test_samudrace.py | 343 ++++++++++ tox.ini | 4 +- uv.lock | 730 +++++++++++---------- 14 files changed, 2116 insertions(+), 354 deletions(-) create mode 100644 earth2studio/data/samudrace.py create mode 100644 earth2studio/lexicon/samudrace.py create mode 100644 earth2studio/models/px/samudrace.py create mode 100644 test/models/px/test_samudrace.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 9468241d2..f7a70a82a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added GenCast 1 degree Mini model +- Added SamudrACE Coupled Climate Model ### Changed diff --git a/docs/modules/models_px.rst b/docs/modules/models_px.rst index 1def4736c..800ca86b2 100644 --- a/docs/modules/models_px.rst +++ b/docs/modules/models_px.rst @@ -55,6 +55,7 @@ Thus are typically used to generate forecast predictions. Pangu6 Pangu3 Persistence + SamudrACE SFNO StormCast StormScopeGOES diff --git a/earth2studio/data/__init__.py b/earth2studio/data/__init__.py index a27049741..10d7753d8 100644 --- a/earth2studio/data/__init__.py +++ b/earth2studio/data/__init__.py @@ -39,6 +39,7 @@ ) from .rand import Random, Random_FX, RandomDataFrame from .rx import CosineSolarZenith, LandSeaMask, SurfaceGeoPotential +from .samudrace import SamudrACEData from .time_window import TimeWindow from .ufs import UFSObsConv, UFSObsSat from .utils import datasource_to_file, fetch_data, fetch_dataframe, prep_data_array diff --git a/earth2studio/data/ace2.py b/earth2studio/data/ace2.py index faa2605aa..44919e0fb 100644 --- a/earth2studio/data/ace2.py +++ b/earth2studio/data/ace2.py @@ -50,8 +50,9 @@ @check_optional_dependencies("ace2") class ACE2ERA5Data: """ACE2-ERA5 data source providing forcing or initial-conditions data. - Files are downloaded on-demand and cached automatically. Data are served as-is; no transformations are applied, - with the exception of global mean CO2 concentration, which may be overridden by a user-supplied function. + Files are downloaded on-demand and cached automatically. Data are served as-is; no + transformations are applied, with the exception of global mean CO2 concentration, + which may be overridden by a user-supplied function. Provides all input variables described in the ACE2-ERA5 paper. diff --git a/earth2studio/data/samudrace.py b/earth2studio/data/samudrace.py new file mode 100644 index 000000000..d5cd8d33f --- /dev/null +++ b/earth2studio/data/samudrace.py @@ -0,0 +1,249 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import shutil +from datetime import datetime + +import numpy as np +import xarray as xr +from huggingface_hub import HfFileSystem +from loguru import logger + +from earth2studio.data.ace2 import ACE_GRID_LAT, ACE_GRID_LON +from earth2studio.data.utils import datasource_cache_root, prep_data_inputs +from earth2studio.lexicon.samudrace import SamudrACELexicon +from earth2studio.utils.type import TimeArray, VariableArray + +# Available initial-condition timestamps and their HF paths +_IC_TIMESTAMPS: dict[str, str] = { + "0151-01-06T00:00:00": "0151-01-06T00:00:00", + "0311-01-01T00:00:00": "0311-01-01T00:00:00", + "0313-01-01T00:00:00": "0313-01-01T00:00:00", + "0315-01-01T00:00:00": "0315-01-01T00:00:00", + "0317-01-01T00:00:00": "0317-01-01T00:00:00", + "0319-01-01T00:00:00": "0319-01-01T00:00:00", +} + + +class SamudrACEData: + """SamudrACE initial-condition data source. + + Provides combined atmosphere and ocean initial-condition variables from + the SamudrACE HuggingFace repository. Each initial condition has separate + atmosphere and ocean NetCDF files that are downloaded, merged, and served + as a single ``xr.DataArray`` with all 118 prognostic variables (38 + atmosphere + 80 ocean). + + The SamudrACE checkpoint was trained on a GFDL CM4 preindustrial-control + run. Initial conditions are identified by their CM4 model-year timestamp + (e.g. ``"0311-01-01T00:00:00"``). Because the model-year dates do not + correspond to real calendar dates, the ``ic_timestamp`` parameter selects + which IC snapshot to serve; the data are then returned for whatever + ``time`` is requested (i.e. the same spatial fields are recycled). + + Parameters + ---------- + ic_timestamp : str, optional + Initial-condition timestamp identifier. Must be one of the available + timestamps in the repository, by default ``"0311-01-01T00:00:00"``. + cache : bool, optional + Cache downloaded files locally, by default True. + verbose : bool, optional + Print download progress, by default True. + + References + ---------- + - SamudrACE paper: https://arxiv.org/abs/2509.12490 + - HuggingFace repo: https://huggingface.co/allenai/SamudrACE-CM4-piControl + + Badges + ------ + region:global dataclass:reanalysis product:temp product:atmos product:ocean + """ + + _HF_REPO_ID = "allenai/SamudrACE-CM4-piControl" + + def __init__( + self, + ic_timestamp: str = "0311-01-01T00:00:00", + cache: bool = True, + verbose: bool = True, + ): + if ic_timestamp not in _IC_TIMESTAMPS: + raise ValueError( + f"ic_timestamp must be one of {list(_IC_TIMESTAMPS.keys())}, " + f"got '{ic_timestamp}'" + ) + self._ic_timestamp = ic_timestamp + self._cache = cache + self._verbose = verbose + self.lat = ACE_GRID_LAT + self.lon = ACE_GRID_LON + self._hf_fs = HfFileSystem() + self._atm_ds: xr.Dataset | None = None + self._ocean_ds: xr.Dataset | None = None + + def __call__( + self, + time: datetime | list[datetime] | TimeArray, + variable: str | list[str] | VariableArray, + ) -> xr.DataArray: + """Fetch initial-condition data. + + The same spatial fields are returned for every requested time (the IC + snapshot is time-invariant). Variables are mapped from Earth2Studio + names to FME names via the ``SamudrACELexicon``. + + Parameters + ---------- + time : datetime | list[datetime] | TimeArray + Timestamps to return data for (UTC). The spatial fields are + identical for all times; only the time coordinate differs. + variable : str | list[str] | VariableArray + Earth2Studio variable names. + + Returns + ------- + xr.DataArray + Data array with dimensions ``[time, variable, lat, lon]``. + """ + time_list, var_list_e2s = prep_data_inputs(time, variable) + + # Map E2S → FME variable names + try: + var_list_fme = [SamudrACELexicon[v][0] for v in var_list_e2s] + except KeyError as e: + raise KeyError(f"Unknown SamudrACE variable id: {e}") from e + + return self._fetch_initial_conditions(time_list, var_list_e2s, var_list_fme) + + async def fetch( + self, + time: datetime | list[datetime] | TimeArray, + variable: str | list[str] | VariableArray, + ) -> xr.DataArray: + """Async wrapper for :meth:`__call__`. + + Parameters + ---------- + time : datetime | list[datetime] | TimeArray + Timestamps to return data for (UTC). + variable : str | list[str] | VariableArray + Earth2Studio variable names. + + Returns + ------- + xr.DataArray + Data array with dimensions ``[time, variable, lat, lon]``. + """ + return self(time, variable) + + @property + def cache(self) -> str: + """Local cache directory for downloaded files.""" + root = os.path.join(datasource_cache_root(), "SamudrACE") + if not self._cache: + root = os.path.join(root, "tmp_SamudrACE") + return root + + def _download_ic_file(self, component: str) -> str: + """Download a single IC file (atmosphere or ocean) and return local path. + + Parameters + ---------- + component : str + Either ``"atmosphere"`` or ``"ocean"``. + + Returns + ------- + str + Local filesystem path to the downloaded NetCDF file. + """ + hf_dir = _IC_TIMESTAMPS[self._ic_timestamp] + filename = f"initial_conditions/{hf_dir}/{component}/initial_condition.nc" + local_path = os.path.join(self.cache, filename) + if not os.path.exists(local_path): + os.makedirs(os.path.dirname(local_path), exist_ok=True) + hf_path = f"{self._HF_REPO_ID}/{filename}" + logger.info("Downloading SamudrACE {} IC: {}", component, hf_path) + self._hf_fs.get_file(hf_path, local_path) + return local_path + + def _open_ic_datasets(self) -> tuple[xr.Dataset, xr.Dataset]: + """Lazily download and open atmosphere and ocean IC datasets.""" + if self._atm_ds is None: + atm_path = self._download_ic_file("atmosphere") + self._atm_ds = xr.open_dataset(atm_path, engine="netcdf4") + if self._ocean_ds is None: + ocean_path = self._download_ic_file("ocean") + self._ocean_ds = xr.open_dataset(ocean_path, engine="netcdf4") + return self._atm_ds, self._ocean_ds + + def _fetch_initial_conditions( + self, + time_list: list[datetime], + var_list_e2s: list[str], + var_list_fme: list[str], + ) -> xr.DataArray: + """Load atmosphere + ocean IC variables and merge into a single DataArray. + + Each IC file has a ``sample`` dimension of size 1. The spatial fields + are broadcast identically to every requested time. + """ + atm_ds, ocean_ds = self._open_ic_datasets() + + arrays: list[xr.DataArray] = [] + for fme_name, e2s_name in zip(var_list_fme, var_list_e2s): + # Look in atmosphere first, then ocean + if fme_name in atm_ds: + da = atm_ds[fme_name] + elif fme_name in ocean_ds: + da = ocean_ds[fme_name] + else: + raise KeyError( + f"Variable '{fme_name}' (E2S: '{e2s_name}') not found in " + f"SamudrACE IC files for timestamp '{self._ic_timestamp}'" + ) + + # IC files have dims (sample, lat, lon); squeeze sample + if "sample" in da.dims: + da = da.isel(sample=0) + + # Ensure (lat, lon) ordering + if "lat" in da.dims and "lon" in da.dims: + da = da.transpose("lat", "lon") + + # Assign canonical grid coordinates + da = da.assign_coords(lat=self.lat, lon=self.lon) + + # Broadcast to every requested time + per_time = [da for _ in time_list] + + stacked = xr.concat(per_time, dim="time") + stacked = stacked.assign_coords( + time=np.array(time_list, dtype="datetime64[ns]") + ) + arrays.append(stacked) + + result = xr.concat(arrays, dim="variable") + result = result.assign_coords(variable=np.array(var_list_e2s, dtype=object)) + result = result.transpose("time", "variable", "lat", "lon") + + if not self._cache: + shutil.rmtree(self.cache, ignore_errors=True) + + return result diff --git a/earth2studio/lexicon/__init__.py b/earth2studio/lexicon/__init__.py index 34b01a31d..af829e17f 100644 --- a/earth2studio/lexicon/__init__.py +++ b/earth2studio/lexicon/__init__.py @@ -35,5 +35,6 @@ PlanetaryComputerOISSTLexicon, PlanetaryComputerSentinel3AODLexicon, ) +from .samudrace import SamudrACELexicon from .ufs import GSIConventionalLexicon, GSISatelliteLexicon from .wb2 import WB2ClimatetologyLexicon, WB2Lexicon diff --git a/earth2studio/lexicon/base.py b/earth2studio/lexicon/base.py index 88f5fdac2..66b7d730e 100644 --- a/earth2studio/lexicon/base.py +++ b/earth2studio/lexicon/base.py @@ -279,6 +279,16 @@ def __contains__(cls, val: object) -> bool: "strd06": "surface long-wave (thermal) radiation downwards (J m-2) past 6 hours", "sf": "snowfall water equivalent (kg m-2)", "ro": "runoff water equivalent (surface plus subsurface) (kg m-2)", + "ewss": "eastward turbulent surface stress (N m-2 s)", + "nsss": "northward turbulent surface stress (N m-2 s)", + "sithick": "sea ice thickness (m)", + "siconc": "sea ice area fraction as seen by the ocean (0-1)", + "zos": "sea surface height above geoid (m)", + "mttwp": "tendency of total water path due to advection (kg m-2 s-1)", + "thetao": "sea water potential temperature (K)", + "so": "sea water salinity (PSU)", + "uo": "sea water x (eastward) velocity (m s-1)", + "vo": "sea water y (northward) velocity (m s-1)", } diff --git a/earth2studio/lexicon/samudrace.py b/earth2studio/lexicon/samudrace.py new file mode 100644 index 000000000..404d02a6f --- /dev/null +++ b/earth2studio/lexicon/samudrace.py @@ -0,0 +1,154 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +from collections.abc import Callable + +import numpy as np + +from .base import LexiconType + + +def _build_variable_mappings() -> tuple[dict[str, str], dict[str, str]]: + """Build bidirectional mappings between Earth2Studio and FME variable names + for the SamudrACE coupled atmosphere-ocean model. + + The SamudrACE model uses CM4 model-level naming for atmosphere variables + and CMIP6 naming conventions for ocean variables. This mapping covers + all prognostic, forcing, and diagnostic variables across both components. + + Returns + ------- + tuple[dict[str, str], dict[str, str]] + Mapping from Earth2Studio variable names to FME variable names and + vice versa. + """ + mapping: dict[str, str] = { + # ---- Atmosphere: near-surface and surface ---- + "u10m": "UGRD10m", + "v10m": "VGRD10m", + "t2m": "TMP2m", + "q2m": "Q2m", + "sp": "PRESsfc", + "skt": "surface_temperature", + "z": "HGTsfc", + # ---- Atmosphere: forcing ---- + "mtdwswrf": "DSWRFtoa", + "land_abs": "land_fraction", + "ocean_abs": "ocean_fraction", + "sic_abs": "sea_ice_fraction", + # ---- Atmosphere: diagnostics ---- + "mslhf": "LHTFLsfc", + "msshf": "SHTFLsfc", + "tp": "PRATEsfc", + "msuwlwrf": "ULWRFsfc", + "mtuwlwrf": "ULWRFtoa", + "msdwlwrf": "DLWRFsfc", + "msdwswrf": "DSWRFsfc", + "msuwswrf": "USWRFsfc", + "mtuwswrf": "USWRFtoa", + "mttwp": "tendency_of_total_water_path_due_to_advection", + "ewss": "eastward_surface_wind_stress", + "nsss": "northward_surface_wind_stress", + "t850": "TMP850", + "z500": "h500", + # ---- Atmosphere: additional forcing ---- + "lake_abs": "lake_fraction", + # ---- Ocean: surface prognostic ---- + "sst": "sst", + "zos": "zos", + "sithick": "HI", + "siconc": "ocean_sea_ice_fraction", + } + + # ---- Atmosphere: CM4 model levels (k=0..7) ---- + for k in range(8): + mapping[f"u{k}k"] = f"eastward_wind_{k}" + mapping[f"v{k}k"] = f"northward_wind_{k}" + mapping[f"t{k}k"] = f"air_temperature_{k}" + mapping[f"qtot{k}k"] = f"specific_total_water_{k}" + + # ---- Ocean: depth-level variables (19 levels, 0..18) ---- + for d in range(19): + mapping[f"thetao_{d}"] = f"thetao_{d}" + mapping[f"so_{d}"] = f"so_{d}" + mapping[f"uo_{d}"] = f"uo_{d}" + mapping[f"vo_{d}"] = f"vo_{d}" + + fme_to_e2s = {v: k for k, v in mapping.items()} + return mapping, fme_to_e2s + + +# Public constants for reuse across model and data modules +E2S_TO_FME, FME_TO_E2S = _build_variable_mappings() + + +class SamudrACELexicon(metaclass=LexiconType): + """SamudrACE Lexicon + + Maps Earth2Studio variable names to the variable labels used by the FME + CoupledStepper for the SamudrACE coupled atmosphere-ocean model. Covers + both atmosphere (CM4 model levels) and ocean (CMIP6 naming) variables. + + Examples + -------- + >>> from earth2studio.lexicon.samudrace import SamudrACELexicon + >>> SamudrACELexicon["u10m"] + ("UGRD10m", <function mod at 0x...>) + >>> SamudrACELexicon.get_e2s_from_fme("sst") + "sst" + """ + + VOCAB: dict[str, str] = dict(E2S_TO_FME) + VOCAB_REVERSE: dict[str, str] = dict(FME_TO_E2S) + + @classmethod + def get_item(cls, val: str) -> tuple[str, Callable]: + """Return name in SamudrACE/FME vocabulary. + + Parameters + ---------- + val : str + Name in Earth2Studio terminology. + + Returns + ------- + tuple[str, Callable] + FME/SamudrACE variable name and modifier function. + """ + fme_key = cls.VOCAB[val] + + def mod(x: np.array) -> np.array: + return x + + return fme_key, mod + + @classmethod + def get_e2s_from_fme(cls, val: str) -> str: + """Return name in Earth2Studio terminology. + + Parameters + ---------- + val : str + Name in FME/SamudrACE terminology. + + Returns + ------- + str + Earth2Studio variable name. + """ + return cls.VOCAB_REVERSE[val] diff --git a/earth2studio/models/px/__init__.py b/earth2studio/models/px/__init__.py index 2b360dce3..55a091f47 100644 --- a/earth2studio/models/px/__init__.py +++ b/earth2studio/models/px/__init__.py @@ -36,6 +36,7 @@ from earth2studio.models.px.interpmodafno import InterpModAFNO from earth2studio.models.px.pangu import Pangu3, Pangu6, Pangu24 from earth2studio.models.px.persistence import Persistence +from earth2studio.models.px.samudrace import SamudrACE from earth2studio.models.px.sfno import SFNO from earth2studio.models.px.stormcast import StormCast from earth2studio.models.px.stormscope import StormScopeGOES, StormScopeMRMS diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py new file mode 100644 index 000000000..e3c070e26 --- /dev/null +++ b/earth2studio/models/px/samudrace.py @@ -0,0 +1,949 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +from collections import OrderedDict +from collections.abc import Generator, Iterator +from typing import Any + +import cftime +import numpy as np +import pandas as pd +import torch +import xarray as xr +from loguru import logger + +from earth2studio.data.ace2 import ACE_GRID_LAT, ACE_GRID_LON +from earth2studio.lexicon.samudrace import SamudrACELexicon +from earth2studio.models.auto import AutoModelMixin, Package +from earth2studio.models.batch import batch_coords, batch_func +from earth2studio.models.px.base import PrognosticModel +from earth2studio.models.px.utils import PrognosticMixin +from earth2studio.utils.coords import handshake_coords, handshake_dim +from earth2studio.utils.imports import ( + OptionalDependencyFailure, + check_optional_dependencies, +) +from earth2studio.utils.type import CoordSystem + +try: + from fme.ace.data_loading.batch_data import BatchData, PrognosticState + from fme.coupled.stepper import CoupledStepper, load_coupled_stepper + from huggingface_hub import HfFileSystem +except ImportError: + OptionalDependencyFailure("samudrace") + BatchData = Any + PrognosticState = Any + CoupledStepper = Any + HfFileSystem = None + + +# Number of atmosphere 6h steps in one coupled (ocean) 5-day cycle +N_INNER_STEPS = 20 + + +def _npdatetime64_to_cftime(dt64_array: np.ndarray) -> np.ndarray: + """Convert np.datetime64 array to cftime.DatetimeProlepticGregorian array. + + Parameters + ---------- + dt64_array : np.ndarray + Input datetime64 array. + + Returns + ------- + np.ndarray + Array of cftime.DatetimeProlepticGregorian objects. + """ + if len(dt64_array.shape) > 1: + return_shape = list(dt64_array.shape) + dt64_array = dt64_array.reshape(-1) + else: + return_shape = None + + dt_index = pd.to_datetime(dt64_array) + years = dt_index.year + months = dt_index.month + days = dt_index.day + hours = dt_index.hour + minutes = dt_index.minute + seconds = dt_index.second + + result = np.fromiter( + ( + cftime.DatetimeProlepticGregorian(y, m, d, H, M, S) + for y, m, d, H, M, S in zip(years, months, days, hours, minutes, seconds) + ), + dtype=object, + count=len(dt64_array), + ) + if return_shape is not None: + result = result.reshape(return_shape) + return result + + +@check_optional_dependencies() +class SamudrACE(torch.nn.Module, AutoModelMixin, PrognosticMixin): + """SamudrACE coupled atmosphere-ocean prognostic model wrapper. + + SamudrACE is a coupled climate emulator combining ACE2 (atmosphere, 6-hour + time steps) with Samudra (ocean, 5-day time steps) through a coupler that + exchanges surface fluxes and SST/sea-ice between the two components. The + model operates on a 1-degree horizontal grid (180x360) with 8 atmospheric + model levels and 19 ocean depth levels. + + Use :class:`earth2studio.data.SamudrACEData` to fetch initial-condition + data for this model. Forcing data (``DSWRFtoa`` and static fields) are + downloaded from HuggingFace automatically based on the ``forcing_scenario`` + parameter. + + Note + ---- + The atmosphere component uses 8 GFDL CM4 **hybrid sigma-pressure** levels + (indices 0-7). Pressure at each level is computed as + ``P(k) = ak(k) + bk(k) * P_surface``. The coefficients for the 9 level + interfaces (half-levels) are: + + ==== ======== ======= + k ak (Pa) bk + ==== ======== ======= + 0 100 0.000 + 1 5579 0.000 + 2 8198 0.043 + 3 8095 0.164 + 4 6465 0.363 + 5 4940 0.519 + 6 2367 0.768 + 7 1156 0.883 + 8 0 1.000 + ==== ======== ======= + + The ocean component uses 19 layers defined by 20 interface (half-level) + depths from the GFDL CM4 ocean grid. The interface depths in metres are: + + ``[0, 5, 15, 30, 50, 80, 130, 200, 300, 450, 650, 900, 1200, 1600, + 2100, 2700, 3500, 4500, 5500, 6500]`` + + Parameters + ---------- + coupled_stepper : CoupledStepper + FME CoupledStepper instance loaded from a checkpoint. + forcing_scenario : str, optional + Forcing scenario identifier, must be one of ``"0151"`` or ``"0311"``. The + corresponding forcing NetCDF file is downloaded from HuggingFace and cached + automatically, by default ``"0311"``. + dt : numpy.timedelta64, optional + Atmosphere model timestep, by default 6 hours. + + References + ---------- + - SamudrACE paper: https://arxiv.org/abs/2509.12490 + - ACE2 code: https://github.com/ai2cm/ace + + Badges + ------ + region:global class:cm product:temp product:atmos product:ocean year:2025 + gpu:40gb + """ + + def __init__( + self, + coupled_stepper: CoupledStepper, + forcing_scenario: str = "0311", + dt: np.timedelta64 = np.timedelta64(6, "h"), + ): + super().__init__() + + self.coupled_stepper = coupled_stepper + self._dt = dt + self._forcing_scenario = forcing_scenario + self._forcing_ds: xr.Dataset | None = None + self.lexicon = SamudrACELexicon + + # Register a buffer for device tracking + self.register_buffer("device_buffer", torch.empty(0)) + + # Atmosphere variable lists + atm_stepper = self.coupled_stepper.atmosphere + atm_prog_fme = list(atm_stepper.prognostic_names) + atm_forcing_fme = list(atm_stepper._input_only_names) + atm_out_fme = list(atm_stepper.out_names) + + # Ocean variable lists + ocean_stepper = self.coupled_stepper.ocean + ocean_prog_fme = list(ocean_stepper.prognostic_names) + ocean_forcing_fme = list(ocean_stepper._input_only_names) + ocean_out_fme = list(ocean_stepper.out_names) + + # Store FME variable lists (prognostic = state vars carried forward) + self._atm_prog_fme = sorted(atm_prog_fme) + self._atm_forcing_fme = sorted(atm_forcing_fme) + self._atm_out_fme = atm_out_fme + self._ocean_prog_fme = sorted(ocean_prog_fme) + self._ocean_forcing_fme = sorted(ocean_forcing_fme) + self._ocean_out_fme = ocean_out_fme + + # Build E2S equivalents + self._atm_prog_e2s = [ + self.lexicon.get_e2s_from_fme(v) for v in self._atm_prog_fme + ] + self._ocean_prog_e2s = [ + self.lexicon.get_e2s_from_fme(v) for v in self._ocean_prog_fme + ] + self._atm_out_e2s = [ + self.lexicon.get_e2s_from_fme(v) for v in self._atm_out_fme + ] + self._ocean_out_e2s = [ + self.lexicon.get_e2s_from_fme(v) for v in self._ocean_out_fme + ] + + # Combined prognostic and output variable lists (atmosphere first) + self._prog_e2s = self._atm_prog_e2s + self._ocean_prog_e2s + self._all_out_e2s = self._atm_out_e2s + self._ocean_out_e2s + + # Identify atmosphere forcing variables that must come from external + # data rather than from inter-component coupling. The coupled stepper + # handles ocean↔atmosphere exchange internally; we only need to feed + # the *exogenous* forcings that neither component produces. + ocean_out_set = set(ocean_out_fme) + self._exogenous_forcing_fme = sorted( + v for v in atm_forcing_fme if v not in ocean_out_set + ) + # The coupled ocean→atmosphere exchange supplies surface_temperature, + # sea_ice_fraction, and ocean_fraction — everything else must come + # from external data (including time-varying forcings like DSWRFtoa + # AND static fields like HGTsfc, land_fraction, lake_fraction). + _coupled_fields = {"ocean_fraction", "sea_ice_fraction"} + self._external_forcing_fme: list[str] = [] + for v in self._exogenous_forcing_fme: + if v not in _coupled_fields and v in self.lexicon.VOCAB_REVERSE: + self._external_forcing_fme.append(v) + + # Grid (same 1° Gaussian grid as ACE2ERA5) + self.lat = ACE_GRID_LAT + self.lon = ACE_GRID_LON + + logger.debug( + "SamudrACE initialized: {} atm prog, {} ocean prog, " + "{} atm out, {} ocean out, {} external forcing vars", + len(self._atm_prog_fme), + len(self._ocean_prog_fme), + len(self._atm_out_fme), + len(self._ocean_out_fme), + len(self._external_forcing_fme), + ) + + def input_coords(self) -> CoordSystem: + """Input coordinate system of the prognostic model. + + Returns + ------- + CoordSystem + Coordinate system dictionary + """ + return CoordSystem( + { + "batch": np.empty(0), + "time": np.empty(0), + "lead_time": np.array( + [np.timedelta64(0, "h")], dtype="timedelta64[ns]" + ), + "variable": np.array(self._prog_e2s, dtype=object), + "lat": self.lat, + "lon": self.lon, + } + ) + + @batch_coords() + def output_coords(self, input_coords: CoordSystem) -> CoordSystem: + """Output coordinate system of the prognostic model. + + Parameters + ---------- + input_coords : CoordSystem + Input coordinate system to transform into output_coords. + + Returns + ------- + CoordSystem + Coordinate system dictionary + """ + output_coords = OrderedDict( + { + "batch": np.empty(0), + "time": np.empty(0), + "lead_time": np.array([self._dt]), + "variable": np.array(self._all_out_e2s), + "lat": self.lat, + "lon": self.lon, + } + ) + if input_coords is None: + return output_coords + + test_coords = input_coords.copy() + test_coords["lead_time"] = ( + test_coords["lead_time"] - input_coords["lead_time"][0] + ) + target_input_coords = self.input_coords() + for i, key in enumerate(target_input_coords): + if key not in ["batch", "time"]: + handshake_dim(test_coords, key, i) + handshake_coords(test_coords, target_input_coords, key) + + output_coords["batch"] = input_coords["batch"] + output_coords["time"] = input_coords["time"] + output_coords["lead_time"] = ( + input_coords["lead_time"][0] + output_coords["lead_time"] + ) + return output_coords + + @classmethod + def load_default_package(cls) -> Package: + """Load default SamudrACE package from HuggingFace. + + Returns + ------- + Package + Model package + """ + return Package( + "hf://allenai/SamudrACE-CM4-piControl", + cache_options={ + "cache_storage": Package.default_cache("samudrace"), + "same_names": True, + }, + ) + + @classmethod + @check_optional_dependencies() + def load_model( + cls, + package: Package, + forcing_scenario: str = "0311", + dt: np.timedelta64 = np.timedelta64(6, "h"), + ) -> PrognosticModel: + """Load SamudrACE prognostic model from a package. + + Parameters + ---------- + package : Package + Package to load the model checkpoint from. + forcing_scenario : str, optional + Forcing scenario identifier. Must be one of ``"0151"`` or + ``"0311"``, by default ``"0311"``. The corresponding forcing + NetCDF file is downloaded from HuggingFace on first use and + cached locally. + dt : numpy.timedelta64, optional + Timestep for advancing lead time coordinates, by default 6 hours. + + Returns + ------- + PrognosticModel + SamudrACE prognostic model + """ + checkpoint_path = package.resolve("samudrACE_CM4_piControl_ckpt.tar") + logger.info("Loading SamudrACE coupled stepper from {}", checkpoint_path) + coupled_stepper = load_coupled_stepper(checkpoint_path) + return cls( + coupled_stepper=coupled_stepper, + forcing_scenario=forcing_scenario, + dt=dt, + ) + + def _build_batch_data( + self, + data_dict: dict[str, torch.Tensor], + time_array: np.ndarray, + n_batch: int, + ) -> BatchData: + """Construct an FME BatchData object from a variable dict and time info. + + Parameters + ---------- + data_dict : dict[str, torch.Tensor] + Mapping from FME variable names to tensors of shape + ``[n_batch, n_times, lat, lon]``. + time_array : np.ndarray + 1-D array of np.datetime64 timestamps of length ``n_times``. + n_batch : int + Batch size. + + Returns + ------- + BatchData + FME BatchData instance on device. + """ + times = np.stack([time_array] * n_batch, axis=0) + time_da = xr.DataArray(_npdatetime64_to_cftime(times), dims=["sample", "time"]) + return BatchData.new_on_device( + data=data_dict, + time=time_da, + horizontal_dims=["lat", "lon"], + ) + + def _tensor_to_component_states( + self, + x: torch.Tensor, + coords: CoordSystem, + ) -> tuple[PrognosticState, PrognosticState]: + """Convert Earth2Studio input tensor to atmosphere and ocean PrognosticStates. + + Parameters + ---------- + x : torch.Tensor + Input tensor of shape ``[batch, time, lead_time, variable, lat, lon]``. + coords : CoordSystem + Input coordinate system. + + Returns + ------- + tuple[PrognosticState, PrognosticState] + Atmosphere and ocean PrognosticState objects. + """ + b, t, lt, v, lat, lon = x.shape + x_flat = x.reshape(b * t, lt, v, lat, lon) + + var_list = list(coords["variable"]) + time_array = coords["time"] + coords["lead_time"] + + # Split atmosphere state + atm_data: dict[str, torch.Tensor] = {} + for fme_name in self._atm_prog_fme: + e2s_name = self.lexicon.get_e2s_from_fme(fme_name) + idx = var_list.index(e2s_name) + atm_data[fme_name] = x_flat[:, :, idx, ...] + + # Split ocean state + ocean_data: dict[str, torch.Tensor] = {} + for fme_name in self._ocean_prog_fme: + e2s_name = self.lexicon.get_e2s_from_fme(fme_name) + idx = var_list.index(e2s_name) + ocean_data[fme_name] = x_flat[:, :, idx, ...] + + atm_bd = self._build_batch_data(atm_data, time_array, b * t) + ocean_bd = self._build_batch_data(ocean_data, time_array, b * t) + + return PrognosticState(atm_bd), PrognosticState(ocean_bd) + + # HuggingFace repository for forcing data + _HF_REPO_ID = "allenai/SamudrACE-CM4-piControl" + + def _ensure_forcing_file(self) -> str: + """Download the forcing NetCDF from HuggingFace if not already cached. + + Returns + ------- + str + Local filesystem path to the cached forcing file. + """ + cache_dir = Package.default_cache("samudrace") + local_path = os.path.join( + cache_dir, + "forcing_data", + f"forcing_{self._forcing_scenario}.nc", + ) + if not os.path.exists(local_path): + os.makedirs(os.path.dirname(local_path), exist_ok=True) + hf_path = ( + f"{self._HF_REPO_ID}/forcing_data/forcing_{self._forcing_scenario}.nc" + ) + logger.info("Downloading SamudrACE forcing: {}", hf_path) + hf_fs = HfFileSystem() + hf_fs.get_file(hf_path, local_path) + return local_path + + def _open_forcing_ds(self) -> xr.Dataset: + """Lazily open the forcing NetCDF dataset (cached across calls).""" + if self._forcing_ds is None: + forcing_path = self._ensure_forcing_file() + self._forcing_ds = xr.open_dataset(forcing_path, engine="netcdf4") + return self._forcing_ds + + def _get_forcing_slice( + self, + fme_name: str, + month: int, + day: int, + hour: int, + n_flat: int, + lat_len: int, + lon_len: int, + ) -> torch.Tensor: + """Extract a single forcing field from the forcing NetCDF for a given time. + + Parameters + ---------- + fme_name : str + FME variable name. + month : int + Target month (1-12). + day : int + Target day (1-31). + hour : int + Target hour (0, 6, 12, 18). + n_flat : int + Flattened batch size. + lat_len : int + Latitude dimension size. + lon_len : int + Longitude dimension size. + + Returns + ------- + torch.Tensor + Forcing field of shape ``[n_flat, lat, lon]``. + """ + ds = self._open_forcing_ds() + da = ds[fme_name] + device = self.device_buffer.device + + if "time" in da.dims: + # Time-varying field (e.g. DSWRFtoa): match by month/day/hour + if not hasattr(self, "_forcing_time_index"): + cf_times = ds["time"].values + self._forcing_time_index: dict[tuple[int, int, int], int] = {} + for i, ct in enumerate(cf_times): + self._forcing_time_index[(ct.month, ct.day, ct.hour)] = i + key = (month, day, hour) + if key not in self._forcing_time_index: + raise ValueError( + f"No forcing data for month={month}, day={day}, hour={hour}. " + f"SamudrACE forcing uses a no-leap calendar at 6h resolution." + ) + idx = self._forcing_time_index[key] + vals = torch.as_tensor(da.values[idx], dtype=torch.float32, device=device) + else: + # Static field (e.g. HGTsfc, land_fraction) + vals = torch.as_tensor(da.values, dtype=torch.float32, device=device) + + # Broadcast to [n_flat, lat, lon] + if vals.ndim == 2: + vals = vals.unsqueeze(0).expand(n_flat, -1, -1) + return vals + + def _batch_data_to_tensor( + self, + data: dict[str, torch.Tensor], + var_names_fme: list[str], + ) -> torch.Tensor: + """Convert FME output dict to a stacked tensor. + + Parameters + ---------- + data : dict[str, torch.Tensor] + Dictionary mapping FME variable names to tensors. + var_names_fme : list[str] + Ordered list of variable names to stack. + + Returns + ------- + torch.Tensor + Stacked tensor of shape ``[batch, 1, 1, variable, lat, lon]`` + (the second singleton is the ``lead_time`` dimension). + """ + y_list = [data[name] for name in var_names_fme] + y = torch.stack(y_list, dim=2) + y = y.unsqueeze(2) + return y + + @torch.inference_mode() + def _forward( + self, + x: torch.Tensor, + coords: CoordSystem, + atm_state: PrognosticState, + ocean_state: PrognosticState, + atm_flux_accum: list[dict[str, torch.Tensor]], + step_in_cycle: int, + ) -> tuple[ + torch.Tensor, + CoordSystem, + PrognosticState, + PrognosticState, + list[dict[str, torch.Tensor]], + int, + ]: + """Run one 6h atmosphere step and optionally trigger ocean step. + + Parameters + ---------- + x : torch.Tensor + Input tensor. + coords : CoordSystem + Input coordinate system. + atm_state : PrognosticState + Current atmosphere prognostic state. + ocean_state : PrognosticState + Current ocean prognostic state. + atm_flux_accum : list[dict[str, torch.Tensor]] + Accumulated atmosphere flux outputs for ocean forcing. + step_in_cycle : int + Current step index within the coupled cycle (0..19). + + Returns + ------- + tuple + (output_tensor, output_coords, new_atm_state, new_ocean_state, + new_flux_accum, new_step_in_cycle) + """ + if len(coords["lead_time"]) != 1: + raise ValueError("SamudrACE forward expects exactly one lead_time entry.") + + b, t, _, _, lat_len, lon_len = x.shape + n_flat = b * t + + # Build atmosphere forcing: external data + ocean-sourced fields + lead_times = np.array( + [coords["lead_time"][0], coords["lead_time"][0] + self._dt] + ) + abs_times = [ + (coords["time"][0] + lt if len(coords["time"]) > 0 else lt) + for lt in lead_times + ] + time_array = np.array(abs_times) + + # Fetch external forcing for this single step (IC + 1 forward = 2 timesteps) + atm_forcing_data: dict[str, torch.Tensor] = {} + + if self._external_forcing_fme: + for fme_name in self._external_forcing_fme: + slices = [] + for abs_t in abs_times: + ts = pd.Timestamp(abs_t) + val = self._get_forcing_slice( + fme_name, ts.month, ts.day, ts.hour, n_flat, lat_len, lon_len + ) + slices.append(val) + atm_forcing_data[fme_name] = torch.stack(slices, dim=1) + + # Add ocean-sourced forcing: SST, ocean_fraction, sea_ice_fraction + # These are held constant for all inner atmosphere steps + ocean_bd = ocean_state.as_batch_data() + coupled_config = self.coupled_stepper._config + + # SST → atmosphere surface_temperature + sst_name = coupled_config.sst_name + if sst_name in ocean_bd.data: + sst_val = ocean_bd.data[sst_name][:, -1:, ...] # last timestep + atm_forcing_data["surface_temperature"] = sst_val.expand(-1, 2, -1, -1) + + # Sea ice fraction and ocean fraction — derived from ocean's + # ocean_sea_ice_fraction via the CoupledOceanFractionConfig when + # available, otherwise look for direct sea_ice_fraction/ocean_fraction. + ofp = coupled_config.ocean_fraction_prediction + if ofp is not None: + sic_name = ofp.sea_ice_fraction_name # e.g. "ocean_sea_ice_fraction" + land_name = ofp.land_fraction_name # e.g. "land_fraction" + atm_sic_name = ofp.sea_ice_fraction_name_in_atmosphere # "sea_ice_fraction" + + # Compute atmosphere-facing sea_ice and ocean_fraction from ocean + if sic_name in ocean_bd.data: + osic = ocean_bd.data[sic_name][:, -1:, ...] + # Get land fraction from atmosphere state + atm_bd_pre = atm_state.as_batch_data() + land_frac = ( + atm_bd_pre.data[land_name][:, -1:, ...] + if land_name in atm_bd_pre.data + else torch.zeros_like(osic) + ) + # sea_ice_fraction = ocean_sea_ice_fraction * (1 - land_fraction) + sic_atm = osic * (1.0 - land_frac) + atm_forcing_data[atm_sic_name] = sic_atm.expand(-1, 2, -1, -1) + # ocean_fraction = 1 - land_fraction - sea_ice_fraction + ocean_frac = 1.0 - land_frac - sic_atm + atm_forcing_data["ocean_fraction"] = ocean_frac.expand(-1, 2, -1, -1) + else: + if "sea_ice_fraction" in ocean_bd.data: + sic_val = ocean_bd.data["sea_ice_fraction"][:, -1:, ...] + atm_forcing_data["sea_ice_fraction"] = sic_val.expand(-1, 2, -1, -1) + + if "ocean_fraction" in ocean_bd.data: + of_val = ocean_bd.data["ocean_fraction"][:, -1:, ...] + atm_forcing_data["ocean_fraction"] = of_val.expand(-1, 2, -1, -1) + + # Fallback: static fields from atmosphere state if not already provided + # by the external data source above. + atm_bd = atm_state.as_batch_data() + for static_name in ["land_fraction", "lake_fraction", "HGTsfc"]: + if static_name not in atm_forcing_data and static_name in atm_bd.data: + static_val = atm_bd.data[static_name][:, -1:, ...] + atm_forcing_data[static_name] = static_val.expand(-1, 2, -1, -1) + + atm_forcing = self._build_batch_data(atm_forcing_data, time_array, n_flat) + + # Run atmosphere step + atm_paired, new_atm_state = self.coupled_stepper.atmosphere.predict_paired( + atm_state, atm_forcing + ) + + # Accumulate flux outputs for ocean forcing + new_flux_accum = list(atm_flux_accum) + flux_step: dict[str, torch.Tensor] = {} + for fme_name in self._ocean_forcing_fme: + if fme_name in atm_paired.prediction: + flux_step[fme_name] = atm_paired.prediction[fme_name][:, -1, ...] + if flux_step: + new_flux_accum.append(flux_step) + + new_step = step_in_cycle + 1 + new_ocean_state = ocean_state + + # At the end of a coupled cycle, run the ocean step + if new_step >= N_INNER_STEPS: + new_ocean_state = self._run_ocean_step( + new_ocean_state, new_atm_state, new_flux_accum, coords + ) + new_flux_accum = [] + new_step = 0 + + # Build output tensor: concatenate atmosphere + ocean outputs + atm_out = self._batch_data_to_tensor(atm_paired.prediction, self._atm_out_fme) + # For ocean: use latest ocean state (may have just been updated) + ocean_data = new_ocean_state.as_batch_data().data + ocean_out_dict: dict[str, torch.Tensor] = {} + for fme_name in self._ocean_out_fme: + if fme_name in ocean_data: + ocean_out_dict[fme_name] = ocean_data[fme_name][:, -1:, ...] + else: + ocean_out_dict[fme_name] = torch.full( + (n_flat, 1, lat_len, lon_len), + float("nan"), + device=self.device_buffer.device, + ) + ocean_out = self._batch_data_to_tensor(ocean_out_dict, self._ocean_out_fme) + + # Concatenate along variable dimension + y = torch.cat([atm_out, ocean_out], dim=3) + # Reshape back: [b*t, 1, 1, var, lat, lon] -> [b, t, 1, var, lat, lon] + y = y.reshape(b, t, 1, len(self._all_out_e2s), lat_len, lon_len) + + out_coords = self.output_coords(coords) + return y, out_coords, new_atm_state, new_ocean_state, new_flux_accum, new_step + + def _run_ocean_step( + self, + ocean_state: PrognosticState, + atm_state: PrognosticState, + flux_accum: list[dict[str, torch.Tensor]], + coords: CoordSystem, + ) -> PrognosticState: + """Run a single ocean step using time-averaged atmosphere fluxes. + + Parameters + ---------- + ocean_state : PrognosticState + Current ocean state. + atm_state : PrognosticState + Current atmosphere state (used for static fields like land_fraction). + flux_accum : list[dict[str, torch.Tensor]] + List of atmosphere flux dicts, one per inner atmosphere step. + coords : CoordSystem + Current coordinate system. + + Returns + ------- + PrognosticState + Updated ocean state after 5-day step. + """ + if not flux_accum: + return ocean_state + + # Time-average the accumulated atmosphere fluxes + avg_forcing: dict[str, torch.Tensor] = {} + for key in flux_accum[0]: + stacked = torch.stack([f[key] for f in flux_accum], dim=1) + avg_forcing[key] = stacked.mean(dim=1, keepdim=True) + + # Ocean expects 2 timesteps: IC + 1 forward step + # Expand forcing to 2 timesteps (IC has NaN, forward step has averaged flux) + ocean_forcing_data: dict[str, torch.Tensor] = {} + n_flat = list(avg_forcing.values())[0].shape[0] + for key, val in avg_forcing.items(): + nan_pad = torch.full_like(val, float("nan")) + ocean_forcing_data[key] = torch.cat([nan_pad, val], dim=1) + + # Add static fields if needed (land_fraction from atmosphere state) + atm_bd = atm_state.as_batch_data() + if "land_fraction" in atm_bd.data: + lf_val = atm_bd.data["land_fraction"][:, -1:, ...] + ocean_forcing_data["land_fraction"] = lf_val.expand(-1, 2, -1, -1) + + # Build time array for ocean forcing (2 timesteps spanning the 5-day window) + ocean_dt = np.timedelta64(5, "D") + time_array = np.array( + ( + [ + coords["time"][0] + coords["lead_time"][0], + coords["time"][0] + coords["lead_time"][0] + ocean_dt, + ] + if len(coords["time"]) > 0 + else [coords["lead_time"][0], coords["lead_time"][0] + ocean_dt] + ), + ) + + ocean_forcing = self._build_batch_data(ocean_forcing_data, time_array, n_flat) + + _, new_ocean_state = self.coupled_stepper.ocean.predict_paired( + ocean_state, ocean_forcing + ) + return new_ocean_state + + def _build_initial_output( + self, x: torch.Tensor, coords: CoordSystem + ) -> tuple[torch.Tensor, CoordSystem]: + """Construct initial-condition output tensor matching model output schema. + + Parameters + ---------- + x : torch.Tensor + Input tensor. + coords : CoordSystem + Input coordinate system. + + Returns + ------- + tuple[torch.Tensor, CoordSystem] + Initial condition output tensor and coordinate system. + """ + ic_coords = coords.copy() + ic_coords["variable"] = np.array(self._all_out_e2s, dtype=object) + + b, t, _, _, lat_len, lon_len = x.shape + v_out = len(self._all_out_e2s) + y0 = torch.full( + (b, t, 1, v_out, lat_len, lon_len), + float("nan"), + device=x.device, + dtype=x.dtype, + ) + + # Copy prognostic variables from input to output + var_to_idx_out = {v: i for i, v in enumerate(self._all_out_e2s)} + var_to_idx_in = {v: i for i, v in enumerate(self._prog_e2s)} + for v in self._prog_e2s: + if v in var_to_idx_out: + y0[:, :, 0, var_to_idx_out[v], ...] = x[:, :, 0, var_to_idx_in[v], ...] + + return y0, ic_coords + + @batch_func() + def __call__( + self, x: torch.Tensor, coords: CoordSystem + ) -> tuple[torch.Tensor, CoordSystem]: + """Runs one prognostic step (6h atmosphere) using FME CoupledStepper. + + Parameters + ---------- + x : torch.Tensor + Input tensor. + coords : CoordSystem + Input coordinate system. + + Returns + ------- + tuple[torch.Tensor, CoordSystem] + Output tensor and coordinate system 6 hours in the future. + """ + x = x.to(self.device_buffer.device) + + # Initialize component states from input tensor + atm_state, ocean_state = self._tensor_to_component_states(x, coords) + + y, out_coords, _, _, _, _ = self._forward( + x, coords, atm_state, ocean_state, [], 0 + ) + return y, out_coords + + @batch_func() + def _default_generator( + self, x: torch.Tensor, coords: CoordSystem + ) -> Generator[tuple[torch.Tensor, CoordSystem], None, None]: + """Generator to perform coupled time-integration of SamudrACE. + + Parameters + ---------- + x : torch.Tensor + Input tensor. + coords : CoordSystem + Input coordinate system. + + Yields + ------ + tuple[torch.Tensor, CoordSystem] + Output tensor and coordinate system at each 6h time step. + """ + coords = coords.copy() + x = x.to(self.device_buffer.device) + + # Yield initial condition + ic_tensor, ic_coords = self._build_initial_output(x, coords) + yield ic_tensor, ic_coords + + # Initialize component states + atm_state, ocean_state = self._tensor_to_component_states(x, coords) + atm_flux_accum: list[dict[str, torch.Tensor]] = [] + step_in_cycle = 0 + + while True: + x, coords = self.front_hook(x, coords) + + ( + out, + out_coords, + atm_state, + ocean_state, + atm_flux_accum, + step_in_cycle, + ) = self._forward( + x, coords, atm_state, ocean_state, atm_flux_accum, step_in_cycle + ) + + out, out_coords = self.rear_hook(out, out_coords) + yield out, out_coords.copy() + + # Update x with latest prognostic variables from output + x_next = x.clone() + var_to_idx_out = {v: i for i, v in enumerate(self._all_out_e2s)} + var_to_idx_in = {v: i for i, v in enumerate(self._prog_e2s)} + for v in self._prog_e2s: + if v in var_to_idx_out: + x_next[:, :, 0, var_to_idx_in[v], ...] = out[ + :, :, 0, var_to_idx_out[v], ... + ] + x = x_next + + coords = coords.copy() + coords["lead_time"] = coords["lead_time"] + self._dt + + def create_iterator( + self, x: torch.Tensor, coords: CoordSystem + ) -> Iterator[tuple[torch.Tensor, CoordSystem]]: + """Creates an iterator for time-integration of SamudrACE. + + Parameters + ---------- + x : torch.Tensor + Input tensor. + coords : CoordSystem + Input coordinate system. + + Yields + ------ + tuple[torch.Tensor, CoordSystem] + Predicted state and coordinates at each 6h time step. + """ + yield from self._default_generator(x, coords) diff --git a/pyproject.toml b/pyproject.toml index 0a40fbadf..faac98eb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -187,6 +187,11 @@ pangu = [ "onnxscript", "onnxruntime-gpu>=1.21.0", ] +samudrace = [ + "fme>=2025.10.0", + "pandas>=2.3.2", + "scipy>=1.15.2", +] sfno = [ "makani", "pynvml>=12.0.0", @@ -281,6 +286,22 @@ conflicts = [ [ { extra = "ace2" }, { extra = "sfno" }, + ], + [ + { extra = "samudrace" }, + { extra = "atlas" }, + ], + [ + { extra = "samudrace" }, + { extra = "fcn3" }, + ], + [ + { extra = "samudrace" }, + { extra = "perturbation" }, + ], + [ + { extra = "samudrace" }, + { extra = "sfno" }, ] ] default-groups = ["dev", "build"] diff --git a/test/models/px/test_samudrace.py b/test/models/px/test_samudrace.py new file mode 100644 index 000000000..820c2d606 --- /dev/null +++ b/test/models/px/test_samudrace.py @@ -0,0 +1,343 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from collections.abc import Iterable + +import numpy as np +import pytest +import torch +import xarray as xr + +from earth2studio.data import Random, fetch_data +from earth2studio.data.ace2 import ACE_GRID_LAT, ACE_GRID_LON +from earth2studio.models.px.samudrace import SamudrACE +from earth2studio.utils import handshake_dim + +pytest.importorskip("fme") + +# Atmosphere variable lists matching SamudrACE coupled config +ATM_PROGNOSTIC = sorted( + ["PRESsfc", "surface_temperature", "TMP2m", "Q2m", "UGRD10m", "VGRD10m"] + + [f"air_temperature_{k}" for k in range(8)] + + [f"specific_total_water_{k}" for k in range(8)] + + [f"eastward_wind_{k}" for k in range(8)] + + [f"northward_wind_{k}" for k in range(8)] +) + +ATM_INPUT_ONLY = sorted( + [ + "DSWRFtoa", + "HGTsfc", + "lake_fraction", + "land_fraction", + "ocean_fraction", + "sea_ice_fraction", + ] +) + +ATM_OUT = ATM_PROGNOSTIC + [ + "LHTFLsfc", + "SHTFLsfc", + "PRATEsfc", + "ULWRFsfc", + "ULWRFtoa", + "DLWRFsfc", + "DSWRFsfc", + "USWRFsfc", + "USWRFtoa", + "tendency_of_total_water_path_due_to_advection", + "eastward_surface_wind_stress", + "northward_surface_wind_stress", + "TMP850", + "h500", +] + +OCEAN_PROGNOSTIC = sorted( + ["sst", "zos", "HI", "ocean_sea_ice_fraction"] + + [f"thetao_{d}" for d in range(19)] + + [f"so_{d}" for d in range(19)] + + [f"uo_{d}" for d in range(19)] + + [f"vo_{d}" for d in range(19)] +) + +OCEAN_INPUT_ONLY = sorted( + [ + "DLWRFsfc", + "DSWRFsfc", + "ULWRFsfc", + "USWRFsfc", + "LHTFLsfc", + "SHTFLsfc", + "PRATEsfc", + "eastward_surface_wind_stress", + "northward_surface_wind_stress", + "land_fraction", + ] +) + +OCEAN_OUT = OCEAN_PROGNOSTIC + +# External forcing variables that the wrapper reads from the forcing file +# (everything in ATM_INPUT_ONLY that is not coupled or from ocean output) +_EXTERNAL_FORCING = ["DSWRFtoa", "HGTsfc", "lake_fraction", "land_fraction"] + + +class PhooOutput: + """Mock output from predict_paired.""" + + prediction: dict = {} + + +class PhooStepper(torch.nn.Module): + """Mock single-component stepper matching the FME Stepper interface.""" + + def __init__( + self, + prognostic_names: list, + input_only_names: list, + out_names: list, + ): + super().__init__() + self.prognostic_names = prognostic_names + self._input_only_names = input_only_names + self.out_names = out_names + self.register_buffer("device_buffer", torch.empty(0)) + + def predict_paired(self, ic, forcing_batch): + first_key = self.prognostic_names[0] + batch, _, lat, lon = ic._data.data[first_key].shape + device = self.device_buffer.device + output = PhooOutput() + output.prediction = { + key: torch.randn(batch, 1, lat, lon, device=device) + for key in self.out_names + } + # Return updated state as PrognosticState for ocean updates + import cftime + from fme.ace.data_loading.batch_data import BatchData, PrognosticState + + state_data = { + key: torch.randn(batch, 1, lat, lon, device=device) + for key in self.prognostic_names + } + + time_da = xr.DataArray( + np.array( + [ + [cftime.DatetimeProlepticGregorian(2001, 1, 1, 0, 0, 0)] + for _ in range(batch) + ], + dtype=object, + ), + dims=["sample", "time"], + ) + bd = BatchData.new_on_device( + data=state_data, time=time_da, horizontal_dims=["lat", "lon"] + ) + return output, PrognosticState(bd) + + +class PhooCoupledOceanFractionConfig: + """Mock ocean fraction prediction config.""" + + sea_ice_fraction_name = "ocean_sea_ice_fraction" + land_fraction_name = "land_fraction" + sea_ice_fraction_name_in_atmosphere = "sea_ice_fraction" + + +class PhooCoupledConfig: + """Mock coupled stepper config.""" + + sst_name = "sst" + ocean_fraction_prediction = PhooCoupledOceanFractionConfig() + + +class PhooCoupledStepper: + """Mock CoupledStepper matching the interface used by SamudrACE wrapper.""" + + def __init__(self): + self.atmosphere = PhooStepper(ATM_PROGNOSTIC, ATM_INPUT_ONLY, ATM_OUT) + self.ocean = PhooStepper(OCEAN_PROGNOSTIC, OCEAN_INPUT_ONLY, OCEAN_OUT) + self._config = PhooCoupledConfig() + + def to(self, device): + self.atmosphere = self.atmosphere.to(device) + self.ocean = self.ocean.to(device) + return self + + +@pytest.fixture(scope="module") +def dummy_forcing_ds(tmp_path_factory): + """Create a minimal forcing xarray Dataset for mock tests. + + Contains DSWRFtoa (time-varying, 3 days of 6h steps) plus static fields + HGTsfc, land_fraction, and lake_fraction. + """ + n_lat = len(ACE_GRID_LAT) + n_lon = len(ACE_GRID_LON) + # 12 time steps covering 3 days at 6h cadence + import cftime + + times = [ + cftime.DatetimeNoLeap(2001, 1, d + 1, h) + for d in range(3) + for h in (0, 6, 12, 18) + ] + + ds = xr.Dataset() + ds["time"] = xr.DataArray(times, dims=["time"]) + ds["lat"] = xr.DataArray(ACE_GRID_LAT, dims=["lat"]) + ds["lon"] = xr.DataArray(ACE_GRID_LON, dims=["lon"]) + + # Time-varying field + ds["DSWRFtoa"] = xr.DataArray( + np.random.randn(len(times), n_lat, n_lon).astype(np.float32), + dims=["time", "lat", "lon"], + ) + # Static fields + for name in ("HGTsfc", "land_fraction", "lake_fraction"): + ds[name] = xr.DataArray( + np.random.randn(n_lat, n_lon).astype(np.float32), + dims=["lat", "lon"], + ) + + return ds + + +@pytest.mark.parametrize("device", ["cuda:0"]) +def test_samudrace_call(dummy_forcing_ds, device): + torch.cuda.empty_cache() + time = np.array([np.datetime64("2001-01-01T00:00")]) + + coupled = PhooCoupledStepper().to(device) + p = SamudrACE(coupled).to(device) + # Inject dummy forcing dataset to bypass HuggingFace download + p._forcing_ds = dummy_forcing_ds + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + r = Random(dc) + + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + out, out_coords = p(x, coords) + + if not isinstance(time, Iterable): + time = [time] + + assert out.shape[0] == len(time) + assert out.shape[1] == 1 + assert out.shape[3] == len(p.lat) + assert out.shape[4] == len(p.lon) + assert (out_coords["variable"] == p.output_coords(coords)["variable"]).all() + assert (out_coords["time"] == time).all() + handshake_dim(out_coords, "lon", 4) + handshake_dim(out_coords, "lat", 3) + handshake_dim(out_coords, "variable", 2) + handshake_dim(out_coords, "lead_time", 1) + handshake_dim(out_coords, "time", 0) + np.testing.assert_array_equal(out_coords["lat"], ACE_GRID_LAT) + np.testing.assert_array_equal(out_coords["lon"], ACE_GRID_LON) + + +@pytest.mark.parametrize("batch", [1, 2]) +@pytest.mark.parametrize("device", ["cuda:0"]) +def test_samudrace_iter(dummy_forcing_ds, batch, device): + torch.cuda.empty_cache() + time = np.array([np.datetime64("2001-01-01T00:00")]) + + coupled = PhooCoupledStepper().to(device) + p = SamudrACE(coupled).to(device) + # Inject dummy forcing dataset to bypass HuggingFace download + p._forcing_ds = dummy_forcing_ds + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + r = Random(dc) + + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + x = x.unsqueeze(0).repeat(batch, 1, 1, 1, 1, 1) + coords.update({"batch": np.arange(batch)}) + coords.move_to_end("batch", last=False) + + p_iter = p.create_iterator(x, coords) + + # First yield returns IC + out, out_coords = next(p_iter) + assert len(out.shape) == 6 + assert out.shape[0] == batch + assert out_coords["lead_time"][0] == np.timedelta64(0, "h") + + for i, (out, out_coords) in enumerate(p_iter): + assert len(out.shape) == 6 + assert (out_coords["variable"] == p.output_coords(coords)["variable"]).all() + assert (out_coords["batch"] == np.arange(batch)).all() + assert (out_coords["time"] == time).all() + assert out_coords["lead_time"][0] == np.timedelta64(6 * (i + 1), "h") + np.testing.assert_array_equal(out_coords["lat"], ACE_GRID_LAT) + np.testing.assert_array_equal(out_coords["lon"], ACE_GRID_LON) + if i > 2: + break + + +@pytest.mark.package +@pytest.mark.parametrize("device", ["cuda:0"]) +def test_samudrace_package(device): + torch.cuda.empty_cache() + model = SamudrACE.load_model(SamudrACE.load_default_package()) + + time = np.array([np.datetime64("2001-01-01T00:00")]) + + p = model.to(device) + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + r = Random(dc) + + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + out, out_coords = p(x, coords) + + if not isinstance(time, Iterable): + time = [time] + + assert out.shape[0] == len(time) + assert out.shape[1] == 1 + assert out.shape[3] == len(p.lat) + assert out.shape[4] == len(p.lon) + assert (out_coords["variable"] == p.output_coords(coords)["variable"]).all() + assert (out_coords["time"] == time).all() + handshake_dim(out_coords, "lon", 4) + handshake_dim(out_coords, "lat", 3) + handshake_dim(out_coords, "variable", 2) + handshake_dim(out_coords, "lead_time", 1) + handshake_dim(out_coords, "time", 0) diff --git a/tox.ini b/tox.ini index 10d4ce3e3..a65fd334a 100644 --- a/tox.ini +++ b/tox.ini @@ -116,7 +116,7 @@ commands = [testenv:test-px-models-ace2] runner = uv-venv-lock-runner description = Run tests for px models with conflicts -extras = ace2 +extras = ace2,samudrace commands = pytest {posargs:-s --cov --cov-append --slow --package --testmon} \ - test/models/px/test_ace2.py + test/models/px/test_ace2.py test/models/px/test_samudrace.py diff --git a/uv.lock b/uv.lock index 67585fa8b..222c0356b 100644 --- a/uv.lock +++ b/uv.lock @@ -6,18 +6,18 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version < '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'", @@ -39,6 +39,18 @@ conflicts = [[ ], [ { package = "earth2studio", extra = "ace2" }, { package = "earth2studio", extra = "sfno" }, +], [ + { package = "earth2studio", extra = "atlas" }, + { package = "earth2studio", extra = "samudrace" }, +], [ + { package = "earth2studio", extra = "fcn3" }, + { package = "earth2studio", extra = "samudrace" }, +], [ + { package = "earth2studio", extra = "perturbation" }, + { package = "earth2studio", extra = "samudrace" }, +], [ + { package = "earth2studio", extra = "samudrace" }, + { package = "earth2studio", extra = "sfno" }, ]] [[package]] @@ -224,7 +236,7 @@ version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -317,7 +329,7 @@ version = "4.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } wheels = [ @@ -520,7 +532,7 @@ dependencies = [ { name = "pandas" }, { name = "pillow" }, { name = "pyyaml" }, - { name = "tornado", marker = "sys_platform != 'emscripten' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tornado", marker = "sys_platform != 'emscripten' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "xyzservices" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e4/31/7ee0c4dfd0255631b0624ce01be178704f91f763f02a1879368eb109befd/bokeh-3.8.2.tar.gz", hash = "sha256:8e7dcacc21d53905581b54328ad2705954f72f2997f99fc332c1de8da53aa3cc", size = 6529251, upload-time = "2026-01-06T00:20:06.568Z" } @@ -620,26 +632,26 @@ name = "cbottle" version = "2025.5.1" source = { git = "https://github.com/NVlabs/cBottle.git?rev=8b8b358466e6b2f50d1779009790002ceb596e72#8b8b358466e6b2f50d1779009790002ceb596e72" } dependencies = [ - { name = "cartopy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "cftime", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "earth2grid", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "h5netcdf", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "matplotlib", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "netcdf4", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-physicsnemo", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pandas", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "psutil", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "python-dotenv", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "s3fs", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "scipy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "tensorboard", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "torch", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "torchmetrics", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "tqdm", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "xarray", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "zarr", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "zict", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cartopy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cftime", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "earth2grid", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "h5netcdf", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "matplotlib", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "netcdf4", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-physicsnemo", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pandas", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "psutil", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "python-dotenv", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "s3fs", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "scipy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tensorboard", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "torch", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "torchmetrics", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tqdm", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "xarray", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "zarr", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "zict", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] [[package]] @@ -670,7 +682,7 @@ name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pycparser", marker = "implementation_name != 'PyPy' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ @@ -895,7 +907,7 @@ name = "click" version = "8.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } wheels = [ @@ -907,7 +919,7 @@ name = "click-plugins" version = "1.1.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "click", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c3/a4/34847b59150da33690a36da3681d6bbc2ec14ee9a846bc30a6746e5984e4/click_plugins-1.1.1.2.tar.gz", hash = "sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261", size = 8343, upload-time = "2025-06-25T00:47:37.555Z" } wheels = [ @@ -1136,7 +1148,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version <= '3.11' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tomli", marker = "python_full_version <= '3.11' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] [[package]] @@ -1157,7 +1169,7 @@ name = "cryptography" version = "46.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cffi", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } wheels = [ @@ -1228,30 +1240,30 @@ sdist = { url = "https://files.pythonhosted.org/packages/a9/0a/376c8aeb76daf82d4 [[package]] name = "cuda-bindings" -version = "12.9.5" +version = "12.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cuda-pathfinder" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/91/6c/a90efb9e83c3830f10236c51b56b436e0b78efba79364659037dc93cdbbc/cuda_bindings-12.9.5-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14dcc3a4b7bc50a7bec0e98a815b7cc36a0cfeafa20152e484c3a05068209da5", size = 15619944, upload-time = "2025-12-18T16:30:56.452Z" }, - { url = "https://files.pythonhosted.org/packages/34/4a/f323d52849e4a85ea7ebbff0625c9c6297e35f0e91ce5e2d1cff4731bd1b/cuda_bindings-12.9.5-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:819f38fe6f3f8ea28f772e61c2583dd10152ee81051a970a291b7f916973729e", size = 16149366, upload-time = "2025-12-18T16:30:58.942Z" }, - { url = "https://files.pythonhosted.org/packages/c6/07/41122c3073267645b5481f03b98d3de47848798967f64b51f25428e9d564/cuda_bindings-12.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:6427fd9fef4c8cc171fbf9eb74763faeddc1fa3899882c269ff7f9b12e03b965", size = 15376641, upload-time = "2025-12-18T16:31:00.983Z" }, - { url = "https://files.pythonhosted.org/packages/07/83/1720946a56090a004f375617fb2df61185a413daa779e8bb4bda313be9e3/cuda_bindings-12.9.5-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92f21accf6fcdea7998b2ee1bbed71e2a156737624c46dc9bc3b51a1c55bda88", size = 15400554, upload-time = "2025-12-18T16:31:03.599Z" }, - { url = "https://files.pythonhosted.org/packages/10/5c/dd3cac662aad06e5b8661749b403cb6dc8359506a79e387ffc497cd25902/cuda_bindings-12.9.5-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5218388042d3415fba74030600fa25d59e3ec4183c344f227d43df52ca53f408", size = 15918529, upload-time = "2025-12-18T16:31:06.25Z" }, - { url = "https://files.pythonhosted.org/packages/33/88/b9fb610955af5a79108744dd75cd921484b43da6b151988d889180a5ad16/cuda_bindings-12.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:ee42798f639920d30292a1649b24388526067463f73a8469feeba1570121ce2d", size = 15399440, upload-time = "2025-12-18T16:31:08.894Z" }, - { url = "https://files.pythonhosted.org/packages/dc/7a/fb65f880eb30ebf1bc648933ba4d4d37adbaf502bbede724d442a9512aca/cuda_bindings-12.9.5-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e06d272b25149e1a83b446ff3dbefcf6f82f66865c49e8d9db75683bbcff0b5f", size = 15269227, upload-time = "2025-12-18T16:31:10.952Z" }, - { url = "https://files.pythonhosted.org/packages/68/b7/19ff68738d7397bdd58b5feb8385d5fbe14903ce9b60b3e772a5f25ea0ec/cuda_bindings-12.9.5-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da37458f8c5074d59040deddbd005460c0cf70d1ef90dd7d2c816e4686038e87", size = 15752484, upload-time = "2025-12-18T16:31:13.251Z" }, - { url = "https://files.pythonhosted.org/packages/c7/7c/ee0e24167501e37fddb09a386f7ba7a7f377bf5adb3399277ff20185f26c/cuda_bindings-12.9.5-cp313-cp313-win_amd64.whl", hash = "sha256:5b9401e3bcd5d3a3c90cbb759e2cf6b8a446789b8dd6e452de9530e50b93683f", size = 15363723, upload-time = "2025-12-18T16:31:15.305Z" }, - { url = "https://files.pythonhosted.org/packages/e2/ca/c4551ae51a133ca1e44fe3fedc6b2607d50fa8690f096cfd6c254bcf40c5/cuda_bindings-12.9.5-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3fb96c3d99f58ee5b3072bf1b40c215f4207481cc8b5f15b1a6c628eeb40cae", size = 15228703, upload-time = "2025-12-18T16:31:17.492Z" }, - { url = "https://files.pythonhosted.org/packages/4f/17/5c5063639de93a27ba67fd9c12f7663014010b1fb50990399c923cafa8d3/cuda_bindings-12.9.5-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5f5ee48922d723c626549b5644f69adcbf7537499a42963cc39d328319ff44ed", size = 15709656, upload-time = "2025-12-18T16:31:20.056Z" }, - { url = "https://files.pythonhosted.org/packages/91/3d/72ae9c90aac0071e92bcbcb976b8fc3531dd74c4799dbbdc739a8b671b74/cuda_bindings-12.9.5-cp313-cp313t-win_amd64.whl", hash = "sha256:dbe330129380cc01a1a8f23894ae39c52e9fedc4b7db8ed69ac5f8ac48d55084", size = 15759852, upload-time = "2025-12-18T16:31:22.454Z" }, - { url = "https://files.pythonhosted.org/packages/27/cb/eed7d79086adbb5f1ea96445170544f80ab1bd0d5b5e8f62823cfa054c90/cuda_bindings-12.9.5-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b3a89fccd6cc1ec535a940b43243761537ae573d977c3cd18e38f841e1f8a86", size = 15352988, upload-time = "2025-12-18T16:31:24.924Z" }, - { url = "https://files.pythonhosted.org/packages/94/4c/6d2e59c2321efe9f219ba5eb5063a61facfe527655fe3ad7bdaafda1da1a/cuda_bindings-12.9.5-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40dc79c8cbf663e24d2607b2a979787e0d6840b624a4da48cd5303acb8482ad2", size = 15789364, upload-time = "2025-12-18T16:31:27.1Z" }, - { url = "https://files.pythonhosted.org/packages/25/b0/21d9247995c9d34d7cb2c23bc50aa3ee6f4fbf92eb3a0d09be9223e221a0/cuda_bindings-12.9.5-cp314-cp314-win_amd64.whl", hash = "sha256:5faab6be8fc097076eabe591e084c7c743d6d4222ef15f42008122cdd5ca31e1", size = 15534026, upload-time = "2025-12-18T16:31:29.176Z" }, - { url = "https://files.pythonhosted.org/packages/13/10/0d4980c6b9b7caffaa0e553378ce363f03e8e4b933c505c5117b26f8c067/cuda_bindings-12.9.5-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a82dd5c30d9ef0956ddc9ae84e27ea027576633161de8646b00e7189d4f0a39", size = 15262883, upload-time = "2025-12-18T16:31:31.58Z" }, - { url = "https://files.pythonhosted.org/packages/ed/9f/582ee268a5ebb96a643c29c69354b0c2d9634cd98deda1c5bd4abe4f61c8/cuda_bindings-12.9.5-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:77964179bc62504dc6bdba745bd594652233ec7796af8adce10edc0dfaf1ed95", size = 15740980, upload-time = "2025-12-18T16:31:33.972Z" }, - { url = "https://files.pythonhosted.org/packages/a3/44/aab452c0a531a2c26e546745e0bba3047a7a30185620beeb68ed89a78f6d/cuda_bindings-12.9.5-cp314-cp314t-win_amd64.whl", hash = "sha256:ec376bfd8b07931f72bebed5e558c9bdae3a85473a6a1d5783ef3483a22fe86c", size = 16195220, upload-time = "2025-12-18T16:31:36.087Z" }, + { url = "https://files.pythonhosted.org/packages/a9/2b/ebcbb60aa6dba830474cd360c42e10282f7a343c0a1f58d24fbd3b7c2d77/cuda_bindings-12.9.4-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6a429dc6c13148ff1e27c44f40a3dd23203823e637b87fd0854205195988306", size = 11840604, upload-time = "2025-10-21T14:51:34.565Z" }, + { url = "https://files.pythonhosted.org/packages/45/e7/b47792cc2d01c7e1d37c32402182524774dadd2d26339bd224e0e913832e/cuda_bindings-12.9.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c912a3d9e6b6651853eed8eed96d6800d69c08e94052c292fec3f282c5a817c9", size = 12210593, upload-time = "2025-10-21T14:51:36.574Z" }, + { url = "https://files.pythonhosted.org/packages/dd/be/90d32049e06abcfba4b2e7df1dbcb5e16215c8852eef0cd8b25f38a66bd4/cuda_bindings-12.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:443b0875916879c2e4c3722941e25e42d5ab9bcbf34c9e83404fb100fa1f6913", size = 11490933, upload-time = "2025-10-21T14:51:38.792Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c2/65bfd79292b8ff18be4dd7f7442cea37bcbc1a228c1886f1dea515c45b67/cuda_bindings-12.9.4-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:694ba35023846625ef471257e6b5a4bc8af690f961d197d77d34b1d1db393f56", size = 11760260, upload-time = "2025-10-21T14:51:40.79Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c1/dabe88f52c3e3760d861401bb994df08f672ec893b8f7592dc91626adcf3/cuda_bindings-12.9.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fda147a344e8eaeca0c6ff113d2851ffca8f7dfc0a6c932374ee5c47caa649c8", size = 12151019, upload-time = "2025-10-21T14:51:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/df/6b/9c1b1a6c01392bfdd758e9486f52a1a72bc8f49e98f9355774ef98b5fb4e/cuda_bindings-12.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:696ca75d249ddf287d01b9a698b8e2d8a05046495a9c051ca15659dc52d17615", size = 11586961, upload-time = "2025-10-21T14:51:45.394Z" }, + { url = "https://files.pythonhosted.org/packages/05/8b/b4b2d1c7775fa403b64333e720cfcfccef8dcb9cdeb99947061ca5a77628/cuda_bindings-12.9.4-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf8bfaedc238f3b115d957d1fd6562b7e8435ba57f6d0e2f87d0e7149ccb2da5", size = 11570071, upload-time = "2025-10-21T14:51:47.472Z" }, + { url = "https://files.pythonhosted.org/packages/63/56/e465c31dc9111be3441a9ba7df1941fe98f4aa6e71e8788a3fb4534ce24d/cuda_bindings-12.9.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:32bdc5a76906be4c61eb98f546a6786c5773a881f3b166486449b5d141e4a39f", size = 11906628, upload-time = "2025-10-21T14:51:49.905Z" }, + { url = "https://files.pythonhosted.org/packages/05/d0/d0e4e2e047d8e899f023fa15ad5e9894ce951253f4c894f1cd68490fdb14/cuda_bindings-12.9.4-cp313-cp313-win_amd64.whl", hash = "sha256:a2e82c8985948f953c2be51df45c3fe11c812a928fca525154fb9503190b3e64", size = 11556719, upload-time = "2025-10-21T14:51:52.248Z" }, + { url = "https://files.pythonhosted.org/packages/ec/07/6aff13bc1e977e35aaa6b22f52b172e2890c608c6db22438cf7ed2bf43a6/cuda_bindings-12.9.4-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3adf4958dcf68ae7801a59b73fb00a8b37f8d0595060d66ceae111b1002de38d", size = 11566797, upload-time = "2025-10-21T14:51:54.581Z" }, + { url = "https://files.pythonhosted.org/packages/a3/84/1e6be415e37478070aeeee5884c2022713c1ecc735e6d82d744de0252eee/cuda_bindings-12.9.4-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56e0043c457a99ac473ddc926fe0dc4046694d99caef633e92601ab52cbe17eb", size = 11925991, upload-time = "2025-10-21T14:51:56.535Z" }, + { url = "https://files.pythonhosted.org/packages/4d/3c/972edfddb4ae8a9fccd3c3766ed47453b6f805b6026b32f10209dd4b8ad4/cuda_bindings-12.9.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b32d8b685f0e66f5658bcf4601ef034e89fc2843582886f0a58784a4302da06c", size = 11894363, upload-time = "2025-10-21T14:51:58.633Z" }, + { url = "https://files.pythonhosted.org/packages/1e/b5/96a6696e20c4ffd2b327f54c7d0fde2259bdb998d045c25d5dedbbe30290/cuda_bindings-12.9.4-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f53a7f453d4b2643d8663d036bafe29b5ba89eb904c133180f295df6dc151e5", size = 11624530, upload-time = "2025-10-21T14:52:01.539Z" }, + { url = "https://files.pythonhosted.org/packages/d1/af/6dfd8f2ed90b1d4719bc053ff8940e494640fe4212dc3dd72f383e4992da/cuda_bindings-12.9.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8b72ee72a9cc1b531db31eebaaee5c69a8ec3500e32c6933f2d3b15297b53686", size = 11922703, upload-time = "2025-10-21T14:52:03.585Z" }, + { url = "https://files.pythonhosted.org/packages/e6/87/652796522cc1a7af559460e1ce59b642e05c1468b9c08522a9a096b4cf04/cuda_bindings-12.9.4-cp314-cp314-win_amd64.whl", hash = "sha256:53a10c71fdbdb743e0268d07964e5a996dd00b4e43831cbfce9804515d97d575", size = 11517716, upload-time = "2025-10-21T14:52:06.013Z" }, + { url = "https://files.pythonhosted.org/packages/39/73/d2fc40c043bac699c3880bf88d3cebe9d88410cd043795382826c93a89f0/cuda_bindings-12.9.4-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20f2699d61d724de3eb3f3369d57e2b245f93085cab44fd37c3bea036cea1a6f", size = 11565056, upload-time = "2025-10-21T14:52:08.338Z" }, + { url = "https://files.pythonhosted.org/packages/6c/19/90ac264acc00f6df8a49378eedec9fd2db3061bf9263bf9f39fd3d8377c3/cuda_bindings-12.9.4-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d80bffc357df9988dca279734bc9674c3934a654cab10cadeed27ce17d8635ee", size = 11924658, upload-time = "2025-10-21T14:52:10.411Z" }, + { url = "https://files.pythonhosted.org/packages/ab/52/a30f46e822bfa6b4a659d1e8de8c4a4adf908ea075dac568b55362541bd8/cuda_bindings-12.9.4-cp314-cp314t-win_amd64.whl", hash = "sha256:53e11991a92ff6f26a0c8a98554cd5d6721c308a6b7bfb08bebac9201e039e43", size = 12055608, upload-time = "2025-10-21T14:52:12.335Z" }, ] [[package]] @@ -1289,13 +1301,13 @@ wheels = [ [[package]] name = "cuda-python" -version = "12.9.5" +version = "12.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cuda-bindings" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/02/ce79a804a2d6ee7dc2d1637b75b7c3f01eb90a796915d4d3a1ac42e2d6e6/cuda_python-12.9.5-py3-none-any.whl", hash = "sha256:6fbbb3be2ab617d8269ad83e5fe9d748b1da4c5e0f79257a3296408a70766b39", size = 7596, upload-time = "2025-12-18T16:45:15.973Z" }, + { url = "https://files.pythonhosted.org/packages/af/f3/6b032a554019cfb3447e671798c1bd3e79b5f1af20d10253f56cea269ef2/cuda_python-12.9.4-py3-none-any.whl", hash = "sha256:d2cacea882a69863f1e7d27ee71d75f0684f4c76910aff839067e4f89c902279", size = 7594, upload-time = "2025-10-21T14:55:12.846Z" }, ] [[package]] @@ -1308,10 +1320,10 @@ wheels = [ [package.optional-dependencies] nvcc = [ - { name = "nvidia-cuda-nvcc-cu12", marker = "sys_platform == 'linux' or sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-nvcc-cu12", marker = "sys_platform == 'linux' or sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] nvrtc = [ - { name = "nvidia-cuda-nvrtc-cu12", marker = "sys_platform == 'linux' or sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-nvrtc-cu12", marker = "sys_platform == 'linux' or sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] [[package]] @@ -1331,7 +1343,7 @@ dependencies = [ { name = "nvtx" }, { name = "packaging" }, { name = "pandas" }, - { name = "pyarrow", marker = "platform_machine == 'aarch64' or platform_machine == 'x86_64' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyarrow", marker = "platform_machine == 'aarch64' or platform_machine == 'x86_64' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "pylibcudf-cu12" }, { name = "rich" }, { name = "rmm-cu12" }, @@ -1392,7 +1404,7 @@ dependencies = [ { name = "click" }, { name = "cloudpickle" }, { name = "fsspec" }, - { name = "importlib-metadata", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "importlib-metadata", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "packaging" }, { name = "partd" }, { name = "pyyaml" }, @@ -1573,7 +1585,7 @@ wheels = [ [[package]] name = "earth2grid" -version = "2025.11.1+torch29" +version = "2025.11.1+torch210" source = { git = "https://github.com/NVlabs/earth2grid.git?rev=11dcf1b0787a7eb6a8497a3a5a5e1fdcc31232d3#11dcf1b0787a7eb6a8497a3a5a5e1fdcc31232d3" } dependencies = [ { name = "einops" }, @@ -1628,7 +1640,7 @@ aifsens = [ all = [ { name = "aiofiles" }, { name = "anemoi-models" }, - { name = "cbottle", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cbottle", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "cdsapi" }, { name = "cfgrib" }, { name = "cucim-cu12" }, @@ -1651,8 +1663,8 @@ all = [ { name = "httpx" }, { name = "hydra-core" }, { name = "importlib-metadata" }, - { name = "intake-esgf", version = "2025.10.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "intake-esgf", version = "2026.1.26", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "intake-esgf", version = "2025.10.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "intake-esgf", version = "2026.1.26", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "jax", extra = ["cuda12"] }, { name = "makani" }, { name = "microsoft-aurora" }, @@ -1674,19 +1686,19 @@ all = [ { name = "pystac-client" }, { name = "python-dotenv" }, { name = "python-multipart" }, - { name = "rasterio", version = "1.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rasterio", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rasterio", version = "1.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rasterio", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "redis" }, { name = "requests" }, - { name = "rioxarray", version = "0.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rioxarray", version = "0.20.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rioxarray", version = "0.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rioxarray", version = "0.20.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "rq" }, { name = "ruamel-yaml" }, { name = "scikit-image" }, { name = "scipy" }, { name = "timm" }, - { name = "torch-harmonics", version = "0.8.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-12-earth2studio-ace2'" }, - { name = "torch-harmonics", version = "0.8.1", source = { git = "https://github.com/NVIDIA/torch-harmonics.git?rev=a632ca748a12bd9f74dbc1e00653317810991f74#a632ca748a12bd9f74dbc1e00653317810991f74" }, marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno' or extra != 'extra-12-earth2studio-ace2'" }, + { name = "torch-harmonics", version = "0.8.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-12-earth2studio-ace2' or extra == 'extra-12-earth2studio-samudrace' or (extra != 'extra-12-earth2studio-atlas' and extra != 'extra-12-earth2studio-fcn3' and extra != 'extra-12-earth2studio-perturbation' and extra != 'extra-12-earth2studio-sfno')" }, + { name = "torch-harmonics", version = "0.8.1", source = { git = "https://github.com/NVIDIA/torch-harmonics.git?rev=a632ca748a12bd9f74dbc1e00653317810991f74#a632ca748a12bd9f74dbc1e00653317810991f74" }, marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno'" }, { name = "types-redis" }, { name = "urllib3" }, { name = "uvicorn", extra = ["standard"] }, @@ -1702,7 +1714,7 @@ aurora = [ { name = "microsoft-aurora" }, ] cbottle = [ - { name = "cbottle", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cbottle", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "earth2grid" }, ] corrdiff = [ @@ -1744,17 +1756,17 @@ data = [ { name = "ecmwf-opendata" }, { name = "globus-sdk" }, { name = "httpx" }, - { name = "intake-esgf", version = "2025.10.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "intake-esgf", version = "2026.1.26", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "intake-esgf", version = "2025.10.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "intake-esgf", version = "2026.1.26", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "multi-storage-client", extra = ["boto3", "fsspec", "google-cloud-storage"] }, { name = "pandas" }, { name = "planetary-computer" }, { name = "pyproj" }, { name = "pystac-client" }, - { name = "rasterio", version = "1.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rasterio", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rioxarray", version = "0.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rioxarray", version = "0.20.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rasterio", version = "1.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rasterio", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rioxarray", version = "0.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rioxarray", version = "0.20.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "scipy" }, ] dlesym = [ @@ -1819,6 +1831,11 @@ precip-afno = [ precip-afno-v2 = [ { name = "nvidia-physicsnemo" }, ] +samudrace = [ + { name = "fme" }, + { name = "pandas" }, + { name = "scipy" }, +] serve = [ { name = "aiofiles" }, { name = "fastapi" }, @@ -1906,10 +1923,10 @@ docs = [ { name = "myst-parser" }, { name = "nvidia-sphinx-theme" }, { name = "scipy" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx-autodoc-typehints", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx-autodoc-typehints", version = "3.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx-autodoc-typehints", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx-autodoc-typehints", version = "3.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "sphinx-badges" }, { name = "sphinx-design" }, { name = "sphinx-favicon" }, @@ -1980,6 +1997,7 @@ requires-dist = [ { name = "flax", marker = "extra == 'gencast'", specifier = ">=0.10.6" }, { name = "flax", marker = "extra == 'graphcast'", specifier = ">=0.10.6" }, { name = "fme", marker = "extra == 'ace2'", git = "https://github.com/ai2cm/ace.git?rev=e211cad3e1a5cff0fa84e8d2f0ee67042eff3d4d" }, + { name = "fme", marker = "extra == 'samudrace'", git = "https://github.com/ai2cm/ace.git?rev=e211cad3e1a5cff0fa84e8d2f0ee67042eff3d4d" }, { name = "fsspec", specifier = ">=2024.2.0" }, { name = "gcsfs" }, { name = "globus-sdk", marker = "extra == 'all'", specifier = "<4.0.0" }, @@ -2066,6 +2084,7 @@ requires-dist = [ { name = "pandas", marker = "extra == 'ace2'", specifier = ">=2.3.2" }, { name = "pandas", marker = "extra == 'all'", specifier = "<3.0" }, { name = "pandas", marker = "extra == 'data'", specifier = "<3.0" }, + { name = "pandas", marker = "extra == 'samudrace'", specifier = ">=2.3.2" }, { name = "planetary-computer", marker = "extra == 'all'", specifier = ">=0.5.0" }, { name = "planetary-computer", marker = "extra == 'data'", specifier = ">=0.5.0" }, { name = "prometheus-client", marker = "extra == 'all'", specifier = ">=0.17.0" }, @@ -2113,6 +2132,7 @@ requires-dist = [ { name = "scipy", marker = "extra == 'data'", specifier = ">=1.15.2" }, { name = "scipy", marker = "extra == 'fcn3'", specifier = ">=1.10.0" }, { name = "scipy", marker = "extra == 'perturbation'", specifier = ">=1.15.2" }, + { name = "scipy", marker = "extra == 'samudrace'", specifier = ">=1.15.2" }, { name = "scipy", marker = "extra == 'sfno'", specifier = ">=1.10.0" }, { name = "scipy", marker = "extra == 'stormcast'", specifier = ">=1.15.2" }, { name = "scipy", marker = "extra == 'stormscope'", specifier = ">=1.15.2" }, @@ -2137,7 +2157,7 @@ requires-dist = [ { name = "xarray", extras = ["parallel"], specifier = ">=2023.1.0" }, { name = "zarr", specifier = ">=3.1.0" }, ] -provides-extras = ["ace2", "aifs", "aifsens", "all", "atlas", "aurora", "cbottle", "climatenet", "corrdiff", "cyclone", "da-healda", "da-interp", "da-stormcast", "data", "derived", "dlesym", "dlwp", "fcn", "fcn3", "fengwu", "fuxi", "gencast", "graphcast", "interp-modafno", "pangu", "perturbation", "precip-afno", "precip-afno-v2", "serve", "sfno", "solarradiation-afno", "statistics", "stormcast", "stormscope", "utils", "windgust-afno"] +provides-extras = ["ace2", "aifs", "aifsens", "all", "atlas", "aurora", "cbottle", "climatenet", "corrdiff", "cyclone", "da-healda", "da-interp", "da-stormcast", "data", "derived", "dlesym", "dlwp", "fcn", "fcn3", "fengwu", "fuxi", "gencast", "graphcast", "interp-modafno", "pangu", "perturbation", "precip-afno", "precip-afno-v2", "samudrace", "serve", "sfno", "solarradiation-afno", "statistics", "stormcast", "stormscope", "utils", "windgust-afno"] [package.metadata.requires-dev] build = [ @@ -2513,7 +2533,7 @@ dependencies = [ { name = "tensorly-torch" }, { name = "torch" }, { name = "torch-harmonics", version = "0.8.0", source = { registry = "https://pypi.org/simple" } }, - { name = "wandb", extra = ["media"], marker = "extra == 'extra-12-earth2studio-ace2'" }, + { name = "wandb", extra = ["media"], marker = "extra == 'extra-12-earth2studio-ace2' or extra == 'extra-12-earth2studio-samudrace' or (extra != 'extra-12-earth2studio-atlas' and extra != 'extra-12-earth2studio-fcn3' and extra != 'extra-12-earth2studio-perturbation' and extra != 'extra-12-earth2studio-sfno')" }, { name = "xarray" }, { name = "zarr" }, ] @@ -3067,7 +3087,7 @@ name = "hatch" version = "1.16.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "backports-zstd", marker = "python_full_version < '3.14' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "backports-zstd", marker = "python_full_version < '3.14' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "click" }, { name = "hatchling" }, { name = "httpx" }, @@ -3279,7 +3299,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "fsspec" }, - { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "httpx" }, { name = "packaging" }, { name = "pyyaml" }, @@ -3425,16 +3445,16 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "dask", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "globus-sdk", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "netcdf4", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pandas", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pystac-client", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pyyaml", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "requests", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "requests-cache", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "tqdm", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "xarray", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "dask", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "globus-sdk", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "netcdf4", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pandas", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pystac-client", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyyaml", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "requests", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "requests-cache", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tqdm", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "xarray", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5d/31/22fdaecbac3e8830d3ecf47fb3516ff940ccb160447e6376e42c49d91a82/intake_esgf-2025.10.22.tar.gz", hash = "sha256:dcbb091612b1cd9168ae93b6ce6ab585cf3e1b9eefd47fe9d36954ced856311d", size = 97011, upload-time = "2025-10-22T17:58:04.992Z" } wheels = [ @@ -3450,32 +3470,32 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "dask", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "globus-sdk", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "netcdf4", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pandas", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pystac-client", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pyyaml", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "requests", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "requests-cache", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "tqdm", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "xarray", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "dask", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "globus-sdk", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "netcdf4", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pandas", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pystac-client", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyyaml", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "requests", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "requests-cache", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tqdm", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "xarray", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/13/6f99d94d2522a55646edb8e3e0c9bf14474bd04403fc15465ab0d7137ec5/intake_esgf-2026.1.26.tar.gz", hash = "sha256:0ae6257104e4f307bb28f675d1ad703b7cdaa10e74b5b3a77e6949aee72c9890", size = 98904, upload-time = "2026-01-26T17:13:23.789Z" } wheels = [ @@ -3524,7 +3544,7 @@ name = "jaraco-context" version = "6.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "backports-tarfile", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "backports-tarfile", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cb/9c/a788f5bb29c61e456b8ee52ce76dbdd32fd72cd73dd67bc95f42c7a8d13c/jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f", size = 15850, upload-time = "2026-01-13T02:53:53.847Z" } wheels = [ @@ -3598,18 +3618,18 @@ wheels = [ [package.optional-dependencies] with-cuda = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-cupti-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-nvcc-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-nvrtc-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-runtime-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cudnn-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cufft-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cusolver-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nccl-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nvshmem-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-cupti-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-nvcc-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-nvrtc-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-runtime-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cudnn-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cufft-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cusolver-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nccl-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvshmem-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] [[package]] @@ -3784,13 +3804,13 @@ name = "keyring" version = "25.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "importlib-metadata", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "jaraco-classes" }, { name = "jaraco-context" }, { name = "jaraco-functools" }, - { name = "jeepney", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pywin32-ctypes", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "secretstorage", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "jeepney", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "secretstorage", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } wheels = [ @@ -4021,8 +4041,8 @@ name = "lightning-utilities" version = "0.15.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "typing-extensions", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "typing-extensions", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f1/45/7fa8f56b17dc0f0a41ec70dd307ecd6787254483549843bef4c30ab5adce/lightning_utilities-0.15.3.tar.gz", hash = "sha256:792ae0204c79f6859721ac7f386c237a33b0ed06ba775009cb894e010a842033", size = 33553, upload-time = "2026-02-22T14:48:53.348Z" } wheels = [ @@ -4066,8 +4086,8 @@ name = "loguru" version = "0.7.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "win32-setctime", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "win32-setctime", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" } wheels = [ @@ -4135,8 +4155,8 @@ dependencies = [ { name = "pillow" }, { name = "ruamel-yaml" }, { name = "torch" }, - { name = "torch-harmonics", version = "0.8.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-12-earth2studio-ace2'" }, - { name = "torch-harmonics", version = "0.8.1", source = { git = "https://github.com/NVIDIA/torch-harmonics.git?rev=a632ca748a12bd9f74dbc1e00653317810991f74#a632ca748a12bd9f74dbc1e00653317810991f74" }, marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno' or extra != 'extra-12-earth2studio-ace2'" }, + { name = "torch-harmonics", version = "0.8.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-12-earth2studio-ace2' or extra == 'extra-12-earth2studio-samudrace' or (extra != 'extra-12-earth2studio-atlas' and extra != 'extra-12-earth2studio-fcn3' and extra != 'extra-12-earth2studio-perturbation' and extra != 'extra-12-earth2studio-sfno')" }, + { name = "torch-harmonics", version = "0.8.1", source = { git = "https://github.com/NVIDIA/torch-harmonics.git?rev=a632ca748a12bd9f74dbc1e00653317810991f74#a632ca748a12bd9f74dbc1e00653317810991f74" }, marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno'" }, { name = "tqdm" }, { name = "wandb" }, ] @@ -4663,7 +4683,7 @@ name = "mypy" version = "1.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "librt", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "librt", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, @@ -4716,8 +4736,8 @@ dependencies = [ { name = "markdown-it-py" }, { name = "mdit-py-plugins" }, { name = "pyyaml" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/fa/7b45eef11b7971f0beb29d27b7bfe0d747d063aa29e170d9edd004733c8a/myst_parser-5.0.0.tar.gz", hash = "sha256:f6f231452c56e8baa662cc352c548158f6a16fcbd6e3800fc594978002b94f3a", size = 98535, upload-time = "2026-01-15T09:08:18.036Z" } wheels = [ @@ -5047,7 +5067,7 @@ name = "nvidia-cudnn-cu12" version = "9.10.2.21" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cublas-cu12" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/fa/41/e79269ce215c857c935fd86bcfe91a451a584dfc27f1e068f568b9ad1ab7/nvidia_cudnn_cu12-9.10.2.21-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:c9132cc3f8958447b4910a1720036d9eff5928cc3179b0a51fb6d167c6cc87d8", size = 705026878, upload-time = "2025-06-06T21:52:51.348Z" }, @@ -5060,7 +5080,7 @@ name = "nvidia-cufft-cu12" version = "11.3.3.83" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvjitlink-cu12" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/60/bc/7771846d3a0272026c416fbb7e5f4c1f146d6d80704534d0b187dd6f4800/nvidia_cufft_cu12-11.3.3.83-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:848ef7224d6305cdb2a4df928759dca7b1201874787083b6e7550dd6765ce69a", size = 193109211, upload-time = "2025-03-07T01:44:56.873Z" }, @@ -5092,9 +5112,9 @@ name = "nvidia-cusolver-cu12" version = "11.7.3.90" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cublas-cu12" }, + { name = "nvidia-cusparse-cu12" }, + { name = "nvidia-nvjitlink-cu12" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/c8/32/f7cd6ce8a7690544d084ea21c26e910a97e077c9b7f07bf5de623ee19981/nvidia_cusolver_cu12-11.7.3.90-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:db9ed69dbef9715071232caa9b69c52ac7de3a95773c2db65bdba85916e4e5c0", size = 267229841, upload-time = "2025-03-07T01:46:54.356Z" }, @@ -5107,7 +5127,7 @@ name = "nvidia-cusparse-cu12" version = "12.5.8.93" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvjitlink-cu12" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/bc/f7/cd777c4109681367721b00a106f491e0d0d15cfa1fd59672ce580ce42a97/nvidia_cusparse_cu12-12.5.8.93-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9b6c161cb130be1a07a27ea6923df8141f3c295852f4b260c65f18f3e0a091dc", size = 288117129, upload-time = "2025-03-07T01:47:40.407Z" }, @@ -5175,11 +5195,11 @@ wheels = [ [[package]] name = "nvidia-nvshmem-cu12" -version = "3.3.20" +version = "3.4.5" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/92/9d/3dd98852568fb845ec1f7902c90a22b240fe1cbabda411ccedf2fd737b7b/nvidia_nvshmem_cu12-3.3.20-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b0b960da3842212758e4fa4696b94f129090b30e5122fea3c5345916545cff0", size = 124484616, upload-time = "2025-08-04T20:24:59.172Z" }, - { url = "https://files.pythonhosted.org/packages/3b/6c/99acb2f9eb85c29fc6f3a7ac4dccfd992e22666dd08a642b303311326a97/nvidia_nvshmem_cu12-3.3.20-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d00f26d3f9b2e3c3065be895e3059d6479ea5c638a3f38c9fec49b1b9dd7c1e5", size = 124657145, upload-time = "2025-08-04T20:25:19.995Z" }, + { url = "https://files.pythonhosted.org/packages/1d/6a/03aa43cc9bd3ad91553a88b5f6fb25ed6a3752ae86ce2180221962bc2aa5/nvidia_nvshmem_cu12-3.4.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b48363fc6964dede448029434c6abed6c5e37f823cb43c3bcde7ecfc0457e15", size = 138936938, upload-time = "2025-09-06T00:32:05.589Z" }, + { url = "https://files.pythonhosted.org/packages/b5/09/6ea3ea725f82e1e76684f0708bbedd871fc96da89945adeba65c3835a64c/nvidia_nvshmem_cu12-3.4.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:042f2500f24c021db8a06c5eec2539027d57460e1c1a762055a6554f72c369bd", size = 139103095, upload-time = "2025-09-06T00:32:31.266Z" }, ] [[package]] @@ -5231,8 +5251,8 @@ version = "0.0.9.post1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydata-sphinx-theme" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/8c/79/017fab2f7167a9a9795665f894d04f77aafceca80821b51589bb4b23ff5c/nvidia_sphinx_theme-0.0.9.post1-py3-none-any.whl", hash = "sha256:21ca60206dff2f380d7783d64bbaf71a5b9cacae53c7d0686f089c16b5a3d45a", size = 143816, upload-time = "2025-11-09T23:16:55.719Z" }, @@ -6193,8 +6213,8 @@ dependencies = [ { name = "beautifulsoup4" }, { name = "docutils" }, { name = "pygments" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/00/20/bb50f9de3a6de69e6abd6b087b52fa2418a0418b19597601605f855ad044/pydata_sphinx_theme-0.16.1.tar.gz", hash = "sha256:a08b7f0b7f70387219dc659bff0893a7554d5eb39b59d3b8ef37b8401b7642d7", size = 2412693, upload-time = "2024-12-17T10:53:39.537Z" } @@ -6427,7 +6447,7 @@ name = "pytest" version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, @@ -6444,7 +6464,7 @@ version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } wheels = [ @@ -6645,14 +6665,14 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "affine", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "attrs", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "certifi", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "click", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "click-plugins", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "cligj", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "numpy", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pyparsing", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "affine", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "attrs", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "certifi", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "click", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "click-plugins", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cligj", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyparsing", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ec/fa/fce8dc9f09e5bc6520b6fc1b4ecfa510af9ca06eb42ad7bdff9c9b8989d0/rasterio-1.4.4.tar.gz", hash = "sha256:c95424e2c7f009b8f7df1095d645c52895cd332c0c2e1b4c2e073ea28b930320", size = 445004, upload-time = "2025-12-12T18:01:08.971Z" } wheels = [ @@ -6703,29 +6723,29 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "affine", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "attrs", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "certifi", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "click", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "cligj", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pyparsing", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "affine", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "attrs", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "certifi", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "click", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cligj", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyparsing", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f6/88/edb4b66b6cb2c13f123af5a3896bf70c0cbe73ab3cd4243cb4eb0212a0f6/rasterio-1.5.0.tar.gz", hash = "sha256:1e0ea56b02eea4989b36edf8e58a5a3ef40e1b7edcb04def2603accd5ab3ee7b", size = 452184, upload-time = "2026-01-05T16:06:47.169Z" } wheels = [ @@ -6793,7 +6813,7 @@ name = "redis" version = "7.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "async-timeout", marker = "python_full_version < '3.11.3' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "async-timeout", marker = "python_full_version < '3.11.3' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/32/6fac13a11e73e1bc67a2ae821a72bfe4c2d8c4c48f0267e4a952be0f1bae/redis-7.2.0.tar.gz", hash = "sha256:4dd5bf4bd4ae80510267f14185a15cba2a38666b941aff68cccf0256b51c1f26", size = 4901247, upload-time = "2026-02-16T17:16:22.797Z" } wheels = [ @@ -6807,7 +6827,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } wheels = [ @@ -6885,11 +6905,11 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "numpy", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "packaging", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pyproj", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rasterio", version = "1.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "xarray", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyproj", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rasterio", version = "1.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "xarray", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3d/8e/fe4e87460f8c62d8d5c683e09f19fbde5d9cfcfd0342d02df1f452999b5d/rioxarray-0.19.0.tar.gz", hash = "sha256:7819a0036fd874c8c8e280447cbbe43d8dc72fc4a14ac7852a665b1bdb7d4b04", size = 54600, upload-time = "2025-04-21T17:46:54.183Z" } wheels = [ @@ -6905,27 +6925,27 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pyproj", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "rasterio", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "xarray", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pyproj", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "rasterio", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "xarray", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5c/ad/d9f7a6d197a44a2c8f53174bdea919b7df3c70ef5c14a13702888516609a/rioxarray-0.20.0.tar.gz", hash = "sha256:8bfc7e979edc7e30b4671d638a9be0e5a7d673dab2ea88e2445d3c7745599c02", size = 55038, upload-time = "2025-10-24T18:14:41.924Z" } wheels = [ @@ -7351,8 +7371,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "jeepney", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "cryptography", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "jeepney", marker = "sys_platform == 'linux' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ @@ -7574,23 +7594,23 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "alabaster", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "babel", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "colorama", marker = "(python_full_version < '3.12' and sys_platform == 'win32') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "docutils", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "imagesize", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "jinja2", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "packaging", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pygments", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "requests", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "roman-numerals", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "snowballstemmer", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "alabaster", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "babel", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "(python_full_version < '3.12' and sys_platform == 'win32') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (python_full_version >= '3.12' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "docutils", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "imagesize", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "jinja2", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pygments", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "requests", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "roman-numerals", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "snowballstemmer", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-applehelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-devhelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-htmlhelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-jsmath", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-qthelp", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } wheels = [ @@ -7606,39 +7626,39 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "alabaster", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "babel", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "colorama", marker = "(python_full_version >= '3.12' and sys_platform == 'win32') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "docutils", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "imagesize", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "jinja2", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pygments", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "requests", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "roman-numerals", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "snowballstemmer", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "alabaster", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "babel", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "(python_full_version >= '3.12' and sys_platform == 'win32') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (python_full_version < '3.12' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'win32' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "docutils", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "imagesize", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "jinja2", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pygments", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "requests", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "roman-numerals", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "snowballstemmer", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cd/bd/f08eb0f4eed5c83f1ba2a3bd18f7745a2b1525fad70660a1c00224ec468a/sphinx-9.1.0.tar.gz", hash = "sha256:7741722357dd75f8190766926071fed3bdc211c74dd2d7d4df5404da95930ddb", size = 8718324, upload-time = "2025-12-31T15:09:27.646Z" } wheels = [ @@ -7658,7 +7678,7 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1d/f6/bdd93582b2aaad2cfe9eb5695a44883c8bc44572dd3c351a947acbb13789/sphinx_autodoc_typehints-3.6.1.tar.gz", hash = "sha256:fa0b686ae1b85965116c88260e5e4b82faec3687c2e94d6a10f9b36c3743e2fe", size = 37563, upload-time = "2026-01-02T15:23:46.543Z" } wheels = [ @@ -7674,23 +7694,23 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/54/319628e24e98102e6f73cf6e5f345324a94d9adc18d456193b84f2ac1608/sphinx_autodoc_typehints-3.7.0.tar.gz", hash = "sha256:f7c536f4c0a729324cfebfaa3787c80ca14d08817952153e6da4e971c5306c20", size = 41344, upload-time = "2026-02-23T20:54:58.529Z" } wheels = [ @@ -7702,8 +7722,8 @@ name = "sphinx-badges" version = "0.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/23/7f/5e47edaa1b67e7206814e1259ee81c0f285678a4f8f13e4f2a45a76b8639/sphinx_badges-0.1.6.tar.gz", hash = "sha256:1e66f84d6a24e10d6205e796c1eb1a8cf05d35c7412bd58cc43b3a1199cb8b7c", size = 98458, upload-time = "2026-03-24T02:15:54.417Z" } wheels = [ @@ -7715,8 +7735,8 @@ name = "sphinx-design" version = "0.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/13/7b/804f311da4663a4aecc6cf7abd83443f3d4ded970826d0c958edc77d4527/sphinx_design-0.7.0.tar.gz", hash = "sha256:d2a3f5b19c24b916adb52f97c5f00efab4009ca337812001109084a740ec9b7a", size = 2203582, upload-time = "2026-01-19T13:12:53.297Z" } wheels = [ @@ -7730,8 +7750,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "imagesize" }, { name = "requests" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2c/26/e7ca2321e6286d6ed6a2e824a0ee35ae660ec9a45a4719e33a627ce9e4d2/sphinx_favicon-1.1.0.tar.gz", hash = "sha256:6f65939fc2a6ac4259c88b09169f0b72681cd4c03dd1d0cf91c57a1fa314e50b", size = 8744, upload-time = "2026-02-12T20:55:41.294Z" } wheels = [ @@ -7744,8 +7764,8 @@ version = "0.20.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pillow" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5f/14/9238ac61932299b38c20c7c37dbfe60348c0348ea4d400f9ef25875b3bf7/sphinx_gallery-0.20.0.tar.gz", hash = "sha256:70281510c6183d812d3595957005ccf555c5a793f207410f6cd16a25bf08d735", size = 473502, upload-time = "2025-12-02T15:51:37.277Z" } wheels = [ @@ -7759,8 +7779,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, { name = "setuptools" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "wheel" }, ] sdist = { url = "https://files.pythonhosted.org/packages/89/6b/19def5241b45a7ae90fd91052bb91fa7b8fbcc0606a0cf65ac4ea70fb93b/sphinx_togglebutton-0.4.4.tar.gz", hash = "sha256:04c332692fd5f5363ad02a001e693369767d6c1f0e58279770a2aeb571b472a1", size = 17883, upload-time = "2026-01-14T14:33:11.599Z" } @@ -7828,7 +7848,7 @@ version = "0.52.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } wheels = [ @@ -7870,16 +7890,16 @@ name = "tensorboard" version = "2.20.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "absl-py", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "grpcio", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "markdown", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "pillow", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "protobuf", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "setuptools", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "tensorboard-data-server", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "werkzeug", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "absl-py", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "grpcio", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "markdown", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "pillow", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "protobuf", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "setuptools", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "tensorboard-data-server", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "werkzeug", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl", hash = "sha256:9dc9f978cb84c0723acf9a345d96c184f0293d18f166bb8d59ee098e6cfaaba6", size = 5525680, upload-time = "2025-07-17T19:20:49.638Z" }, @@ -7903,7 +7923,7 @@ dependencies = [ { name = "cloudpickle" }, { name = "importlib-metadata" }, { name = "numpy" }, - { name = "orjson", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "orjson", marker = "python_full_version < '3.13' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "packaging" }, { name = "pyvers" }, { name = "torch" }, @@ -8126,58 +8146,68 @@ wheels = [ [[package]] name = "torch" -version = "2.9.1" +version = "2.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "cuda-bindings", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "filelock" }, { name = "fsspec" }, { name = "jinja2" }, { name = "networkx" }, - { name = "nvidia-cublas-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-cupti-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-nvrtc-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cuda-runtime-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cudnn-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cufft-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cufile-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-curand-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cusolver-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cusparse-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-cusparselt-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nccl-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nvjitlink-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nvshmem-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "nvidia-nvtx-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "setuptools", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cublas-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-cupti-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-nvrtc-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cuda-runtime-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cudnn-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cufft-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cufile-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-curand-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cusolver-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cusparse-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-cusparselt-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nccl-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvjitlink-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvshmem-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "nvidia-nvtx-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "setuptools", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "sympy" }, - { name = "triton", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "triton", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_machine != 'x86_64' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform != 'linux' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "typing-extensions" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/15/db/c064112ac0089af3d2f7a2b5bfbabf4aa407a78b74f87889e524b91c5402/torch-2.9.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:62b3fd888277946918cba4478cf849303da5359f0fb4e3bfb86b0533ba2eaf8d", size = 104220430, upload-time = "2025-11-12T15:20:31.705Z" }, - { url = "https://files.pythonhosted.org/packages/56/be/76eaa36c9cd032d3b01b001e2c5a05943df75f26211f68fae79e62f87734/torch-2.9.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d033ff0ac3f5400df862a51bdde9bad83561f3739ea0046e68f5401ebfa67c1b", size = 899821446, upload-time = "2025-11-12T15:20:15.544Z" }, - { url = "https://files.pythonhosted.org/packages/47/cc/7a2949e38dfe3244c4df21f0e1c27bce8aedd6c604a587dd44fc21017cb4/torch-2.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:0d06b30a9207b7c3516a9e0102114024755a07045f0c1d2f2a56b1819ac06bcb", size = 110973074, upload-time = "2025-11-12T15:21:39.958Z" }, - { url = "https://files.pythonhosted.org/packages/1e/ce/7d251155a783fb2c1bb6837b2b7023c622a2070a0a72726ca1df47e7ea34/torch-2.9.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:52347912d868653e1528b47cafaf79b285b98be3f4f35d5955389b1b95224475", size = 74463887, upload-time = "2025-11-12T15:20:36.611Z" }, - { url = "https://files.pythonhosted.org/packages/0f/27/07c645c7673e73e53ded71705045d6cb5bae94c4b021b03aa8d03eee90ab/torch-2.9.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:da5f6f4d7f4940a173e5572791af238cb0b9e21b1aab592bd8b26da4c99f1cd6", size = 104126592, upload-time = "2025-11-12T15:20:41.62Z" }, - { url = "https://files.pythonhosted.org/packages/19/17/e377a460603132b00760511299fceba4102bd95db1a0ee788da21298ccff/torch-2.9.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:27331cd902fb4322252657f3902adf1c4f6acad9dcad81d8df3ae14c7c4f07c4", size = 899742281, upload-time = "2025-11-12T15:22:17.602Z" }, - { url = "https://files.pythonhosted.org/packages/b1/1a/64f5769025db846a82567fa5b7d21dba4558a7234ee631712ee4771c436c/torch-2.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:81a285002d7b8cfd3fdf1b98aa8df138d41f1a8334fd9ea37511517cedf43083", size = 110940568, upload-time = "2025-11-12T15:21:18.689Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ab/07739fd776618e5882661d04c43f5b5586323e2f6a2d7d84aac20d8f20bd/torch-2.9.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:c0d25d1d8e531b8343bea0ed811d5d528958f1dcbd37e7245bc686273177ad7e", size = 74479191, upload-time = "2025-11-12T15:21:25.816Z" }, - { url = "https://files.pythonhosted.org/packages/20/60/8fc5e828d050bddfab469b3fe78e5ab9a7e53dda9c3bdc6a43d17ce99e63/torch-2.9.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c29455d2b910b98738131990394da3e50eea8291dfeb4b12de71ecf1fdeb21cb", size = 104135743, upload-time = "2025-11-12T15:21:34.936Z" }, - { url = "https://files.pythonhosted.org/packages/f2/b7/6d3f80e6918213babddb2a37b46dbb14c15b14c5f473e347869a51f40e1f/torch-2.9.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:524de44cd13931208ba2c4bde9ec7741fd4ae6bfd06409a604fc32f6520c2bc9", size = 899749493, upload-time = "2025-11-12T15:24:36.356Z" }, - { url = "https://files.pythonhosted.org/packages/a6/47/c7843d69d6de8938c1cbb1eba426b1d48ddf375f101473d3e31a5fc52b74/torch-2.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:545844cc16b3f91e08ce3b40e9c2d77012dd33a48d505aed34b7740ed627a1b2", size = 110944162, upload-time = "2025-11-12T15:21:53.151Z" }, - { url = "https://files.pythonhosted.org/packages/28/0e/2a37247957e72c12151b33a01e4df651d9d155dd74d8cfcbfad15a79b44a/torch-2.9.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5be4bf7496f1e3ffb1dd44b672adb1ac3f081f204c5ca81eba6442f5f634df8e", size = 74830751, upload-time = "2025-11-12T15:21:43.792Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f7/7a18745edcd7b9ca2381aa03353647bca8aace91683c4975f19ac233809d/torch-2.9.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:30a3e170a84894f3652434b56d59a64a2c11366b0ed5776fab33c2439396bf9a", size = 104142929, upload-time = "2025-11-12T15:21:48.319Z" }, - { url = "https://files.pythonhosted.org/packages/f4/dd/f1c0d879f2863ef209e18823a988dc7a1bf40470750e3ebe927efdb9407f/torch-2.9.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:8301a7b431e51764629208d0edaa4f9e4c33e6df0f2f90b90e261d623df6a4e2", size = 899748978, upload-time = "2025-11-12T15:23:04.568Z" }, - { url = "https://files.pythonhosted.org/packages/1f/9f/6986b83a53b4d043e36f3f898b798ab51f7f20fdf1a9b01a2720f445043d/torch-2.9.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2e1c42c0ae92bf803a4b2409fdfed85e30f9027a66887f5e7dcdbc014c7531db", size = 111176995, upload-time = "2025-11-12T15:22:01.618Z" }, - { url = "https://files.pythonhosted.org/packages/40/60/71c698b466dd01e65d0e9514b5405faae200c52a76901baf6906856f17e4/torch-2.9.1-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:2c14b3da5df416cf9cb5efab83aa3056f5b8cd8620b8fde81b4987ecab730587", size = 74480347, upload-time = "2025-11-12T15:21:57.648Z" }, - { url = "https://files.pythonhosted.org/packages/48/50/c4b5112546d0d13cc9eaa1c732b823d676a9f49ae8b6f97772f795874a03/torch-2.9.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1edee27a7c9897f4e0b7c14cfc2f3008c571921134522d5b9b5ec4ebbc69041a", size = 74433245, upload-time = "2025-11-12T15:22:39.027Z" }, - { url = "https://files.pythonhosted.org/packages/81/c9/2628f408f0518b3bae49c95f5af3728b6ab498c8624ab1e03a43dd53d650/torch-2.9.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:19d144d6b3e29921f1fc70503e9f2fc572cde6a5115c0c0de2f7ca8b1483e8b6", size = 104134804, upload-time = "2025-11-12T15:22:35.222Z" }, - { url = "https://files.pythonhosted.org/packages/28/fc/5bc91d6d831ae41bf6e9e6da6468f25330522e92347c9156eb3f1cb95956/torch-2.9.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:c432d04376f6d9767a9852ea0def7b47a7bbc8e7af3b16ac9cf9ce02b12851c9", size = 899747132, upload-time = "2025-11-12T15:23:36.068Z" }, - { url = "https://files.pythonhosted.org/packages/63/5d/e8d4e009e52b6b2cf1684bde2a6be157b96fb873732542fb2a9a99e85a83/torch-2.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:d187566a2cdc726fc80138c3cdb260970fab1c27e99f85452721f7759bbd554d", size = 110934845, upload-time = "2025-11-12T15:22:48.367Z" }, - { url = "https://files.pythonhosted.org/packages/bd/b2/2d15a52516b2ea3f414643b8de68fa4cb220d3877ac8b1028c83dc8ca1c4/torch-2.9.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cb10896a1f7fedaddbccc2017ce6ca9ecaaf990f0973bdfcf405439750118d2c", size = 74823558, upload-time = "2025-11-12T15:22:43.392Z" }, - { url = "https://files.pythonhosted.org/packages/86/5c/5b2e5d84f5b9850cd1e71af07524d8cbb74cba19379800f1f9f7c997fc70/torch-2.9.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:0a2bd769944991c74acf0c4ef23603b9c777fdf7637f115605a4b2d8023110c7", size = 104145788, upload-time = "2025-11-12T15:23:52.109Z" }, - { url = "https://files.pythonhosted.org/packages/a9/8c/3da60787bcf70add986c4ad485993026ac0ca74f2fc21410bc4eb1bb7695/torch-2.9.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:07c8a9660bc9414c39cac530ac83b1fb1b679d7155824144a40a54f4a47bfa73", size = 899735500, upload-time = "2025-11-12T15:24:08.788Z" }, - { url = "https://files.pythonhosted.org/packages/db/2b/f7818f6ec88758dfd21da46b6cd46af9d1b3433e53ddbb19ad1e0da17f9b/torch-2.9.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c88d3299ddeb2b35dcc31753305612db485ab6f1823e37fb29451c8b2732b87e", size = 111163659, upload-time = "2025-11-12T15:23:20.009Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8b/4b61d6e13f7108f36910df9ab4b58fd389cc2520d54d81b88660804aad99/torch-2.10.0-2-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f", size = 79423467, upload-time = "2026-02-10T21:44:48.711Z" }, + { url = "https://files.pythonhosted.org/packages/d3/54/a2ba279afcca44bbd320d4e73675b282fcee3d81400ea1b53934efca6462/torch-2.10.0-2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574", size = 79498202, upload-time = "2026-02-10T21:44:52.603Z" }, + { url = "https://files.pythonhosted.org/packages/ec/23/2c9fe0c9c27f7f6cb865abcea8a4568f29f00acaeadfc6a37f6801f84cb4/torch-2.10.0-2-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e", size = 79498254, upload-time = "2026-02-10T21:44:44.095Z" }, + { url = "https://files.pythonhosted.org/packages/36/ab/7b562f1808d3f65414cd80a4f7d4bb00979d9355616c034c171249e1a303/torch-2.10.0-3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac5bdcbb074384c66fa160c15b1ead77839e3fe7ed117d667249afce0acabfac", size = 915518691, upload-time = "2026-03-11T14:15:43.147Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7a/abada41517ce0011775f0f4eacc79659bc9bc6c361e6bfe6f7052a6b9363/torch-2.10.0-3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:98c01b8bb5e3240426dcde1446eed6f40c778091c8544767ef1168fc663a05a6", size = 915622781, upload-time = "2026-03-11T14:17:11.354Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c6/4dfe238342ffdcec5aef1c96c457548762d33c40b45a1ab7033bb26d2ff2/torch-2.10.0-3-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:80b1b5bfe38eb0e9f5ff09f206dcac0a87aadd084230d4a36eea5ec5232c115b", size = 915627275, upload-time = "2026-03-11T14:16:11.325Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/72bf18847f58f877a6a8acf60614b14935e2f156d942483af1ffc081aea0/torch-2.10.0-3-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:46b3574d93a2a8134b3f5475cfb98e2eb46771794c57015f6ad1fb795ec25e49", size = 915523474, upload-time = "2026-03-11T14:17:44.422Z" }, + { url = "https://files.pythonhosted.org/packages/f4/39/590742415c3030551944edc2ddc273ea1fdfe8ffb2780992e824f1ebee98/torch-2.10.0-3-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:b1d5e2aba4eb7f8e87fbe04f86442887f9167a35f092afe4c237dfcaaef6e328", size = 915632474, upload-time = "2026-03-11T14:15:13.666Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8e/34949484f764dde5b222b7fe3fede43e4a6f0da9d7f8c370bb617d629ee2/torch-2.10.0-3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:0228d20b06701c05a8f978357f657817a4a63984b0c90745def81c18aedfa591", size = 915523882, upload-time = "2026-03-11T14:14:46.311Z" }, + { url = "https://files.pythonhosted.org/packages/78/89/f5554b13ebd71e05c0b002f95148033e730d3f7067f67423026cc9c69410/torch-2.10.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:3282d9febd1e4e476630a099692b44fdc214ee9bf8ee5377732d9d9dfe5712e4", size = 145992610, upload-time = "2026-01-21T16:25:26.327Z" }, + { url = "https://files.pythonhosted.org/packages/ae/30/a3a2120621bf9c17779b169fc17e3dc29b230c29d0f8222f499f5e159aa8/torch-2.10.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a2f9edd8dbc99f62bc4dfb78af7bf89499bca3d753423ac1b4e06592e467b763", size = 915607863, upload-time = "2026-01-21T16:25:06.696Z" }, + { url = "https://files.pythonhosted.org/packages/6f/3d/c87b33c5f260a2a8ad68da7147e105f05868c281c63d65ed85aa4da98c66/torch-2.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:29b7009dba4b7a1c960260fc8ac85022c784250af43af9fb0ebafc9883782ebd", size = 113723116, upload-time = "2026-01-21T16:25:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/61/d8/15b9d9d3a6b0c01b883787bd056acbe5cc321090d4b216d3ea89a8fcfdf3/torch-2.10.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:b7bd80f3477b830dd166c707c5b0b82a898e7b16f59a7d9d42778dd058272e8b", size = 79423461, upload-time = "2026-01-21T16:24:50.266Z" }, + { url = "https://files.pythonhosted.org/packages/cc/af/758e242e9102e9988969b5e621d41f36b8f258bb4a099109b7a4b4b50ea4/torch-2.10.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5fd4117d89ffd47e3dcc71e71a22efac24828ad781c7e46aaaf56bf7f2796acf", size = 145996088, upload-time = "2026-01-21T16:24:44.171Z" }, + { url = "https://files.pythonhosted.org/packages/23/8e/3c74db5e53bff7ed9e34c8123e6a8bfef718b2450c35eefab85bb4a7e270/torch-2.10.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:787124e7db3b379d4f1ed54dd12ae7c741c16a4d29b49c0226a89bea50923ffb", size = 915711952, upload-time = "2026-01-21T16:23:53.503Z" }, + { url = "https://files.pythonhosted.org/packages/6e/01/624c4324ca01f66ae4c7cd1b74eb16fb52596dce66dbe51eff95ef9e7a4c/torch-2.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:2c66c61f44c5f903046cc696d088e21062644cbe541c7f1c4eaae88b2ad23547", size = 113757972, upload-time = "2026-01-21T16:24:39.516Z" }, + { url = "https://files.pythonhosted.org/packages/c9/5c/dee910b87c4d5c0fcb41b50839ae04df87c1cfc663cf1b5fca7ea565eeaa/torch-2.10.0-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:6d3707a61863d1c4d6ebba7be4ca320f42b869ee657e9b2c21c736bf17000294", size = 79498198, upload-time = "2026-01-21T16:24:34.704Z" }, + { url = "https://files.pythonhosted.org/packages/c9/6f/f2e91e34e3fcba2e3fc8d8f74e7d6c22e74e480bbd1db7bc8900fdf3e95c/torch-2.10.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:5c4d217b14741e40776dd7074d9006fd28b8a97ef5654db959d8635b2fe5f29b", size = 146004247, upload-time = "2026-01-21T16:24:29.335Z" }, + { url = "https://files.pythonhosted.org/packages/98/fb/5160261aeb5e1ee12ee95fe599d0541f7c976c3701d607d8fc29e623229f/torch-2.10.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6b71486353fce0f9714ca0c9ef1c850a2ae766b409808acd58e9678a3edb7738", size = 915716445, upload-time = "2026-01-21T16:22:45.353Z" }, + { url = "https://files.pythonhosted.org/packages/6a/16/502fb1b41e6d868e8deb5b0e3ae926bbb36dab8ceb0d1b769b266ad7b0c3/torch-2.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:c2ee399c644dc92ef7bc0d4f7e74b5360c37cdbe7c5ba11318dda49ffac2bc57", size = 113757050, upload-time = "2026-01-21T16:24:19.204Z" }, + { url = "https://files.pythonhosted.org/packages/1a/0b/39929b148f4824bc3ad6f9f72a29d4ad865bcf7ebfc2fa67584773e083d2/torch-2.10.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:3202429f58309b9fa96a614885eace4b7995729f44beb54d3e4a47773649d382", size = 79851305, upload-time = "2026-01-21T16:24:09.209Z" }, + { url = "https://files.pythonhosted.org/packages/d8/14/21fbce63bc452381ba5f74a2c0a959fdf5ad5803ccc0c654e752e0dbe91a/torch-2.10.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:aae1b29cd68e50a9397f5ee897b9c24742e9e306f88a807a27d617f07adb3bd8", size = 146005472, upload-time = "2026-01-21T16:22:29.022Z" }, + { url = "https://files.pythonhosted.org/packages/54/fd/b207d1c525cb570ef47f3e9f836b154685011fce11a2f444ba8a4084d042/torch-2.10.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6021db85958db2f07ec94e1bc77212721ba4920c12a18dc552d2ae36a3eb163f", size = 915612644, upload-time = "2026-01-21T16:21:47.019Z" }, + { url = "https://files.pythonhosted.org/packages/36/53/0197f868c75f1050b199fe58f9bf3bf3aecac9b4e85cc9c964383d745403/torch-2.10.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff43db38af76fda183156153983c9a096fc4c78d0cd1e07b14a2314c7f01c2c8", size = 113997015, upload-time = "2026-01-21T16:23:00.767Z" }, + { url = "https://files.pythonhosted.org/packages/0e/13/e76b4d9c160e89fff48bf16b449ea324bda84745d2ab30294c37c2434c0d/torch-2.10.0-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:cdf2a523d699b70d613243211ecaac14fe9c5df8a0b0a9c02add60fb2a413e0f", size = 79498248, upload-time = "2026-01-21T16:23:09.315Z" }, + { url = "https://files.pythonhosted.org/packages/4f/93/716b5ac0155f1be70ed81bacc21269c3ece8dba0c249b9994094110bfc51/torch-2.10.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:bf0d9ff448b0218e0433aeb198805192346c4fd659c852370d5cc245f602a06a", size = 79464992, upload-time = "2026-01-21T16:23:05.162Z" }, + { url = "https://files.pythonhosted.org/packages/69/2b/51e663ff190c9d16d4a8271203b71bc73a16aa7619b9f271a69b9d4a936b/torch-2.10.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:233aed0659a2503b831d8a67e9da66a62c996204c0bba4f4c442ccc0c68a3f60", size = 146018567, upload-time = "2026-01-21T16:22:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cd/4b95ef7f293b927c283db0b136c42be91c8ec6845c44de0238c8c23bdc80/torch-2.10.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:682497e16bdfa6efeec8cde66531bc8d1fbbbb4d8788ec6173c089ed3cc2bfe5", size = 915721646, upload-time = "2026-01-21T16:21:16.983Z" }, + { url = "https://files.pythonhosted.org/packages/56/97/078a007208f8056d88ae43198833469e61a0a355abc0b070edd2c085eb9a/torch-2.10.0-cp314-cp314-win_amd64.whl", hash = "sha256:6528f13d2a8593a1a412ea07a99812495bec07e9224c28b2a25c0a30c7da025c", size = 113752373, upload-time = "2026-01-21T16:22:13.471Z" }, + { url = "https://files.pythonhosted.org/packages/d8/94/71994e7d0d5238393df9732fdab607e37e2b56d26a746cb59fdb415f8966/torch-2.10.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f5ab4ba32383061be0fb74bda772d470140a12c1c3b58a0cfbf3dae94d164c28", size = 79850324, upload-time = "2026-01-21T16:22:09.494Z" }, + { url = "https://files.pythonhosted.org/packages/e2/65/1a05346b418ea8ccd10360eef4b3e0ce688fba544e76edec26913a8d0ee0/torch-2.10.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:716b01a176c2a5659c98f6b01bf868244abdd896526f1c692712ab36dbaf9b63", size = 146006482, upload-time = "2026-01-21T16:22:18.42Z" }, + { url = "https://files.pythonhosted.org/packages/1d/b9/5f6f9d9e859fc3235f60578fa64f52c9c6e9b4327f0fe0defb6de5c0de31/torch-2.10.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d8f5912ba938233f86361e891789595ff35ca4b4e2ac8fe3670895e5976731d6", size = 915613050, upload-time = "2026-01-21T16:20:49.035Z" }, + { url = "https://files.pythonhosted.org/packages/66/4d/35352043ee0eaffdeff154fad67cd4a31dbed7ff8e3be1cc4549717d6d51/torch-2.10.0-cp314-cp314t-win_amd64.whl", hash = "sha256:71283a373f0ee2c89e0f0d5f446039bdabe8dbc3c9ccf35f0f784908b0acd185", size = 113995816, upload-time = "2026-01-21T16:22:05.312Z" }, ] [[package]] @@ -8208,18 +8238,18 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version < '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'", @@ -8230,8 +8260,8 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "numpy", marker = "extra == 'extra-12-earth2studio-ace2'" }, - { name = "torch", marker = "extra == 'extra-12-earth2studio-ace2'" }, + { name = "numpy", marker = "extra == 'extra-12-earth2studio-ace2' or extra == 'extra-12-earth2studio-samudrace' or (extra != 'extra-12-earth2studio-atlas' and extra != 'extra-12-earth2studio-fcn3' and extra != 'extra-12-earth2studio-perturbation' and extra != 'extra-12-earth2studio-sfno')" }, + { name = "torch", marker = "extra == 'extra-12-earth2studio-ace2' or extra == 'extra-12-earth2studio-samudrace' or (extra != 'extra-12-earth2studio-atlas' and extra != 'extra-12-earth2studio-fcn3' and extra != 'extra-12-earth2studio-perturbation' and extra != 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/b5/fb47e55b935c868cce08cc5bb4912e665e5b3e438c76ba54ed3ab205cf77/torch_harmonics-0.8.0.tar.gz", hash = "sha256:b44340184416283a3636640a9050c2187515d6bd9858fa0421b048b66465f773", size = 5844331, upload-time = "2025-07-21T16:48:39.912Z" } @@ -8244,18 +8274,18 @@ resolution-markers = [ "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version >= '3.14' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.13.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform != 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'x86_64' and sys_platform != 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform == 'linux'", "python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", "python_full_version < '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'", @@ -8266,8 +8296,8 @@ resolution-markers = [ "python_full_version < '3.12' and platform_machine != 'aarch64' and platform_machine != 'x86_64' and sys_platform != 'linux'", ] dependencies = [ - { name = "numpy", marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno' or extra != 'extra-12-earth2studio-ace2'" }, - { name = "torch", marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno' or extra != 'extra-12-earth2studio-ace2'" }, + { name = "numpy", marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno'" }, + { name = "torch", marker = "extra == 'extra-12-earth2studio-atlas' or extra == 'extra-12-earth2studio-fcn3' or extra == 'extra-12-earth2studio-perturbation' or extra == 'extra-12-earth2studio-sfno'" }, ] [[package]] @@ -8275,10 +8305,10 @@ name = "torchmetrics" version = "1.8.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "lightning-utilities", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, - { name = "torch", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "lightning-utilities", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "numpy", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "packaging", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "torch", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/85/2e/48a887a59ecc4a10ce9e8b35b3e3c5cef29d902c4eac143378526e7485cb/torchmetrics-1.8.2.tar.gz", hash = "sha256:cf64a901036bf107f17a524009eea7781c9c5315d130713aeca5747a686fe7a5", size = 580679, upload-time = "2025-09-03T14:00:54.077Z" } wheels = [ @@ -8287,7 +8317,7 @@ wheels = [ [[package]] name = "torchvision" -version = "0.24.1" +version = "0.25.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -8295,30 +8325,30 @@ dependencies = [ { name = "torch" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/69/30f5f03752aa1a7c23931d2519b31e557f3f10af5089d787cddf3b903ecf/torchvision-0.24.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:056c525dc875f18fe8e9c27079ada166a7b2755cea5a2199b0bc7f1f8364e600", size = 1891436, upload-time = "2025-11-12T15:25:04.3Z" }, - { url = "https://files.pythonhosted.org/packages/0c/69/49aae86edb75fe16460b59a191fcc0f568c2378f780bb063850db0fe007a/torchvision-0.24.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:1e39619de698e2821d71976c92c8a9e50cdfd1e993507dfb340f2688bfdd8283", size = 2387757, upload-time = "2025-11-12T15:25:06.795Z" }, - { url = "https://files.pythonhosted.org/packages/11/c9/1dfc3db98797b326f1d0c3f3bb61c83b167a813fc7eab6fcd2edb8c7eb9d/torchvision-0.24.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a0f106663e60332aa4fcb1ca2159ef8c3f2ed266b0e6df88de261048a840e0df", size = 8047682, upload-time = "2025-11-12T15:25:21.125Z" }, - { url = "https://files.pythonhosted.org/packages/fa/bb/cfc6a6f6ccc84a534ed1fdf029ae5716dd6ff04e57ed9dc2dab38bf652d5/torchvision-0.24.1-cp311-cp311-win_amd64.whl", hash = "sha256:a9308cdd37d8a42e14a3e7fd9d271830c7fecb150dd929b642f3c1460514599a", size = 4037588, upload-time = "2025-11-12T15:25:14.402Z" }, - { url = "https://files.pythonhosted.org/packages/f0/af/18e2c6b9538a045f60718a0c5a058908ccb24f88fde8e6f0fc12d5ff7bd3/torchvision-0.24.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e48bf6a8ec95872eb45763f06499f87bd2fb246b9b96cb00aae260fda2f96193", size = 1891433, upload-time = "2025-11-12T15:25:03.232Z" }, - { url = "https://files.pythonhosted.org/packages/9d/43/600e5cfb0643d10d633124f5982d7abc2170dfd7ce985584ff16edab3e76/torchvision-0.24.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:7fb7590c737ebe3e1c077ad60c0e5e2e56bb26e7bccc3b9d04dbfc34fd09f050", size = 2386737, upload-time = "2025-11-12T15:25:08.288Z" }, - { url = "https://files.pythonhosted.org/packages/93/b1/db2941526ecddd84884132e2742a55c9311296a6a38627f9e2627f5ac889/torchvision-0.24.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:66a98471fc18cad9064123106d810a75f57f0838eee20edc56233fd8484b0cc7", size = 8049868, upload-time = "2025-11-12T15:25:13.058Z" }, - { url = "https://files.pythonhosted.org/packages/69/98/16e583f59f86cd59949f59d52bfa8fc286f86341a229a9d15cbe7a694f0c/torchvision-0.24.1-cp312-cp312-win_amd64.whl", hash = "sha256:4aa6cb806eb8541e92c9b313e96192c6b826e9eb0042720e2fa250d021079952", size = 4302006, upload-time = "2025-11-12T15:25:16.184Z" }, - { url = "https://files.pythonhosted.org/packages/e4/97/ab40550f482577f2788304c27220e8ba02c63313bd74cf2f8920526aac20/torchvision-0.24.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:8a6696db7fb71eadb2c6a48602106e136c785642e598eb1533e0b27744f2cce6", size = 1891435, upload-time = "2025-11-12T15:25:28.642Z" }, - { url = "https://files.pythonhosted.org/packages/30/65/ac0a3f9be6abdbe4e1d82c915d7e20de97e7fd0e9a277970508b015309f3/torchvision-0.24.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:db2125c46f9cb25dc740be831ce3ce99303cfe60439249a41b04fd9f373be671", size = 2338718, upload-time = "2025-11-12T15:25:26.19Z" }, - { url = "https://files.pythonhosted.org/packages/10/b5/5bba24ff9d325181508501ed7f0c3de8ed3dd2edca0784d48b144b6c5252/torchvision-0.24.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f035f0cacd1f44a8ff6cb7ca3627d84c54d685055961d73a1a9fb9827a5414c8", size = 8049661, upload-time = "2025-11-12T15:25:22.558Z" }, - { url = "https://files.pythonhosted.org/packages/5c/ec/54a96ae9ab6a0dd66d4bba27771f892e36478a9c3489fa56e51c70abcc4d/torchvision-0.24.1-cp313-cp313-win_amd64.whl", hash = "sha256:16274823b93048e0a29d83415166a2e9e0bf4e1b432668357b657612a4802864", size = 4319808, upload-time = "2025-11-12T15:25:17.318Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f3/a90a389a7e547f3eb8821b13f96ea7c0563cdefbbbb60a10e08dda9720ff/torchvision-0.24.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e3f96208b4bef54cd60e415545f5200346a65024e04f29a26cd0006dbf9e8e66", size = 2005342, upload-time = "2025-11-12T15:25:11.871Z" }, - { url = "https://files.pythonhosted.org/packages/a9/fe/ff27d2ed1b524078164bea1062f23d2618a5fc3208e247d6153c18c91a76/torchvision-0.24.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:f231f6a4f2aa6522713326d0d2563538fa72d613741ae364f9913027fa52ea35", size = 2341708, upload-time = "2025-11-12T15:25:25.08Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b9/d6c903495cbdfd2533b3ef6f7b5643ff589ea062f8feb5c206ee79b9d9e5/torchvision-0.24.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:1540a9e7f8cf55fe17554482f5a125a7e426347b71de07327d5de6bfd8d17caa", size = 8177239, upload-time = "2025-11-12T15:25:18.554Z" }, - { url = "https://files.pythonhosted.org/packages/4f/2b/ba02e4261369c3798310483028495cf507e6cb3f394f42e4796981ecf3a7/torchvision-0.24.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d83e16d70ea85d2f196d678bfb702c36be7a655b003abed84e465988b6128938", size = 4251604, upload-time = "2025-11-12T15:25:34.069Z" }, - { url = "https://files.pythonhosted.org/packages/42/84/577b2cef8f32094add5f52887867da4c2a3e6b4261538447e9b48eb25812/torchvision-0.24.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cccf4b4fec7fdfcd3431b9ea75d1588c0a8596d0333245dafebee0462abe3388", size = 2005319, upload-time = "2025-11-12T15:25:23.827Z" }, - { url = "https://files.pythonhosted.org/packages/5f/34/ecb786bffe0159a3b49941a61caaae089853132f3cd1e8f555e3621f7e6f/torchvision-0.24.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:1b495edd3a8f9911292424117544f0b4ab780452e998649425d1f4b2bed6695f", size = 2338844, upload-time = "2025-11-12T15:25:32.625Z" }, - { url = "https://files.pythonhosted.org/packages/51/99/a84623786a6969504c87f2dc3892200f586ee13503f519d282faab0bb4f0/torchvision-0.24.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:ab211e1807dc3e53acf8f6638df9a7444c80c0ad050466e8d652b3e83776987b", size = 8175144, upload-time = "2025-11-12T15:25:31.355Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ba/8fae3525b233e109317ce6a9c1de922ab2881737b029a7e88021f81e068f/torchvision-0.24.1-cp314-cp314-win_amd64.whl", hash = "sha256:18f9cb60e64b37b551cd605a3d62c15730c086362b40682d23e24b616a697d41", size = 4234459, upload-time = "2025-11-12T15:25:19.859Z" }, - { url = "https://files.pythonhosted.org/packages/50/33/481602c1c72d0485d4b3a6b48c9534b71c2957c9d83bf860eb837bf5a620/torchvision-0.24.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec9d7379c519428395e4ffda4dbb99ec56be64b0a75b95989e00f9ec7ae0b2d7", size = 2005336, upload-time = "2025-11-12T15:25:27.225Z" }, - { url = "https://files.pythonhosted.org/packages/d0/7f/372de60bf3dd8f5593bd0d03f4aecf0d1fd58f5bc6943618d9d913f5e6d5/torchvision-0.24.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:af9201184c2712d808bd4eb656899011afdfce1e83721c7cb08000034df353fe", size = 2341704, upload-time = "2025-11-12T15:25:29.857Z" }, - { url = "https://files.pythonhosted.org/packages/36/9b/0f3b9ff3d0225ee2324ec663de0e7fb3eb855615ca958ac1875f22f1f8e5/torchvision-0.24.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:9ef95d819fd6df81bc7cc97b8f21a15d2c0d3ac5dbfaab5cbc2d2ce57114b19e", size = 8177422, upload-time = "2025-11-12T15:25:37.357Z" }, - { url = "https://files.pythonhosted.org/packages/d6/ab/e2bcc7c2f13d882a58f8b30ff86f794210b075736587ea50f8c545834f8a/torchvision-0.24.1-cp314-cp314t-win_amd64.whl", hash = "sha256:480b271d6edff83ac2e8d69bbb4cf2073f93366516a50d48f140ccfceedb002e", size = 4335190, upload-time = "2025-11-12T15:25:35.745Z" }, + { url = "https://files.pythonhosted.org/packages/3e/be/c704bceaf11c4f6b19d64337a34a877fcdfe3bd68160a8c9ae9bea4a35a3/torchvision-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db74a551946b75d19f9996c419a799ffdf6a223ecf17c656f90da011f1d75b20", size = 1874923, upload-time = "2026-01-21T16:27:46.574Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e9/f143cd71232430de1f547ceab840f68c55e127d72558b1061a71d0b193cd/torchvision-0.25.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f49964f96644dbac2506dffe1a0a7ec0f2bf8cf7a588c3319fed26e6329ffdf3", size = 2344808, upload-time = "2026-01-21T16:27:43.191Z" }, + { url = "https://files.pythonhosted.org/packages/43/ae/ad5d6165797de234c9658752acb4fce65b78a6a18d82efdf8367c940d8da/torchvision-0.25.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:153c0d2cbc34b7cf2da19d73450f24ba36d2b75ec9211b9962b5022fb9e4ecee", size = 8070752, upload-time = "2026-01-21T16:27:33.748Z" }, + { url = "https://files.pythonhosted.org/packages/23/19/55b28aecdc7f38df57b8eb55eb0b14a62b470ed8efeb22cdc74224df1d6a/torchvision-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:ea580ffd6094cc01914ad32f8c8118174f18974629af905cea08cb6d5d48c7b7", size = 4038722, upload-time = "2026-01-21T16:27:41.355Z" }, + { url = "https://files.pythonhosted.org/packages/56/3a/6ea0d73f49a9bef38a1b3a92e8dd455cea58470985d25635beab93841748/torchvision-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c2abe430c90b1d5e552680037d68da4eb80a5852ebb1c811b2b89d299b10573b", size = 1874920, upload-time = "2026-01-21T16:27:45.348Z" }, + { url = "https://files.pythonhosted.org/packages/51/f8/c0e1ef27c66e15406fece94930e7d6feee4cb6374bbc02d945a630d6426e/torchvision-0.25.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:b75deafa2dfea3e2c2a525559b04783515e3463f6e830cb71de0fb7ea36fe233", size = 2344556, upload-time = "2026-01-21T16:27:40.125Z" }, + { url = "https://files.pythonhosted.org/packages/68/2f/f24b039169db474e8688f649377de082a965fbf85daf4e46c44412f1d15a/torchvision-0.25.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f25aa9e380865b11ea6e9d99d84df86b9cc959f1a007cd966fc6f1ab2ed0e248", size = 8072351, upload-time = "2026-01-21T16:27:21.074Z" }, + { url = "https://files.pythonhosted.org/packages/ad/16/8f650c2e288977cf0f8f85184b90ee56ed170a4919347fc74ee99286ed6f/torchvision-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:f9c55ae8d673ab493325d1267cbd285bb94d56f99626c00ac4644de32a59ede3", size = 4303059, upload-time = "2026-01-21T16:27:11.08Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5b/1562a04a6a5a4cf8cf40016a0cdeda91ede75d6962cff7f809a85ae966a5/torchvision-0.25.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:24e11199e4d84ba9c5ee7825ebdf1cd37ce8deec225117f10243cae984ced3ec", size = 1874918, upload-time = "2026-01-21T16:27:39.02Z" }, + { url = "https://files.pythonhosted.org/packages/36/b1/3d6c42f62c272ce34fcce609bb8939bdf873dab5f1b798fd4e880255f129/torchvision-0.25.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:5f271136d2d2c0b7a24c5671795c6e4fd8da4e0ea98aeb1041f62bc04c4370ef", size = 2309106, upload-time = "2026-01-21T16:27:30.624Z" }, + { url = "https://files.pythonhosted.org/packages/c7/60/59bb9c8b67cce356daeed4cb96a717caa4f69c9822f72e223a0eae7a9bd9/torchvision-0.25.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:855c0dc6d37f462482da7531c6788518baedca1e0847f3df42a911713acdfe52", size = 8071522, upload-time = "2026-01-21T16:27:29.392Z" }, + { url = "https://files.pythonhosted.org/packages/32/a5/9a9b1de0720f884ea50dbf9acb22cbe5312e51d7b8c4ac6ba9b51efd9bba/torchvision-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:cef0196be31be421f6f462d1e9da1101be7332d91984caa6f8022e6c78a5877f", size = 4321911, upload-time = "2026-01-21T16:27:35.195Z" }, + { url = "https://files.pythonhosted.org/packages/52/99/dca81ed21ebaeff2b67cc9f815a20fdaa418b69f5f9ea4c6ed71721470db/torchvision-0.25.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a8f8061284395ce31bcd460f2169013382ccf411148ceb2ee38e718e9860f5a7", size = 1896209, upload-time = "2026-01-21T16:27:32.159Z" }, + { url = "https://files.pythonhosted.org/packages/28/cc/2103149761fdb4eaed58a53e8437b2d716d48f05174fab1d9fcf1e2a2244/torchvision-0.25.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:146d02c9876858420adf41f3189fe90e3d6a409cbfa65454c09f25fb33bf7266", size = 2310735, upload-time = "2026-01-21T16:27:22.327Z" }, + { url = "https://files.pythonhosted.org/packages/76/ad/f4c985ad52ddd3b22711c588501be1b330adaeaf6850317f66751711b78c/torchvision-0.25.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:c4d395cb2c4a2712f6eb93a34476cdf7aae74bb6ea2ea1917f858e96344b00aa", size = 8089557, upload-time = "2026-01-21T16:27:27.666Z" }, + { url = "https://files.pythonhosted.org/packages/63/cc/0ea68b5802e5e3c31f44b307e74947bad5a38cc655231d845534ed50ddb8/torchvision-0.25.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5e6b449e9fa7d642142c0e27c41e5a43b508d57ed8e79b7c0a0c28652da8678c", size = 4344260, upload-time = "2026-01-21T16:27:17.018Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1f/fa839532660e2602b7e704d65010787c5bb296258b44fa8b9c1cd6175e7d/torchvision-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:620a236288d594dcec7634c754484542dc0a5c1b0e0b83a34bda5e91e9b7c3a1", size = 1896193, upload-time = "2026-01-21T16:27:24.785Z" }, + { url = "https://files.pythonhosted.org/packages/80/ed/d51889da7ceaf5ff7a0574fb28f9b6b223df19667265395891f81b364ab3/torchvision-0.25.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b5e7f50002a8145a98c5694a018e738c50e2972608310c7e88e1bd4c058f6ce", size = 2309331, upload-time = "2026-01-21T16:27:19.97Z" }, + { url = "https://files.pythonhosted.org/packages/90/a5/f93fcffaddd8f12f9e812256830ec9c9ca65abbf1bc369379f9c364d1ff4/torchvision-0.25.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:632db02300e83793812eee4f61ae6a2686dab10b4cfd628b620dc47747aa9d03", size = 8088713, upload-time = "2026-01-21T16:27:15.281Z" }, + { url = "https://files.pythonhosted.org/packages/1f/eb/d0096eed5690d962853213f2ee00d91478dfcb586b62dbbb449fb8abc3a6/torchvision-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1abd5ed030c708f5dbf4812ad5f6fbe9384b63c40d6bd79f8df41a4a759a917", size = 4325058, upload-time = "2026-01-21T16:27:26.165Z" }, + { url = "https://files.pythonhosted.org/packages/97/36/96374a4c7ab50dea9787ce987815614ccfe988a42e10ac1a2e3e5b60319a/torchvision-0.25.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad9a8a5877782944d99186e4502a614770fe906626d76e9cd32446a0ac3075f2", size = 1896207, upload-time = "2026-01-21T16:27:23.383Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e2/7abb10a867db79b226b41da419b63b69c0bd5b82438c4a4ed50e084c552f/torchvision-0.25.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:40a122c3cf4d14b651f095e0f672b688dde78632783fc5cd3d4d5e4f6a828563", size = 2310741, upload-time = "2026-01-21T16:27:18.712Z" }, + { url = "https://files.pythonhosted.org/packages/08/e6/0927784e6ffc340b6676befde1c60260bd51641c9c574b9298d791a9cda4/torchvision-0.25.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:846890161b825b38aa85fc37fb3ba5eea74e7091ff28bab378287111483b6443", size = 8089772, upload-time = "2026-01-21T16:27:14.048Z" }, + { url = "https://files.pythonhosted.org/packages/b6/37/e7ca4ec820d434c0f23f824eb29f0676a0c3e7a118f1514f5b949c3356da/torchvision-0.25.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f07f01d27375ad89d72aa2b3f2180f07da95dd9d2e4c758e015c0acb2da72977", size = 4425879, upload-time = "2026-01-21T16:27:12.579Z" }, ] [[package]] @@ -8379,7 +8409,7 @@ name = "tqdm" version = "4.67.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } wheels = [ @@ -8445,21 +8475,21 @@ wheels = [ [[package]] name = "triton" -version = "3.5.1" +version = "3.6.0" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/dc/6ce44d055f2fc2403c4ec6b3cfd3a9b25f57b7d95efadccdea91497f8e81/triton-3.5.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da47169e30a779bade679ce78df4810fca6d78a955843d2ddb11f226adc517dc", size = 159928005, upload-time = "2025-11-11T17:51:50.008Z" }, - { url = "https://files.pythonhosted.org/packages/b0/72/ec90c3519eaf168f22cb1757ad412f3a2add4782ad3a92861c9ad135d886/triton-3.5.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:61413522a48add32302353fdbaaf92daaaab06f6b5e3229940d21b5207f47579", size = 170425802, upload-time = "2025-11-11T17:40:53.209Z" }, - { url = "https://files.pythonhosted.org/packages/db/53/2bcc46879910991f09c063eea07627baef2bc62fe725302ba8f46a2c1ae5/triton-3.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:275a045b6ed670dd1bd005c3e6c2d61846c74c66f4512d6f33cc027b11de8fd4", size = 159940689, upload-time = "2025-11-11T17:51:55.938Z" }, - { url = "https://files.pythonhosted.org/packages/f2/50/9a8358d3ef58162c0a415d173cfb45b67de60176e1024f71fbc4d24c0b6d/triton-3.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d2c6b915a03888ab931a9fd3e55ba36785e1fe70cbea0b40c6ef93b20fc85232", size = 170470207, upload-time = "2025-11-11T17:41:00.253Z" }, - { url = "https://files.pythonhosted.org/packages/f1/ba/805684a992ee32d486b7948d36aed2f5e3c643fc63883bf8bdca1c3f3980/triton-3.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56765ffe12c554cd560698398b8a268db1f616c120007bfd8829d27139abd24a", size = 159955460, upload-time = "2025-11-11T17:52:01.861Z" }, - { url = "https://files.pythonhosted.org/packages/27/46/8c3bbb5b0a19313f50edcaa363b599e5a1a5ac9683ead82b9b80fe497c8d/triton-3.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3f4346b6ebbd4fad18773f5ba839114f4826037c9f2f34e0148894cd5dd3dba", size = 170470410, upload-time = "2025-11-11T17:41:06.319Z" }, - { url = "https://files.pythonhosted.org/packages/84/1e/7df59baef41931e21159371c481c31a517ff4c2517343b62503d0cd2be99/triton-3.5.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02c770856f5e407d24d28ddc66e33cf026e6f4d360dcb8b2fabe6ea1fc758621", size = 160072799, upload-time = "2025-11-11T17:52:07.293Z" }, - { url = "https://files.pythonhosted.org/packages/37/92/e97fcc6b2c27cdb87ce5ee063d77f8f26f19f06916aa680464c8104ef0f6/triton-3.5.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0b4d2c70127fca6a23e247f9348b8adde979d2e7a20391bfbabaac6aebc7e6a8", size = 170579924, upload-time = "2025-11-11T17:41:12.455Z" }, - { url = "https://files.pythonhosted.org/packages/14/f9/0430e879c1e63a1016cb843261528fd3187c872c3a9539132efc39514753/triton-3.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f617aa7925f9ea9968ec2e1adaf93e87864ff51549c8f04ce658f29bbdb71e2d", size = 159956163, upload-time = "2025-11-11T17:52:12.999Z" }, - { url = "https://files.pythonhosted.org/packages/a4/e6/c595c35e5c50c4bc56a7bac96493dad321e9e29b953b526bbbe20f9911d0/triton-3.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0637b1efb1db599a8e9dc960d53ab6e4637db7d4ab6630a0974705d77b14b60", size = 170480488, upload-time = "2025-11-11T17:41:18.222Z" }, - { url = "https://files.pythonhosted.org/packages/41/1e/63d367c576c75919e268e4fbc33c1cb33b6dc12bb85e8bfe531c2a8bd5d3/triton-3.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8932391d7f93698dfe5bc9bead77c47a24f97329e9f20c10786bb230a9083f56", size = 160073620, upload-time = "2025-11-11T17:52:18.403Z" }, - { url = "https://files.pythonhosted.org/packages/16/b5/b0d3d8b901b6a04ca38df5e24c27e53afb15b93624d7fd7d658c7cd9352a/triton-3.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bac7f7d959ad0f48c0e97d6643a1cc0fd5786fe61cb1f83b537c6b2d54776478", size = 170582192, upload-time = "2025-11-11T17:41:23.963Z" }, + { url = "https://files.pythonhosted.org/packages/0f/2c/96f92f3c60387e14cc45aed49487f3486f89ea27106c1b1376913c62abe4/triton-3.6.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49df5ef37379c0c2b5c0012286f80174fcf0e073e5ade1ca9a86c36814553651", size = 176081190, upload-time = "2026-01-20T16:16:00.523Z" }, + { url = "https://files.pythonhosted.org/packages/e0/12/b05ba554d2c623bffa59922b94b0775673de251f468a9609bc9e45de95e9/triton-3.6.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8e323d608e3a9bfcc2d9efcc90ceefb764a82b99dea12a86d643c72539ad5d3", size = 188214640, upload-time = "2026-01-20T16:00:35.869Z" }, + { url = "https://files.pythonhosted.org/packages/17/5d/08201db32823bdf77a0e2b9039540080b2e5c23a20706ddba942924ebcd6/triton-3.6.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:374f52c11a711fd062b4bfbb201fd9ac0a5febd28a96fb41b4a0f51dde3157f4", size = 176128243, upload-time = "2026-01-20T16:16:07.857Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a8/cdf8b3e4c98132f965f88c2313a4b493266832ad47fb52f23d14d4f86bb5/triton-3.6.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74caf5e34b66d9f3a429af689c1c7128daba1d8208df60e81106b115c00d6fca", size = 188266850, upload-time = "2026-01-20T16:00:43.041Z" }, + { url = "https://files.pythonhosted.org/packages/3c/12/34d71b350e89a204c2c7777a9bba0dcf2f19a5bfdd70b57c4dbc5ffd7154/triton-3.6.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448e02fe6dc898e9e5aa89cf0ee5c371e99df5aa5e8ad976a80b93334f3494fd", size = 176133521, upload-time = "2026-01-20T16:16:13.321Z" }, + { url = "https://files.pythonhosted.org/packages/f9/0b/37d991d8c130ce81a8728ae3c25b6e60935838e9be1b58791f5997b24a54/triton-3.6.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10c7f76c6e72d2ef08df639e3d0d30729112f47a56b0c81672edc05ee5116ac9", size = 188289450, upload-time = "2026-01-20T16:00:49.136Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4e/41b0c8033b503fd3cfcd12392cdd256945026a91ff02452bef40ec34bee7/triton-3.6.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1722e172d34e32abc3eb7711d0025bb69d7959ebea84e3b7f7a341cd7ed694d6", size = 176276087, upload-time = "2026-01-20T16:16:18.989Z" }, + { url = "https://files.pythonhosted.org/packages/35/f8/9c66bfc55361ec6d0e4040a0337fb5924ceb23de4648b8a81ae9d33b2b38/triton-3.6.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d002e07d7180fd65e622134fbd980c9a3d4211fb85224b56a0a0efbd422ab72f", size = 188400296, upload-time = "2026-01-20T16:00:56.042Z" }, + { url = "https://files.pythonhosted.org/packages/49/55/5ecf0dcaa0f2fbbd4420f7ef227ee3cb172e91e5fede9d0ecaddc43363b4/triton-3.6.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef5523241e7d1abca00f1d240949eebdd7c673b005edbbce0aca95b8191f1d43", size = 176138577, upload-time = "2026-01-20T16:16:25.426Z" }, + { url = "https://files.pythonhosted.org/packages/df/3d/9e7eee57b37c80cec63322c0231bb6da3cfe535a91d7a4d64896fcb89357/triton-3.6.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a17a5d5985f0ac494ed8a8e54568f092f7057ef60e1b0fa09d3fd1512064e803", size = 188273063, upload-time = "2026-01-20T16:01:07.278Z" }, + { url = "https://files.pythonhosted.org/packages/48/db/56ee649cab5eaff4757541325aca81f52d02d4a7cd3506776cad2451e060/triton-3.6.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b3a97e8ed304dfa9bd23bb41ca04cdf6b2e617d5e782a8653d616037a5d537d", size = 176274804, upload-time = "2026-01-20T16:16:31.528Z" }, + { url = "https://files.pythonhosted.org/packages/f6/56/6113c23ff46c00aae423333eb58b3e60bdfe9179d542781955a5e1514cb3/triton-3.6.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:46bd1c1af4b6704e554cad2eeb3b0a6513a980d470ccfa63189737340c7746a7", size = 188397994, upload-time = "2026-01-20T16:01:14.236Z" }, ] [[package]] @@ -8673,11 +8703,11 @@ wheels = [ [package.optional-dependencies] standard = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "httptools" }, { name = "python-dotenv" }, { name = "pyyaml" }, - { name = "uvloop", marker = "(platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "uvloop", marker = "(platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (platform_python_implementation == 'PyPy' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform == 'cygwin' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (sys_platform == 'win32' and extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, { name = "watchfiles" }, { name = "websockets" }, ] @@ -8971,7 +9001,7 @@ name = "werkzeug" version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno')" }, + { name = "markupsafe", marker = "python_full_version >= '3.12' or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-atlas') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-fcn3') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-perturbation') or (extra == 'extra-12-earth2studio-ace2' and extra == 'extra-12-earth2studio-sfno') or (extra == 'extra-12-earth2studio-atlas' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-fcn3' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-perturbation' and extra == 'extra-12-earth2studio-samudrace') or (extra == 'extra-12-earth2studio-samudrace' and extra == 'extra-12-earth2studio-sfno')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/f1/ee81806690a87dab5f5653c1f146c92bc066d7f4cebc603ef88eb9e13957/werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25", size = 864736, upload-time = "2026-02-19T15:17:18.884Z" } wheels = [ From 083d41687a1fe3d02d7c0178eea40fcbdd12fb4d Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Mon, 30 Mar 2026 19:02:26 +0000 Subject: [PATCH 09/20] Fixes --- earth2studio/io/netcdf4.py | 8 +++++--- earth2studio/models/px/samudrace.py | 16 ++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/earth2studio/io/netcdf4.py b/earth2studio/io/netcdf4.py index 345567a17..6bbdef86f 100644 --- a/earth2studio/io/netcdf4.py +++ b/earth2studio/io/netcdf4.py @@ -28,10 +28,13 @@ from earth2studio.utils.type import CoordSystem units_map = { - "h": "hours", - "D": "days", + "ns": "nanoseconds", + "us": "microseconds", + "ms": "milliseconds", "s": "seconds", "m": "minutes", + "h": "hours", + "D": "days", "Y": "years", } rev_units_map = {v: k for k, v in units_map.items()} @@ -133,7 +136,6 @@ def add_dimension(self, name: str, shape: tuple | list, data: np.ndarray) -> Non # Check if data is datetime64 if np.issubdtype(data.dtype, np.datetime64): - var = self.root.createVariable(name, "f8", (name,)) var.units = "hours since 0001-01-01 00:00:00.0" var.calendar = "proleptic_gregorian" diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index e3c070e26..00b2c8ac7 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -480,8 +480,6 @@ def _get_forcing_slice( day: int, hour: int, n_flat: int, - lat_len: int, - lon_len: int, ) -> torch.Tensor: """Extract a single forcing field from the forcing NetCDF for a given time. @@ -497,10 +495,6 @@ def _get_forcing_slice( Target hour (0, 6, 12, 18). n_flat : int Flattened batch size. - lat_len : int - Latitude dimension size. - lon_len : int - Longitude dimension size. Returns ------- @@ -625,7 +619,7 @@ def _forward( for abs_t in abs_times: ts = pd.Timestamp(abs_t) val = self._get_forcing_slice( - fme_name, ts.month, ts.day, ts.hour, n_flat, lat_len, lon_len + fme_name, ts.month, ts.day, ts.hour, n_flat ) slices.append(val) atm_forcing_data[fme_name] = torch.stack(slices, dim=1) @@ -776,11 +770,9 @@ def _run_ocean_step( nan_pad = torch.full_like(val, float("nan")) ocean_forcing_data[key] = torch.cat([nan_pad, val], dim=1) - # Add static fields if needed (land_fraction from atmosphere state) - atm_bd = atm_state.as_batch_data() - if "land_fraction" in atm_bd.data: - lf_val = atm_bd.data["land_fraction"][:, -1:, ...] - ocean_forcing_data["land_fraction"] = lf_val.expand(-1, 2, -1, -1) + # Add land_fraction from forcing file (static field needed by ocean stepper) + lf_val = self._get_forcing_slice("land_fraction", 1, 1, 0, n_flat) + ocean_forcing_data["land_fraction"] = lf_val.unsqueeze(1).expand(-1, 2, -1, -1) # Build time array for ocean forcing (2 timesteps spanning the 5-day window) ocean_dt = np.timedelta64(5, "D") From cecbc8c1bf1168e4a1d0fb22eec78a1f398bf7e3 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Mon, 30 Mar 2026 22:26:39 +0000 Subject: [PATCH 10/20] Fixes --- earth2studio/models/px/samudrace.py | 75 ++++++++++++++++++++++++----- test/models/px/test_samudrace.py | 13 +++++ 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index 00b2c8ac7..c0fc480e9 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -395,6 +395,33 @@ def _build_batch_data( horizontal_dims=["lat", "lon"], ) + def _prescribe_ic_sst( + self, + atmos_ic_state: PrognosticState, + atmos_forcing: BatchData, + ) -> PrognosticState: + """This mirrors CoupledStepper._prescribe_ic_sst in FME which blends + the ocean-sourced ``surface_temperature`` into the atmosphere initial + condition using ``ocean_fraction`` as a mask (interpolation mode). + """ + # Extract the IC-timestep slice from forcing (n_ic_timesteps == 1) + forcing_ic = atmos_forcing.select_time_slice( + slice(None, self.coupled_stepper.atmosphere.n_ic_timesteps) + ) + ic_bd = atmos_ic_state.as_batch_data() + prescribed_data = self.coupled_stepper.atmosphere.prescribe_sst( + mask_data=forcing_ic.data, + gen_data=ic_bd.data, + target_data=forcing_ic.data, + ) + return PrognosticState( + BatchData( + data=prescribed_data, + time=ic_bd.time, + labels=ic_bd.labels, + ) + ) + def _tensor_to_component_states( self, x: torch.Tensor, @@ -625,7 +652,9 @@ def _forward( atm_forcing_data[fme_name] = torch.stack(slices, dim=1) # Add ocean-sourced forcing: SST, ocean_fraction, sea_ice_fraction - # These are held constant for all inner atmosphere steps + # These are held constant for all inner atmosphere steps. + # This mirrors CoupledStepper._get_atmosphere_forcings and + # _forcings_from_ocean_with_ocean_fraction in FME. ocean_bd = ocean_state.as_batch_data() coupled_config = self.coupled_stepper._config @@ -638,36 +667,52 @@ def _forward( # Sea ice fraction and ocean fraction — derived from ocean's # ocean_sea_ice_fraction via the CoupledOceanFractionConfig when # available, otherwise look for direct sea_ice_fraction/ocean_fraction. + # Track which names are ocean-sourced for mask zeroing below. + ocean_sourced_names: list[str] = ["surface_temperature"] ofp = coupled_config.ocean_fraction_prediction if ofp is not None: sic_name = ofp.sea_ice_fraction_name # e.g. "ocean_sea_ice_fraction" land_name = ofp.land_fraction_name # e.g. "land_fraction" atm_sic_name = ofp.sea_ice_fraction_name_in_atmosphere # "sea_ice_fraction" - # Compute atmosphere-facing sea_ice and ocean_fraction from ocean + # Compute atmosphere-facing sea_ice and ocean_fraction from ocean. if sic_name in ocean_bd.data: - osic = ocean_bd.data[sic_name][:, -1:, ...] - # Get land fraction from atmosphere state - atm_bd_pre = atm_state.as_batch_data() - land_frac = ( - atm_bd_pre.data[land_name][:, -1:, ...] - if land_name in atm_bd_pre.data - else torch.zeros_like(osic) - ) + # FME: nan_to_num on ocean sea-ice before deriving fractions + osic = torch.nan_to_num(ocean_bd.data[sic_name][:, -1:, ...]) + # land_fraction comes from external forcing, not atmosphere + # prognostic state (which never contains it). + land_frac = atm_forcing_data[land_name][:, :1, ...] # sea_ice_fraction = ocean_sea_ice_fraction * (1 - land_fraction) sic_atm = osic * (1.0 - land_frac) atm_forcing_data[atm_sic_name] = sic_atm.expand(-1, 2, -1, -1) - # ocean_fraction = 1 - land_fraction - sea_ice_fraction - ocean_frac = 1.0 - land_frac - sic_atm + # ocean_fraction = clip(1 - land - sea_ice, min=0) + ocean_frac = torch.clip(1.0 - land_frac - sic_atm, min=0) atm_forcing_data["ocean_fraction"] = ocean_frac.expand(-1, 2, -1, -1) + ocean_sourced_names += [atm_sic_name, "ocean_fraction"] else: if "sea_ice_fraction" in ocean_bd.data: sic_val = ocean_bd.data["sea_ice_fraction"][:, -1:, ...] atm_forcing_data["sea_ice_fraction"] = sic_val.expand(-1, 2, -1, -1) + ocean_sourced_names.append("sea_ice_fraction") if "ocean_fraction" in ocean_bd.data: of_val = ocean_bd.data["ocean_fraction"][:, -1:, ...] atm_forcing_data["ocean_fraction"] = of_val.expand(-1, 2, -1, -1) + ocean_sourced_names.append("ocean_fraction") + + # Apply ocean mask zeroing: set ocean-invalid grid points to 0. + # This mirrors CoupledStepper._forcings_from_ocean_with_ocean_fraction + # (FME lines 979-984) which uses _ocean_mask_provider. + ocean_mask_provider = self.coupled_stepper._ocean_mask_provider + for oname in ocean_sourced_names: + if oname in atm_forcing_data: + mask = ocean_mask_provider.get_mask_tensor_for(oname) + if mask is not None: + mask = mask.to(atm_forcing_data[oname].device) + mask = mask.expand(atm_forcing_data[oname].shape) + atm_forcing_data[oname] = atm_forcing_data[oname].where( + mask != 0, 0 + ) # Fallback: static fields from atmosphere state if not already provided # by the external data source above. @@ -679,6 +724,12 @@ def _forward( atm_forcing = self._build_batch_data(atm_forcing_data, time_array, n_flat) + # Prescribe ocean SST onto the atmosphere IC surface_temperature. + # This mirrors FME's CoupledStepper._prescribe_ic_sst which blends + # ocean SST into the atmosphere IC at the start of each coupled cycle. + if step_in_cycle == 0: + atm_state = self._prescribe_ic_sst(atm_state, atm_forcing) + # Run atmosphere step atm_paired, new_atm_state = self.coupled_stepper.atmosphere.predict_paired( atm_state, atm_forcing diff --git a/test/models/px/test_samudrace.py b/test/models/px/test_samudrace.py index 820c2d606..c4ed45629 100644 --- a/test/models/px/test_samudrace.py +++ b/test/models/px/test_samudrace.py @@ -114,8 +114,13 @@ def __init__( self.prognostic_names = prognostic_names self._input_only_names = input_only_names self.out_names = out_names + self.n_ic_timesteps = 1 self.register_buffer("device_buffer", torch.empty(0)) + def prescribe_sst(self, mask_data, gen_data, target_data): + """Mock SST prescription that returns gen_data unchanged.""" + return dict(gen_data) + def predict_paired(self, ic, forcing_batch): first_key = self.prognostic_names[0] batch, _, lat, lon = ic._data.data[first_key].shape @@ -165,6 +170,13 @@ class PhooCoupledConfig: ocean_fraction_prediction = PhooCoupledOceanFractionConfig() +class PhooMaskProvider: + """Mock ocean mask provider that returns no masks (no-op).""" + + def get_mask_tensor_for(self, name): + return None + + class PhooCoupledStepper: """Mock CoupledStepper matching the interface used by SamudrACE wrapper.""" @@ -172,6 +184,7 @@ def __init__(self): self.atmosphere = PhooStepper(ATM_PROGNOSTIC, ATM_INPUT_ONLY, ATM_OUT) self.ocean = PhooStepper(OCEAN_PROGNOSTIC, OCEAN_INPUT_ONLY, OCEAN_OUT) self._config = PhooCoupledConfig() + self._ocean_mask_provider = PhooMaskProvider() def to(self, device): self.atmosphere = self.atmosphere.to(device) From c77c30e29194c2ee459f1da255615f1b0cc41e13 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Mon, 30 Mar 2026 23:48:47 +0000 Subject: [PATCH 11/20] Update skill --- .../skills/create-prognostic-wrapper/SKILL.md | 266 +++++++++++++++--- 1 file changed, 221 insertions(+), 45 deletions(-) diff --git a/.claude/skills/create-prognostic-wrapper/SKILL.md b/.claude/skills/create-prognostic-wrapper/SKILL.md index a3a90bfc1..f2c8bd914 100644 --- a/.claude/skills/create-prognostic-wrapper/SKILL.md +++ b/.claude/skills/create-prognostic-wrapper/SKILL.md @@ -981,73 +981,249 @@ debug and fix the wrapper or test, then re-run. --- -## Step 12 — Provide Side-by-Side Comparison Scripts +## Step 12 — Provide E2E Validation Scripts and Comparison Plots -Present two scripts to the user: +Create three runnable scripts that validate the Earth2Studio +wrapper produces output equivalent to the model's native +inference pipeline. These scripts are intended to be +**attached to the PR** for reviewer verification and serve +as end-to-end integration tests. -### Reference script (without Earth2Studio) +### 12a. Earth2Studio reference script (`e2s_reference.py`) -Reconstruct a minimal inference script based on the original reference code: +A self-contained script that runs inference through +`run.deterministic` and writes output to a single file. ```python -# Reference inference (no Earth2Studio) -import torch -# ... original model imports ... +"""<ModelName> inference using the Earth2Studio run.deterministic API. -# Load model -model = OriginalModel.from_pretrained("path/to/checkpoint") -model.eval().cuda() +Loads the model, fetches initial conditions from the +appropriate data source, and runs a multi-step rollout. +Output is written to a single NetCDF file for comparison +with the native-framework reference output. +""" -# Prepare input -input_data = ... # Load/prepare input data per original repo instructions +import earth2studio.run as run +from earth2studio.data import ModelDataSource # e.g., SamudrACEData +from earth2studio.io import NetCDF4Backend +from earth2studio.models.px import ModelName -# Run inference -with torch.no_grad(): - output = model(input_data) +# Configuration — match exactly what the native reference uses +SCENARIO = "..." # If applicable +N_STEPS = 40 # Total forward steps +TIME = ["2000-01-01T00:00:00"] +OUTPUT_FILE = "outputs/e2s_reference_output.nc" + +print("Loading model via Earth2Studio...") +package = ModelName.load_default_package() +model = ModelName.load_model(package, ...) +data = ModelDataSource(...) + +print(f"Running deterministic forecast ({N_STEPS} steps)...") +io = run.deterministic( + time=TIME, + nsteps=N_STEPS, + prognostic=model, + data=data, + io=NetCDF4Backend( + file_name=OUTPUT_FILE, + backend_kwargs={"mode": "w"}, + ), +) -print(f"Output shape: {output.shape}") +print(f"Results saved to {OUTPUT_FILE}") ``` -### Earth2Studio equivalent +**Key requirements:** + +- Use the **same initial conditions, forcing data, and + scenario** as the native reference script +- Use `run.deterministic` (not manual iteration) so the + full E2S pipeline (data fetch, coord alignment, IO + write) is exercised +- Output to a **NetCDF file** with all model variables + +### 12b. Native-framework reference script (`fme_reference.py`) + +A self-contained script that runs inference using the +model's **original framework** (not Earth2Studio). ```python -# Earth2Studio inference -import torch -import numpy as np -from earth2studio.models.px import ModelName -from earth2studio.data import Random, fetch_data # or GFS, ERA5, etc. +"""<ModelName> inference using the native framework. -# Load model -model = ModelName.from_pretrained() -model = model.to("cuda") +Downloads model artifacts, then runs inference using the +original API / config-driven pipeline. +""" -# Prepare input via Earth2Studio data pipeline -time = np.array([np.datetime64("2024-01-01T00:00")]) -input_coords = model.input_coords() -input_coords["time"] = time -ds = Random(input_coords) # Replace with real data source -x, coords = fetch_data(ds, time, input_coords["variable"], device="cuda") +import os +# ... native framework imports ... -# Single step -with torch.no_grad(): - output, out_coords = model(x, coords) +# Download / resolve model artifacts +# (e.g., snapshot_download from HuggingFace) +repo_dir = download_model(...) -print(f"Output shape: {output.shape}") -print(f"Lead time: {out_coords['lead_time']}") +# Run inference using the native API +native_inference( + config="inference_config.yaml", + n_steps=..., + output_dir="outputs/native_reference_output", +) -# Multi-step forecast -iterator = model.create_iterator(x, coords) -for i, (step_x, step_coords) in enumerate(iterator): - print(f"Step {i}: lead_time={step_coords['lead_time']}") - if i >= 10: - break +print("Done.") +``` + +**Key requirements:** + +- Use the **same checkpoint, IC files, and config** as + the E2S script +- Write output to a **known directory structure** with + predictable file names +- Pin random seeds if the model has any stochastic + components (`torch.manual_seed(0)`, + `np.random.seed(0)`) + +### 12c. Comparison script (`compare.py`) + +A script that loads both outputs, aligns them by time / +lead-time, and produces: + +1. **Global-mean timeseries** — per variable, 3-panel + (reference, E2S, difference) +2. **Spatial maps** — at selected lead times, 3-panel + (reference, E2S, difference with RMSE/MAE stats) +3. **Summary statistics** — per-variable RMSE, MAE, + max absolute difference, and `np.allclose` result + +```python +"""Compare <ModelName> forecasts from native and E2S pipelines. + +Plots selected variables as timeseries (global mean) and +spatial maps at selected lead times, plus the difference. + +Usage: + python compare.py +""" + +import matplotlib.pyplot as plt +import numpy as np +import xarray as xr + +from earth2studio.lexicon.<model_lexicon> import ModelLexicon + +# ---- Variable definitions ---- +# Map E2S variable names to native-framework names, grouped +# by component if the model has multiple components. +VARIABLES = { + "var_key": { + "e2s_name": "...", + "fme_name": "...", # Native framework name + "component": "...", # If applicable (e.g., "atmosphere", "ocean") + "label": "Description [units]", + "cmap": "RdYlBu_r", + "vmin": ..., "vmax": ..., + }, + # ... more variables ... +} + +# ---- Load datasets ---- +ds_ref = xr.open_dataset("outputs/native_reference_output/predictions.nc") +ds_e2s = xr.open_dataset("outputs/e2s_reference_output.nc") + +# ---- Helper functions ---- + +def get_ref_series(da): + """Extract (n_steps, lat, lon) from native output.""" + return da.isel(sample=0).values + +def get_e2s_series(da, component="atmosphere"): + """Extract (n_steps, lat, lon) from E2S output. + + Skips the IC at lead_time=0 since the native output + typically contains only predictions. + """ + vals = da.isel(time=0).values[1:] # skip IC + # If component has different step cadence, sub-sample: + # if component == "ocean": + # indices = np.arange(N_INNER - 1, len(vals), N_INNER) + # vals = vals[indices] + return vals + +# ---- Figure 1: Global-mean timeseries ---- +# ... 3-panel plot per variable ... + +# ---- Figure 2: Spatial maps at selected steps ---- +# ... 3-panel (ref, E2S, diff) per step ... + +# ---- Summary statistics ---- +for var_key, var_info in VARIABLES.items(): + # Compute RMSE, MAE, max abs diff, allclose + ... + +ds_ref.close() +ds_e2s.close() ``` +### Important considerations for the comparison script + +**Time / lead-time alignment:** + +The E2S output from `run.deterministic` includes the +initial condition at `lead_time=0` as step 0, followed +by predictions at `lead_time=dt, 2*dt, ...`. The native +framework may write predictions only (no IC) starting +from the first forecast step. The comparison script must +account for this offset — typically by skipping the E2S +IC entry (`values[1:]`). + +**Component-specific step cadences:** + +If the model has components that update at different +rates (e.g., atmosphere every 6h, ocean every 5 days), +the native framework may write each component's output +at its own cadence while E2S writes all variables at +every atmosphere step. The comparison script must +sub-sample the E2S output at the slower component's +update boundaries to align with the native output. + +**Variable name mapping:** + +Use the model's lexicon class to map between E2S and +native variable names. Verify the mapping is correct by +checking a few variables at the IC step (where both +outputs should be identical). + +**Grid alignment:** + +Check whether both outputs use the same latitude +ordering (north-to-south vs south-to-north). If they +differ, flip one before computing differences. + +### Deliverables for the PR + +Attach the following to the pull request: + +| File | Purpose | +|------|---------| +| `e2s_reference.py` | E2S inference script | +| `fme_reference.py` (or `<framework>_reference.py`) | Native-framework inference script | +| `compare.py` | Comparison and plotting script | +| `compare_timeseries.png` | Global-mean timeseries plot | +| `compare_<var>.png` | Per-variable spatial map plots | + +These do **not** get committed to the repository — they +are PR attachments for reviewer validation only. + ### **[CONFIRM — Comparison Scripts]** -Ask the user to compare the two scripts and verify the -Earth2Studio version is functionally equivalent to the -reference. +Present the three scripts to the user and ask: + +1. Do the E2S and native reference scripts use identical + inputs (IC, forcing, scenario, number of steps)? +2. Is the time alignment logic in `compare.py` correct + for this model's output structure? +3. Are the comparison plots showing near-zero differences + at the IC step and acceptable divergence at later + steps? --- From b23c24bc8bcf305da5640bac548ee0833d129135 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Mon, 30 Mar 2026 23:53:59 +0000 Subject: [PATCH 12/20] Update skill --- .claude/skills/create-prognostic-wrapper/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/skills/create-prognostic-wrapper/SKILL.md b/.claude/skills/create-prognostic-wrapper/SKILL.md index f2c8bd914..4f7eae452 100644 --- a/.claude/skills/create-prognostic-wrapper/SKILL.md +++ b/.claude/skills/create-prognostic-wrapper/SKILL.md @@ -1043,7 +1043,7 @@ print(f"Results saved to {OUTPUT_FILE}") write) is exercised - Output to a **NetCDF file** with all model variables -### 12b. Native-framework reference script (`fme_reference.py`) +### 12b. Native-framework reference script (`native_reference.py`) A self-contained script that runs inference using the model's **original framework** (not Earth2Studio). @@ -1116,7 +1116,7 @@ from earth2studio.lexicon.<model_lexicon> import ModelLexicon VARIABLES = { "var_key": { "e2s_name": "...", - "fme_name": "...", # Native framework name + "native_name": "...", # Native framework name "component": "...", # If applicable (e.g., "atmosphere", "ocean") "label": "Description [units]", "cmap": "RdYlBu_r", @@ -1205,7 +1205,7 @@ Attach the following to the pull request: | File | Purpose | |------|---------| | `e2s_reference.py` | E2S inference script | -| `fme_reference.py` (or `<framework>_reference.py`) | Native-framework inference script | +| `native_reference.py` (or `<framework>_reference.py`) | Native-framework inference script | | `compare.py` | Comparison and plotting script | | `compare_timeseries.png` | Global-mean timeseries plot | | `compare_<var>.png` | Per-variable spatial map plots | From e50602d84dc867b34598197da5f6d02d0b392cf8 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 00:21:22 +0000 Subject: [PATCH 13/20] Skill update --- .claude/skills/create-prognostic-wrapper/SKILL.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.claude/skills/create-prognostic-wrapper/SKILL.md b/.claude/skills/create-prognostic-wrapper/SKILL.md index 4f7eae452..6d4dc14e5 100644 --- a/.claude/skills/create-prognostic-wrapper/SKILL.md +++ b/.claude/skills/create-prognostic-wrapper/SKILL.md @@ -1042,6 +1042,12 @@ print(f"Results saved to {OUTPUT_FILE}") full E2S pipeline (data fetch, coord alignment, IO write) is exercised - Output to a **NetCDF file** with all model variables +- Pin random seeds if the model has any stochastic + components (`torch.manual_seed(0)`, + `np.random.seed(0)`) and enable torch deterministic + mode when possible (`torch.use_deterministic_algorithms(True)`, + `torch.backends.cudnn.deterministic = True`, + `torch.backends.cudnn.benchmark = False`) ### 12b. Native-framework reference script (`native_reference.py`) @@ -1080,7 +1086,10 @@ print("Done.") predictable file names - Pin random seeds if the model has any stochastic components (`torch.manual_seed(0)`, - `np.random.seed(0)`) + `np.random.seed(0)`) and enable torch deterministic + mode when possible (`torch.use_deterministic_algorithms(True)`, + `torch.backends.cudnn.deterministic = True`, + `torch.backends.cudnn.benchmark = False`) ### 12c. Comparison script (`compare.py`) From ef6ee6658b9c11eb12e9d6422155c877f96ae0c9 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 01:16:38 +0000 Subject: [PATCH 14/20] Skill update --- earth2studio/models/px/samudrace.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index c0fc480e9..f43f765b2 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -159,6 +159,8 @@ class SamudrACE(torch.nn.Module, AutoModelMixin, PrognosticMixin): gpu:40gb """ + _HF_REPO_ID = "allenai/SamudrACE-CM4-piControl" + def __init__( self, coupled_stepper: CoupledStepper, @@ -466,9 +468,6 @@ def _tensor_to_component_states( return PrognosticState(atm_bd), PrognosticState(ocean_bd) - # HuggingFace repository for forcing data - _HF_REPO_ID = "allenai/SamudrACE-CM4-piControl" - def _ensure_forcing_file(self) -> str: """Download the forcing NetCDF from HuggingFace if not already cached. From c18345afbef3d8f01f2bc0164370adab0301ece8 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 03:16:16 +0000 Subject: [PATCH 15/20] Logging --- earth2studio/data/samudrace.py | 3 ++- earth2studio/models/px/samudrace.py | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/earth2studio/data/samudrace.py b/earth2studio/data/samudrace.py index d5cd8d33f..c2f9f7a2b 100644 --- a/earth2studio/data/samudrace.py +++ b/earth2studio/data/samudrace.py @@ -179,7 +179,8 @@ def _download_ic_file(self, component: str) -> str: if not os.path.exists(local_path): os.makedirs(os.path.dirname(local_path), exist_ok=True) hf_path = f"{self._HF_REPO_ID}/{filename}" - logger.info("Downloading SamudrACE {} IC: {}", component, hf_path) + if self._verbose: + logger.info("Downloading SamudrACE {} IC: {}", component, hf_path) self._hf_fs.get_file(hf_path, local_path) return local_path diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index f43f765b2..d5c442575 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -358,7 +358,6 @@ def load_model( SamudrACE prognostic model """ checkpoint_path = package.resolve("samudrACE_CM4_piControl_ckpt.tar") - logger.info("Loading SamudrACE coupled stepper from {}", checkpoint_path) coupled_stepper = load_coupled_stepper(checkpoint_path) return cls( coupled_stepper=coupled_stepper, @@ -487,7 +486,6 @@ def _ensure_forcing_file(self) -> str: hf_path = ( f"{self._HF_REPO_ID}/forcing_data/forcing_{self._forcing_scenario}.nc" ) - logger.info("Downloading SamudrACE forcing: {}", hf_path) hf_fs = HfFileSystem() hf_fs.get_file(hf_path, local_path) return local_path From 55515e685b99a7597594a879304559e3c8fada03 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 03:16:42 +0000 Subject: [PATCH 16/20] Tests --- test/data/test_samudrace_data.py | 167 +++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 test/data/test_samudrace_data.py diff --git a/test/data/test_samudrace_data.py b/test/data/test_samudrace_data.py new file mode 100644 index 000000000..b97072017 --- /dev/null +++ b/test/data/test_samudrace_data.py @@ -0,0 +1,167 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. +# SPDX-FileCopyrightText: All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import datetime +from unittest.mock import MagicMock, patch + +import numpy as np +import pytest +import xarray as xr + +from earth2studio.data.ace2 import ACE_GRID_LAT, ACE_GRID_LON +from earth2studio.data.samudrace import _IC_TIMESTAMPS, SamudrACEData + +# --------------------------------------------------------------------------- +# Fixtures +# --------------------------------------------------------------------------- +N_LAT = len(ACE_GRID_LAT) +N_LON = len(ACE_GRID_LON) + +# Representative atmosphere and ocean variable names (FME-side) +ATM_VARS = ["surface_temperature", "TMP2m", "PRESsfc"] +OCEAN_VARS = ["sst", "zos", "thetao_0"] + + +@pytest.fixture() +def mock_ic_datasets(tmp_path): + """Create minimal atmosphere and ocean IC NetCDF files on disk.""" + atm_ds = xr.Dataset() + for v in ATM_VARS: + atm_ds[v] = xr.DataArray( + np.random.randn(1, N_LAT, N_LON).astype(np.float32), + dims=["sample", "lat", "lon"], + ) + atm_ds = atm_ds.assign_coords( + lat=np.linspace(-89, 89, N_LAT).astype(np.float32), + lon=np.linspace(0.5, 359.5, N_LON).astype(np.float32), + ) + atm_path = tmp_path / "atm_ic.nc" + atm_ds.to_netcdf(atm_path) + + ocean_ds = xr.Dataset() + for v in OCEAN_VARS: + ocean_ds[v] = xr.DataArray( + np.random.randn(1, N_LAT, N_LON).astype(np.float32), + dims=["sample", "lat", "lon"], + ) + ocean_ds = ocean_ds.assign_coords( + lat=np.linspace(-89, 89, N_LAT).astype(np.float32), + lon=np.linspace(0.5, 359.5, N_LON).astype(np.float32), + ) + ocean_path = tmp_path / "ocean_ic.nc" + ocean_ds.to_netcdf(ocean_path) + + return atm_path, ocean_path, atm_ds, ocean_ds + + +def _make_data_source_with_local_ics(mock_ic_datasets): + """Create a SamudrACEData and inject pre-loaded datasets to skip HF.""" + atm_path, ocean_path, _, _ = mock_ic_datasets + with patch.object(SamudrACEData, "_download_ic_file"): + ds = SamudrACEData(ic_timestamp="0311-01-01T00:00:00") + ds._atm_ds = xr.open_dataset(atm_path, engine="netcdf4") + ds._ocean_ds = xr.open_dataset(ocean_path, engine="netcdf4") + return ds + + +# --------------------------------------------------------------------------- +# Tests: SamudrACEData +# --------------------------------------------------------------------------- +def test_samudrace_data_invalid_timestamp(): + """Invalid ic_timestamp raises ValueError.""" + with pytest.raises(ValueError, match="ic_timestamp must be one of"): + SamudrACEData(ic_timestamp="9999-01-01T00:00:00") + + +def test_samudrace_data_call_atm(mock_ic_datasets): + """Fetch atmosphere variables via __call__.""" + ds = _make_data_source_with_local_ics(mock_ic_datasets) + time = datetime.datetime(2001, 1, 1, 0) + da = ds(time, ["skt"]) # skt maps to surface_temperature + assert da.shape == (1, 1, N_LAT, N_LON) + np.testing.assert_array_equal(da.coords["lat"].values, ACE_GRID_LAT) + np.testing.assert_array_equal(da.coords["lon"].values, ACE_GRID_LON) + assert not np.isnan(da.values).any() + + +def test_samudrace_data_call_ocean(mock_ic_datasets): + """Fetch ocean variables via __call__.""" + ds = _make_data_source_with_local_ics(mock_ic_datasets) + time = [datetime.datetime(2001, 1, 1, 0), datetime.datetime(2001, 1, 2, 0)] + da = ds(time, ["sst", "zos"]) # identity-mapped ocean var names + assert da.shape == (2, 2, N_LAT, N_LON) + # Same spatial fields for both times + np.testing.assert_array_equal(da.values[0], da.values[1]) + + +def test_samudrace_data_call_mixed(mock_ic_datasets): + """Fetch a mix of atmosphere + ocean variables.""" + ds = _make_data_source_with_local_ics(mock_ic_datasets) + time = np.array([np.datetime64("2001-01-01T00:00")]) + da = ds(time, ["skt", "sst"]) + assert da.shape == (1, 2, N_LAT, N_LON) + + +def test_samudrace_data_unknown_variable(mock_ic_datasets): + """Unknown variable raises KeyError.""" + ds = _make_data_source_with_local_ics(mock_ic_datasets) + time = datetime.datetime(2001, 1, 1, 0) + with pytest.raises(KeyError, match="Unknown SamudrACE variable"): + ds(time, ["totally_fake_variable_xyz"]) + + +def test_samudrace_data_fetch_async(mock_ic_datasets): + """Async fetch returns same result as __call__.""" + import asyncio + + ds = _make_data_source_with_local_ics(mock_ic_datasets) + time = datetime.datetime(2001, 1, 1, 0) + result = asyncio.get_event_loop().run_until_complete(ds.fetch(time, ["skt"])) + assert result.shape == (1, 1, N_LAT, N_LON) + + +def test_samudrace_data_cache_property(): + """Verify cache paths for cached and non-cached modes.""" + with patch.object(SamudrACEData, "__init__", lambda self, **kw: None): + ds = SamudrACEData.__new__(SamudrACEData) + ds._cache = True + ds._ic_timestamp = "0311-01-01T00:00:00" + ds._verbose = True + ds._hf_fs = MagicMock() + ds._atm_ds = None + ds._ocean_ds = None + ds.lat = ACE_GRID_LAT + ds.lon = ACE_GRID_LON + cached_path = ds.cache + assert "SamudrACE" in cached_path + assert "tmp_SamudrACE" not in cached_path + + ds._cache = False + uncached_path = ds.cache + assert "tmp_SamudrACE" in uncached_path + + +def test_samudrace_data_available_timestamps(): + """Verify all documented timestamps are valid.""" + expected = { + "0151-01-06T00:00:00", + "0311-01-01T00:00:00", + "0313-01-01T00:00:00", + "0315-01-01T00:00:00", + "0317-01-01T00:00:00", + "0319-01-01T00:00:00", + } + assert set(_IC_TIMESTAMPS.keys()) == expected From c11ab3c9671361c8833ea669003193636698ef49 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 22:58:01 +0000 Subject: [PATCH 17/20] Clean up --- earth2studio/models/px/samudrace.py | 75 +++++------------ test/models/px/test_samudrace.py | 120 +++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 58 deletions(-) diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index d5c442575..dfa8d52ae 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -173,6 +173,7 @@ def __init__( self._dt = dt self._forcing_scenario = forcing_scenario self._forcing_ds: xr.Dataset | None = None + self._hf_fs: HfFileSystem | None = None self.lexicon = SamudrACELexicon # Register a buffer for device tracking @@ -216,18 +217,12 @@ def __init__( self._prog_e2s = self._atm_prog_e2s + self._ocean_prog_e2s self._all_out_e2s = self._atm_out_e2s + self._ocean_out_e2s - # Identify atmosphere forcing variables that must come from external - # data rather than from inter-component coupling. The coupled stepper - # handles ocean↔atmosphere exchange internally; we only need to feed - # the *exogenous* forcings that neither component produces. + # Forcing vars not produced by ocean (excludes ocean→atm coupled fields) ocean_out_set = set(ocean_out_fme) self._exogenous_forcing_fme = sorted( v for v in atm_forcing_fme if v not in ocean_out_set ) - # The coupled ocean→atmosphere exchange supplies surface_temperature, - # sea_ice_fraction, and ocean_fraction — everything else must come - # from external data (including time-varying forcings like DSWRFtoa - # AND static fields like HGTsfc, land_fraction, lake_fraction). + # External forcing: exogenous vars minus coupled fields (ocean_fraction, etc.) _coupled_fields = {"ocean_fraction", "sea_ice_fraction"} self._external_forcing_fme: list[str] = [] for v in self._exogenous_forcing_fme: @@ -293,8 +288,6 @@ def output_coords(self, input_coords: CoordSystem) -> CoordSystem: "lon": self.lon, } ) - if input_coords is None: - return output_coords test_coords = input_coords.copy() test_coords["lead_time"] = ( @@ -401,11 +394,7 @@ def _prescribe_ic_sst( atmos_ic_state: PrognosticState, atmos_forcing: BatchData, ) -> PrognosticState: - """This mirrors CoupledStepper._prescribe_ic_sst in FME which blends - the ocean-sourced ``surface_temperature`` into the atmosphere initial - condition using ``ocean_fraction`` as a mask (interpolation mode). - """ - # Extract the IC-timestep slice from forcing (n_ic_timesteps == 1) + """Blend ocean SST into atmosphere IC using ocean_fraction mask.""" forcing_ic = atmos_forcing.select_time_slice( slice(None, self.coupled_stepper.atmosphere.n_ic_timesteps) ) @@ -486,8 +475,9 @@ def _ensure_forcing_file(self) -> str: hf_path = ( f"{self._HF_REPO_ID}/forcing_data/forcing_{self._forcing_scenario}.nc" ) - hf_fs = HfFileSystem() - hf_fs.get_file(hf_path, local_path) + if self._hf_fs is None: + self._hf_fs = HfFileSystem() + self._hf_fs.get_file(hf_path, local_path) return local_path def _open_forcing_ds(self) -> xr.Dataset: @@ -634,7 +624,6 @@ def _forward( ] time_array = np.array(abs_times) - # Fetch external forcing for this single step (IC + 1 forward = 2 timesteps) atm_forcing_data: dict[str, torch.Tensor] = {} if self._external_forcing_fme: @@ -648,45 +637,34 @@ def _forward( slices.append(val) atm_forcing_data[fme_name] = torch.stack(slices, dim=1) - # Add ocean-sourced forcing: SST, ocean_fraction, sea_ice_fraction - # These are held constant for all inner atmosphere steps. - # This mirrors CoupledStepper._get_atmosphere_forcings and - # _forcings_from_ocean_with_ocean_fraction in FME. + # Ocean-sourced forcing: SST, ocean_fraction, sea_ice_fraction ocean_bd = ocean_state.as_batch_data() coupled_config = self.coupled_stepper._config - # SST → atmosphere surface_temperature + # SST → surface_temperature sst_name = coupled_config.sst_name if sst_name in ocean_bd.data: - sst_val = ocean_bd.data[sst_name][:, -1:, ...] # last timestep + sst_val = ocean_bd.data[sst_name][:, -1:, ...] atm_forcing_data["surface_temperature"] = sst_val.expand(-1, 2, -1, -1) - # Sea ice fraction and ocean fraction — derived from ocean's - # ocean_sea_ice_fraction via the CoupledOceanFractionConfig when - # available, otherwise look for direct sea_ice_fraction/ocean_fraction. - # Track which names are ocean-sourced for mask zeroing below. + # Derive sea_ice_fraction and ocean_fraction from ocean state ocean_sourced_names: list[str] = ["surface_temperature"] ofp = coupled_config.ocean_fraction_prediction if ofp is not None: - sic_name = ofp.sea_ice_fraction_name # e.g. "ocean_sea_ice_fraction" - land_name = ofp.land_fraction_name # e.g. "land_fraction" - atm_sic_name = ofp.sea_ice_fraction_name_in_atmosphere # "sea_ice_fraction" + sic_name = ofp.sea_ice_fraction_name + land_name = ofp.land_fraction_name + atm_sic_name = ofp.sea_ice_fraction_name_in_atmosphere - # Compute atmosphere-facing sea_ice and ocean_fraction from ocean. if sic_name in ocean_bd.data: - # FME: nan_to_num on ocean sea-ice before deriving fractions osic = torch.nan_to_num(ocean_bd.data[sic_name][:, -1:, ...]) - # land_fraction comes from external forcing, not atmosphere - # prognostic state (which never contains it). land_frac = atm_forcing_data[land_name][:, :1, ...] - # sea_ice_fraction = ocean_sea_ice_fraction * (1 - land_fraction) sic_atm = osic * (1.0 - land_frac) atm_forcing_data[atm_sic_name] = sic_atm.expand(-1, 2, -1, -1) - # ocean_fraction = clip(1 - land - sea_ice, min=0) ocean_frac = torch.clip(1.0 - land_frac - sic_atm, min=0) atm_forcing_data["ocean_fraction"] = ocean_frac.expand(-1, 2, -1, -1) ocean_sourced_names += [atm_sic_name, "ocean_fraction"] else: + # Fallback: use direct sea_ice_fraction/ocean_fraction if available if "sea_ice_fraction" in ocean_bd.data: sic_val = ocean_bd.data["sea_ice_fraction"][:, -1:, ...] atm_forcing_data["sea_ice_fraction"] = sic_val.expand(-1, 2, -1, -1) @@ -697,9 +675,7 @@ def _forward( atm_forcing_data["ocean_fraction"] = of_val.expand(-1, 2, -1, -1) ocean_sourced_names.append("ocean_fraction") - # Apply ocean mask zeroing: set ocean-invalid grid points to 0. - # This mirrors CoupledStepper._forcings_from_ocean_with_ocean_fraction - # (FME lines 979-984) which uses _ocean_mask_provider. + # Zero ocean-invalid grid points using mask provider ocean_mask_provider = self.coupled_stepper._ocean_mask_provider for oname in ocean_sourced_names: if oname in atm_forcing_data: @@ -711,19 +687,9 @@ def _forward( mask != 0, 0 ) - # Fallback: static fields from atmosphere state if not already provided - # by the external data source above. - atm_bd = atm_state.as_batch_data() - for static_name in ["land_fraction", "lake_fraction", "HGTsfc"]: - if static_name not in atm_forcing_data and static_name in atm_bd.data: - static_val = atm_bd.data[static_name][:, -1:, ...] - atm_forcing_data[static_name] = static_val.expand(-1, 2, -1, -1) - atm_forcing = self._build_batch_data(atm_forcing_data, time_array, n_flat) - # Prescribe ocean SST onto the atmosphere IC surface_temperature. - # This mirrors FME's CoupledStepper._prescribe_ic_sst which blends - # ocean SST into the atmosphere IC at the start of each coupled cycle. + # Prescribe ocean SST onto atmosphere IC at start of each coupled cycle if step_in_cycle == 0: atm_state = self._prescribe_ic_sst(atm_state, atm_forcing) @@ -810,19 +776,18 @@ def _run_ocean_step( stacked = torch.stack([f[key] for f in flux_accum], dim=1) avg_forcing[key] = stacked.mean(dim=1, keepdim=True) - # Ocean expects 2 timesteps: IC + 1 forward step - # Expand forcing to 2 timesteps (IC has NaN, forward step has averaged flux) + # Build 2-timestep forcing: IC (NaN) + forward step (averaged flux) ocean_forcing_data: dict[str, torch.Tensor] = {} n_flat = list(avg_forcing.values())[0].shape[0] for key, val in avg_forcing.items(): nan_pad = torch.full_like(val, float("nan")) ocean_forcing_data[key] = torch.cat([nan_pad, val], dim=1) - # Add land_fraction from forcing file (static field needed by ocean stepper) + # Add land_fraction (static field needed by ocean stepper) lf_val = self._get_forcing_slice("land_fraction", 1, 1, 0, n_flat) ocean_forcing_data["land_fraction"] = lf_val.unsqueeze(1).expand(-1, 2, -1, -1) - # Build time array for ocean forcing (2 timesteps spanning the 5-day window) + # Build time array for ocean forcing (2 timesteps over 5-day window) ocean_dt = np.timedelta64(5, "D") time_array = np.array( ( diff --git a/test/models/px/test_samudrace.py b/test/models/px/test_samudrace.py index c4ed45629..3ce699e0a 100644 --- a/test/models/px/test_samudrace.py +++ b/test/models/px/test_samudrace.py @@ -104,6 +104,8 @@ class PhooOutput: class PhooStepper(torch.nn.Module): """Mock single-component stepper matching the FME Stepper interface.""" + TIME_DIM = 1 + def __init__( self, prognostic_names: list, @@ -121,6 +123,22 @@ def prescribe_sst(self, mask_data, gen_data, target_data): """Mock SST prescription that returns gen_data unchanged.""" return dict(gen_data) + def get_prediction_generator(self, ic, forcing_batch, n_forward_steps, optimizer): + """Mock get_prediction_generator matching FME Stepper interface. + + Yields one TensorDict per step with tensors of shape [batch, lat, lon] + (no time dimension), matching the real Stepper.predict_generator output. + """ + first_key = self.prognostic_names[0] + batch, _, lat, lon = ic._data.data[first_key].shape + device = self.device_buffer.device + for _ in range(n_forward_steps): + step_data = { + key: torch.randn(batch, lat, lon, device=device) + for key in self.out_names + } + yield step_data + def predict_paired(self, ic, forcing_batch): first_key = self.prognostic_names[0] batch, _, lat, lon = ic._data.data[first_key].shape @@ -167,6 +185,8 @@ class PhooCoupledConfig: """Mock coupled stepper config.""" sst_name = "sst" + surface_temperature_name = "surface_temperature" + ocean_fraction_name = "ocean_fraction" ocean_fraction_prediction = PhooCoupledOceanFractionConfig() @@ -185,6 +205,58 @@ def __init__(self): self.ocean = PhooStepper(OCEAN_PROGNOSTIC, OCEAN_INPUT_ONLY, OCEAN_OUT) self._config = PhooCoupledConfig() self._ocean_mask_provider = PhooMaskProvider() + # Ocean-to-atmosphere forcing names: SST + sea ice (from ofp config) + self._ocean_to_atmosphere_forcing_names = [ + "sst", + "ocean_sea_ice_fraction", + ] + + def _forcings_from_ocean_with_ocean_fraction( + self, forcings_from_ocean, atmos_forcing_data + ): + """Mock: compute ocean/sea-ice fraction and apply ocean mask zeroing.""" + forcings_from_ocean = dict(forcings_from_ocean) + ofrac_config = self._config.ocean_fraction_prediction + if ofrac_config is not None: + sic_name = ofrac_config.sea_ice_fraction_name + land_name = ofrac_config.land_fraction_name + atm_sic_name = ofrac_config.sea_ice_fraction_name_in_atmosphere or sic_name + if sic_name in forcings_from_ocean: + sic = torch.nan_to_num(forcings_from_ocean[sic_name]) + land = atmos_forcing_data[land_name][:, :1, ...] + sic_atm = sic * (1.0 - land) + forcings_from_ocean[atm_sic_name] = sic_atm.expand( + -1, sic.shape[1], -1, -1 + ) + forcings_from_ocean[self._config.ocean_fraction_name] = torch.clip( + 1.0 - land - sic_atm, min=0 + ).expand(-1, sic.shape[1], -1, -1) + # Ocean mask zeroing (no-op with PhooMaskProvider) + for name, tensor in forcings_from_ocean.items(): + mask = self._ocean_mask_provider.get_mask_tensor_for(name) + if mask is not None: + mask = mask.expand(tensor.shape) + forcings_from_ocean[name] = tensor.where(mask != 0, 0) + return forcings_from_ocean + + def _prescribe_ic_sst(self, atmos_ic_state, forcing_ic_batch): + """Mock: delegate to atmosphere's prescribe_sst.""" + from fme.ace.data_loading.batch_data import BatchData, PrognosticState + + atmos_ic_data = atmos_ic_state.as_batch_data().data + forcing_ic_data = forcing_ic_batch.data + prescribed = self.atmosphere.prescribe_sst( + mask_data=forcing_ic_data, + gen_data=atmos_ic_data, + target_data=forcing_ic_data, + ) + return PrognosticState( + BatchData( + data=prescribed, + time=forcing_ic_batch.time, + labels=forcing_ic_batch.labels, + ) + ) def to(self, device): self.atmosphere = self.atmosphere.to(device) @@ -196,17 +268,17 @@ def to(self, device): def dummy_forcing_ds(tmp_path_factory): """Create a minimal forcing xarray Dataset for mock tests. - Contains DSWRFtoa (time-varying, 3 days of 6h steps) plus static fields + Contains DSWRFtoa (time-varying, 7 days of 6h steps) plus static fields HGTsfc, land_fraction, and lake_fraction. """ n_lat = len(ACE_GRID_LAT) n_lon = len(ACE_GRID_LON) - # 12 time steps covering 3 days at 6h cadence + # 28 time steps covering 7 days at 6h cadence (enough for ocean step test) import cftime times = [ cftime.DatetimeNoLeap(2001, 1, d + 1, h) - for d in range(3) + for d in range(7) for h in (0, 6, 12, 18) ] @@ -317,6 +389,48 @@ def test_samudrace_iter(dummy_forcing_ds, batch, device): break +@pytest.mark.parametrize("device", ["cuda:0"]) +def test_samudrace_iter_ocean_step(dummy_forcing_ds, device): + """Test that ocean step is triggered after N_INNER_STEPS (20 atm steps = 5 days).""" + torch.cuda.empty_cache() + time = np.array([np.datetime64("2001-01-01T00:00")]) + + coupled = PhooCoupledStepper().to(device) + p = SamudrACE(coupled).to(device) + # Inject dummy forcing dataset to bypass HuggingFace download + p._forcing_ds = dummy_forcing_ds + + dc = p.input_coords() + del dc["batch"] + del dc["time"] + del dc["lead_time"] + del dc["variable"] + r = Random(dc) + + lead_time = p.input_coords()["lead_time"] + variable = p.input_coords()["variable"] + x, coords = fetch_data(r, time, variable, lead_time, device=device) + + p_iter = p.create_iterator(x, coords) + + # First yield returns IC + out, out_coords = next(p_iter) + assert out_coords["lead_time"][0] == np.timedelta64(0, "h") + + # Run 21 iterations to trigger the ocean step (occurs at step 20) + # N_INNER_STEPS = 20, so ocean step triggers after 20 atmosphere steps + for i, (out, out_coords) in enumerate(p_iter): + assert len(out.shape) == 5 + expected_lead = np.timedelta64(6 * (i + 1), "h") + assert out_coords["lead_time"][0] == expected_lead + if i >= 20: + # After 21 iterations we've completed one full ocean cycle + break + + # Verify we reached the expected lead time (21 * 6h = 126h = 5.25 days) + assert out_coords["lead_time"][0] == np.timedelta64(126, "h") + + @pytest.mark.package @pytest.mark.parametrize("device", ["cuda:0"]) def test_samudrace_package(device): From 96a96546fab47e29033816eb45f37e9b250c25f0 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 23:04:49 +0000 Subject: [PATCH 18/20] Greptile --- earth2studio/data/samudrace.py | 3 +++ earth2studio/models/px/samudrace.py | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/earth2studio/data/samudrace.py b/earth2studio/data/samudrace.py index c2f9f7a2b..4c09b227e 100644 --- a/earth2studio/data/samudrace.py +++ b/earth2studio/data/samudrace.py @@ -245,6 +245,9 @@ def _fetch_initial_conditions( result = result.transpose("time", "variable", "lat", "lon") if not self._cache: + result = result.load() # Materialise before files are deleted shutil.rmtree(self.cache, ignore_errors=True) + self._atm_ds = None # Reset so re-download works on next call + self._ocean_ds = None return result diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index dfa8d52ae..2e0b0e9fe 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -54,6 +54,9 @@ # Number of atmosphere 6h steps in one coupled (ocean) 5-day cycle N_INNER_STEPS = 20 +# Valid forcing scenario identifiers +_VALID_FORCING_SCENARIOS = {"0151", "0311"} + def _npdatetime64_to_cftime(dt64_array: np.ndarray) -> np.ndarray: """Convert np.datetime64 array to cftime.DatetimeProlepticGregorian array. @@ -169,6 +172,12 @@ def __init__( ): super().__init__() + if forcing_scenario not in _VALID_FORCING_SCENARIOS: + raise ValueError( + f"forcing_scenario must be one of {sorted(_VALID_FORCING_SCENARIOS)}, " + f"got {forcing_scenario!r}" + ) + self.coupled_stepper = coupled_stepper self._dt = dt self._forcing_scenario = forcing_scenario From 4eb48d1f5bee1fcd74ec2de957be8526fcb30755 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Tue, 31 Mar 2026 23:11:58 +0000 Subject: [PATCH 19/20] Greptile --- earth2studio/data/samudrace.py | 2 +- earth2studio/models/px/samudrace.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/earth2studio/data/samudrace.py b/earth2studio/data/samudrace.py index 4c09b227e..2becf8119 100644 --- a/earth2studio/data/samudrace.py +++ b/earth2studio/data/samudrace.py @@ -72,7 +72,7 @@ class SamudrACEData: Badges ------ - region:global dataclass:reanalysis product:temp product:atmos product:ocean + region:global dataclass:simulation product:temp product:atmos product:ocean """ _HF_REPO_ID = "allenai/SamudrACE-CM4-piControl" diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index 2e0b0e9fe..cff6d0e59 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -158,8 +158,8 @@ class SamudrACE(torch.nn.Module, AutoModelMixin, PrognosticMixin): Badges ------ - region:global class:cm product:temp product:atmos product:ocean year:2025 - gpu:40gb + region:global class:cm product:wind product:precip product:temp product:atmos + product:ocean product:solar year:2025 gpu:40gb """ _HF_REPO_ID = "allenai/SamudrACE-CM4-piControl" From a992cc6becf511862e0225b5c69e83eb3c245cc7 Mon Sep 17 00:00:00 2001 From: Nicholas Geneva <ngeneva@nvidia.com> Date: Wed, 1 Apr 2026 00:03:17 +0000 Subject: [PATCH 20/20] ocean levels to m --- earth2studio/data/samudrace.py | 5 +-- earth2studio/lexicon/samudrace.py | 52 ++++++++++++++++++++++++----- earth2studio/models/px/samudrace.py | 21 +++++++++--- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/earth2studio/data/samudrace.py b/earth2studio/data/samudrace.py index 2becf8119..5270f24a9 100644 --- a/earth2studio/data/samudrace.py +++ b/earth2studio/data/samudrace.py @@ -46,7 +46,8 @@ class SamudrACEData: the SamudrACE HuggingFace repository. Each initial condition has separate atmosphere and ocean NetCDF files that are downloaded, merged, and served as a single ``xr.DataArray`` with all 118 prognostic variables (38 - atmosphere + 80 ocean). + atmosphere + 80 ocean). Ocean variables use depth-based names (e.g., + ``thetao2p5m``, ``so250m``) matching the Samudra paper. The SamudrACE checkpoint was trained on a GFDL CM4 preindustrial-control run. Initial conditions are identified by their CM4 model-year timestamp @@ -125,7 +126,7 @@ def __call__( # Map E2S → FME variable names try: - var_list_fme = [SamudrACELexicon[v][0] for v in var_list_e2s] + var_list_fme = [SamudrACELexicon[v][0] for v in var_list_e2s] # type: ignore[misc] except KeyError as e: raise KeyError(f"Unknown SamudrACE variable id: {e}") from e diff --git a/earth2studio/lexicon/samudrace.py b/earth2studio/lexicon/samudrace.py index 404d02a6f..acbcad1cf 100644 --- a/earth2studio/lexicon/samudrace.py +++ b/earth2studio/lexicon/samudrace.py @@ -22,6 +22,36 @@ from .base import LexiconType +# Ocean depth levels from Samudra paper (metres) +# See: https://arxiv.org/abs/2412.03795 +OCEAN_DEPTHS = [ + 2.5, + 10, + 22.5, + 40, + 65, + 105, + 165, + 250, + 375, + 550, + 775, + 1050, + 1400, + 1850, + 2400, + 3100, + 4000, + 5000, + 6000, +] + + +def _depth_to_str(depth: float) -> str: + """Convert depth to string format, replacing '.' with 'p' for variable names.""" + s = f"{depth:g}" + return s.replace(".", "p") + def _build_variable_mappings() -> tuple[dict[str, str], dict[str, str]]: """Build bidirectional mappings between Earth2Studio and FME variable names @@ -82,12 +112,13 @@ def _build_variable_mappings() -> tuple[dict[str, str], dict[str, str]]: mapping[f"t{k}k"] = f"air_temperature_{k}" mapping[f"qtot{k}k"] = f"specific_total_water_{k}" - # ---- Ocean: depth-level variables (19 levels, 0..18) ---- - for d in range(19): - mapping[f"thetao_{d}"] = f"thetao_{d}" - mapping[f"so_{d}"] = f"so_{d}" - mapping[f"uo_{d}"] = f"uo_{d}" - mapping[f"vo_{d}"] = f"vo_{d}" + # ---- Ocean: depth-level variables (19 depths in metres) ---- + for d, depth in enumerate(OCEAN_DEPTHS): + depth_str = f"{_depth_to_str(depth)}m" # "2p5m", "10m", "22p5m", etc. + mapping[f"thetao{depth_str}"] = f"thetao_{d}" + mapping[f"so{depth_str}"] = f"so_{d}" + mapping[f"uo{depth_str}"] = f"uo_{d}" + mapping[f"vo{depth_str}"] = f"vo_{d}" fme_to_e2s = {v: k for k, v in mapping.items()} return mapping, fme_to_e2s @@ -102,13 +133,18 @@ class SamudrACELexicon(metaclass=LexiconType): Maps Earth2Studio variable names to the variable labels used by the FME CoupledStepper for the SamudrACE coupled atmosphere-ocean model. Covers - both atmosphere (CM4 model levels) and ocean (CMIP6 naming) variables. + both atmosphere (CM4 model levels) and ocean (depth-based naming) variables. + + Ocean variables use depth-based names with 'p' replacing decimal points + (e.g., ``thetao2p5m`` for 2.5m depth, ``so250m`` for 250m depth). Examples -------- >>> from earth2studio.lexicon.samudrace import SamudrACELexicon >>> SamudrACELexicon["u10m"] ("UGRD10m", <function mod at 0x...>) + >>> SamudrACELexicon["thetao2p5m"] + ("thetao_0", <function mod at 0x...>) >>> SamudrACELexicon.get_e2s_from_fme("sst") "sst" """ @@ -132,7 +168,7 @@ def get_item(cls, val: str) -> tuple[str, Callable]: """ fme_key = cls.VOCAB[val] - def mod(x: np.array) -> np.array: + def mod(x: np.ndarray) -> np.ndarray: return x return fme_key, mod diff --git a/earth2studio/models/px/samudrace.py b/earth2studio/models/px/samudrace.py index cff6d0e59..32b3dfe71 100644 --- a/earth2studio/models/px/samudrace.py +++ b/earth2studio/models/px/samudrace.py @@ -134,11 +134,21 @@ class SamudrACE(torch.nn.Module, AutoModelMixin, PrognosticMixin): 8 0 1.000 ==== ======== ======= - The ocean component uses 19 layers defined by 20 interface (half-level) - depths from the GFDL CM4 ocean grid. The interface depths in metres are: - - ``[0, 5, 15, 30, 50, 80, 130, 200, 300, 450, 650, 900, 1200, 1600, - 2100, 2700, 3500, 4500, 5500, 6500]`` + The ocean component uses 19 fixed-depth layers from the GFDL CM4 ocean + grid. Ocean variables use depth-based names (e.g., ``thetao2p5m``, + ``so250m``). Layer index to depth (metres): + + ==== ======= ==== ======= ==== ======= + k depth k depth k depth + ==== ======= ==== ======= ==== ======= + 0 2.5 7 250 14 2400 + 1 10 8 375 15 3100 + 2 22.5 9 550 16 4000 + 3 40 10 775 17 5000 + 4 65 11 1050 18 6000 + 5 105 12 1400 + 6 165 13 1850 + ==== ======= ==== ======= ==== ======= Parameters ---------- @@ -154,6 +164,7 @@ class SamudrACE(torch.nn.Module, AutoModelMixin, PrognosticMixin): References ---------- - SamudrACE paper: https://arxiv.org/abs/2509.12490 + - Samudra: https://arxiv.org/pdf/2412.03795 - ACE2 code: https://github.com/ai2cm/ace Badges