Skip to content

Commit 8a8f4ae

Browse files
committed
Merge branch 'main' of github.com:ArcticSnow/TopoPyScale into main
2 parents abdd141 + 24fbaa4 commit 8a8f4ae

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

.github/copilot-instructions.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copilot Instructions for TopoPyScale
2+
3+
## Project Overview
4+
TopoPyScale is a Python package for topography-based downscaling of climate data to hillslope scale. It processes climate reanalysis data (ERA5, etc.) and digital elevation models (DEM) to produce outputs for models like Cryogrid and FSM. The codebase is organized as a PyPI library, with main logic in the `TopoPyScale/` directory and documentation in `doc/`.
5+
6+
## Key Components
7+
- **Core Library:** All main modules are in `TopoPyScale/`. Each file typically handles a specific aspect (e.g., `fetch_dem.py` for DEM fetching, `topo_scale.py` for downscaling logic).
8+
- **Documentation:** Markdown docs are in `doc/docs/`. API docs are auto-generated using `lazydocs`.
9+
- **Configuration:** Project uses `pyproject.toml` and `MANIFEST.in` for packaging. Documentation build is managed by `mkdocs.yml`.
10+
11+
## Developer Workflows
12+
- **Testing:** GitHub Actions run tests via `test_topopyscale.yml`. Local test commands are not specified; add/maintain tests in the main package directory.
13+
- **Documentation:**
14+
- Edit docs in `doc/docs/`.
15+
- Build locally: `mkdocs serve` (see `doc/README.md`).
16+
- API docs: Run `lazydocs` as described in `doc/README.md`.
17+
- **Releases:** Create a new branch for features/bugfixes, merge to `main`, then follow release video guide (see `README.md`).
18+
19+
## Project-Specific Patterns
20+
- **Data Flow:**
21+
- Inputs: Climate data (ERA5, CORDEX), DEM (local or fetched).
22+
- Processing: DEM-derived values, clustering (k-means), interpolation (bilinear, inverse square distance).
23+
- Outputs: Cryogrid/FSM formats.
24+
- **Contribution:**
25+
- Issues/discussions on GitHub.
26+
- Branching for features/bugfixes is encouraged.
27+
- **Docs Build:** Changes to docs auto-build on ReadTheDocs when committed.
28+
29+
## Integration Points
30+
- **External Data:** Fetches DEM from public repositories (SRTM, ArcticDEM, ASTER).
31+
- **Dependencies:** See `pyproject.toml` and `doc/requirements.txt` for required packages (e.g., `mkdocs`, `lazydocs`).
32+
33+
## Examples
34+
- To fetch DEM: see `fetch_dem.py`.
35+
- To run downscaling: see `topo_scale.py` and related modules.
36+
- To build docs locally:
37+
```bash
38+
pip install mkdocs sphinx_rtd_theme mkdocs-material pygments
39+
mkdocs serve
40+
# Open http://127.0.0.1:8000/
41+
```
42+
- To update API docs:
43+
```bash
44+
lazydocs --output-path="doc/docs" --overview-file="README.md" --src-base-url="https://github.com/ArcticSnow/TopoPyScale" TopoPyScale
45+
```
46+
47+
## References
48+
- Main documentation: https://topopyscale.readthedocs.io
49+
- Release workflow: https://www.youtube.com/watch?v=Ob9llA_QhQY
50+
51+
---
52+
**Feedback:** Please review and suggest updates for any unclear or missing sections.

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"python-envs.defaultEnvManager": "ms-python.python:conda",
3+
"python-envs.defaultPackageManager": "ms-python.python:conda",
4+
"python-envs.pythonProjects": []
5+
}

TopoPyScale/topo_param.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,24 @@ def compute_dem_param(dem_file, fname='ds_param.nc', project_directory=Path('./'
190190
file_ds = pdir / output_folder / fname
191191
if file_ds.is_file():
192192
print(f'\n---> Dataset {fname} found.')
193-
ds = xr.open_dataset(file_ds)
193+
try:
194+
ds = xr.open_dataset(file_ds)
195+
# Test if we can actually read the elevation data
196+
_ = ds.elevation.values
197+
except (RuntimeError, OSError) as e:
198+
if "NetCDF: HDF error" in str(e) or "filter returned failure" in str(e):
199+
print(f'\n---> Dataset {fname} corrupted (HDF/compression error). Trying h5netcdf backend...')
200+
try:
201+
ds = xr.open_dataset(file_ds, engine='h5netcdf')
202+
_ = ds.elevation.values
203+
except Exception:
204+
print(f'\n---> h5netcdf backend failed. Regenerating dataset from DEM...')
205+
if Path(dem_file).is_file():
206+
ds = open_dem(dem_file)
207+
else:
208+
raise ValueError(f'ERROR: Dataset corrupted and no DEM available to regenerate')
209+
else:
210+
raise e
194211

195212
else:
196213
if Path(dem_file).is_file():
@@ -204,7 +221,29 @@ def compute_dem_param(dem_file, fname='ds_param.nc', project_directory=Path('./'
204221
print('\n---> Extracting DEM parameters (slope, aspect, svf)')
205222
dx = ds.x.diff('x').median().values
206223
dy = ds.y.diff('y').median().values
207-
dem_arr = ds.elevation.values
224+
225+
# Safely access elevation data with error handling
226+
try:
227+
dem_arr = ds.elevation.values
228+
except (RuntimeError, OSError) as e:
229+
if "NetCDF: HDF error" in str(e) or "filter returned failure" in str(e):
230+
print(f'---> Error reading elevation data: {str(e)}')
231+
print('---> Attempting to load elevation data with different method...')
232+
try:
233+
# Try loading the data chunk by chunk or using compute()
234+
dem_arr = ds.elevation.load().values
235+
except Exception:
236+
# If all else fails, regenerate from DEM file
237+
print('---> All methods failed. Regenerating from original DEM...')
238+
if Path(dem_file).is_file():
239+
ds_new = open_dem(dem_file)
240+
dem_arr = ds_new.elevation.values
241+
ds = ds_new
242+
var_in = list(ds.variables.keys())
243+
else:
244+
raise ValueError(f'ERROR: Cannot read elevation data and no DEM file available')
245+
else:
246+
raise e
208247

209248
if ('slope' not in var_in) or ('aspect' not in var_in):
210249
print('Computing slope and aspect ...')

0 commit comments

Comments
 (0)