https://github.com/koldunovn/fesomp
helper functions to work with FESOM2 data
https://github.com/koldunovn/fesomp
ocean-modelling ocean-sciences oceanography
Last synced: 6 months ago
JSON representation
helper functions to work with FESOM2 data
- Host: GitHub
- URL: https://github.com/koldunovn/fesomp
- Owner: koldunovn
- License: mit
- Created: 2026-01-17T21:33:49.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-18T17:46:27.000Z (6 months ago)
- Last Synced: 2026-01-18T21:52:16.778Z (6 months ago)
- Topics: ocean-modelling, ocean-sciences, oceanography
- Language: Python
- Homepage: https://fesomp.readthedocs.io/en/latest/
- Size: 6.52 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# FESOMP
A modern Python library for working with FESOM2 (Finite Element Sea ice-Ocean Model) unstructured mesh data.
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
## Features
### Mesh Management
- π **Flexible I/O**: Load meshes from NetCDF or ASCII formats
- β‘ **Lazy Loading**: Topology, geometry, and spatial indices computed on-demand
- π **Dual Coordinates**: Automatic handling of node and element (triangle center) data
- π **Spatial Queries**: Fast nearest-neighbor search, radius queries, and bounding box selection
### Data Interpolation
- π― **Three Methods**: Nearest neighbor (fast), inverse distance weighting (smooth), and linear interpolation
- π **Regular Grid**: Interpolate unstructured data to regular lon/lat grids
- πΎ **Caching**: Reusable interpolators for efficient multi-variable processing
- π **Spherical Geometry**: Accurate great circle calculations on the sphere
### Visualization
- πΊοΈ **Map Plots**: Cartopy integration with multiple projections (PlateCarree, Robinson, Polar, etc.)
- π **Transect Plots**: Vertical cross-sections with automatic vertical coordinate detection
- π¨ **Customizable**: Full control over colormaps, contours, labels, and styling
- π **Auto-Detection**: Automatically determines if data is on nodes/elements and levels/layers
## Installation
### From PyPI
```bash
pip install fesomp
```
### From source
```bash
git clone https://github.com/nkolduno/fesomp.git
cd fesomp
pip install -e .
```
### Dependencies
Core dependencies:
- `numpy >= 1.20`
- `scipy >= 1.7`
- `xarray >= 0.19`
- `pandas >= 1.3`
- `matplotlib >= 3.5`
- `cartopy >= 0.20`
- `netCDF4 >= 1.5`
Development dependencies:
```bash
pip install -e ".[dev]" # Includes pytest, pytest-cov, hypothesis
```
## Quick Start
### Load a mesh
```python
import fesomp
# From NetCDF
mesh = fesomp.load_mesh("path/to/fesom.mesh.diag.nc")
# From ASCII directory
mesh = fesomp.load_mesh("path/to/mesh/directory/")
print(mesh)
# Mesh(n2d=126859, nelem=237843, nlev=47, lon=[-180.00, 180.00], lat=[-90.00, 90.00])
```
### Plot 2D data on a map
```python
import xarray as xr
# Load surface temperature
sst = xr.open_dataset("sst.fesom.1958.nc")['sst'][0, :].values
# Create a map
fig, axes, interp = fesomp.plot(
sst,
mesh.lon,
mesh.lat,
mapproj="robinson",
title="Sea Surface Temperature",
units="Β°C",
cmap="RdYlBu_r",
)
```
### Create a vertical transect
```python
# Load 3D temperature data
temp_3d = xr.open_dataset("temp.fesom.1958.nc")['temp'][0, :, :].values
# Atlantic meridional transect
fig, ax, interp = fesomp.transect(
temp_3d, # shape: (nlev, n2d)
mesh,
start=(-30, -60), # 30Β°W, 60Β°S
end=(-30, 60), # 30Β°W, 60Β°N
title="Temperature along 30Β°W",
units="Β°C",
depth_limits=(0, 2000), # Top 2000 meters
)
```
### Interpolate to regular grid
```python
# Quick interpolation
data_reg, lon_reg, lat_reg = fesomp.regrid(
sst,
mesh.lon,
mesh.lat,
res=(360, 180),
method="idw",
)
# Reusable interpolator (faster for multiple variables)
interp = fesomp.RegridInterpolator(
mesh.lon, mesh.lat,
res=(360, 180),
method="idw",
)
temp_reg, lon_reg, lat_reg = interp(sst)
salt_reg, _, _ = interp(salinity) # Reuses pre-computed weights
```
## Advanced Features
### Automatic Detection
The library automatically detects:
**Horizontal location:**
```python
# Data on nodes (n2d points)
temp_nodes = temp_3d # shape: (nlev, n2d)
fesomp.transect(temp_nodes, mesh, ...) # Uses mesh.lon, mesh.lat
# Data on elements (nelem points)
u_velocity = u_3d # shape: (nlev, nelem)
fesomp.transect(u_velocity, mesh, ...) # Uses mesh.lon_elem, mesh.lat_elem
```
**Vertical coordinate:**
```python
# Data on levels (interfaces) - nlev points
w_velocity # shape: (nlev, n2d)
# Data on layers (centers) - nlev-1 points
temperature # shape: (nlev-1, n2d)
# Automatically uses mesh.depth_levels or mesh.depth_layers
```
### Interpolation Methods
```python
# Nearest neighbor - fastest, best for categorical data
fesomp.transect(..., method="nn")
# Inverse distance weighting - smooth, good balance (default)
fesomp.transect(..., method="idw", influence=80000) # 80 km radius
# Linear - most accurate but slower
fesomp.transect(..., method="linear")
```
### Spatial Queries
```python
# Find nearest nodes
nearest_idx = mesh.find_nearest(lon=10.5, lat=54.3, k=5)
# Find nodes within radius
indices = mesh.find_in_radius(lon=0, lat=0, radius_km=100)
# Bounding box query
indices = mesh.subset_by_bbox(
lon_min=-10, lon_max=10,
lat_min=40, lat_max=60
)
# Access mesh topology
edges = mesh.topology.edges
neighbors = mesh.topology.face_neighbors
# Access mesh geometry
areas = mesh.geometry.elem_area
node_areas = mesh.geometry.node_area
```
## Examples
See the [examples/](examples/) directory for Jupyter notebooks:
- `mesh_tutorial.ipynb` - Mesh loading and exploration
- `plotting_tutorial.ipynb` - 2D map plotting
- `transect_plotting.ipynb` - Vertical transect visualization
## Documentation
### Project Structure
```
fesomp/
βββ src/fesomp/
β βββ mesh/ # Mesh handling
β β βββ mesh.py # Core Mesh class
β β βββ topology.py # Topology computation
β β βββ geometry.py # Geometric calculations
β β βββ spatial.py # Spatial indexing
β β βββ readers/ # I/O for NetCDF and ASCII
β βββ plotting/ # Visualization
β βββ plot.py # 2D map plotting
β βββ regrid.py # Grid interpolation
β βββ transect.py # Vertical transects
βββ tests/ # Test suite (108 tests)
βββ examples/ # Jupyter notebooks
```
### API Overview
**Mesh Operations:**
- `load_mesh(path)` - Load mesh from file or directory
- `mesh.find_nearest(lon, lat, k)` - Find k nearest nodes
- `mesh.find_in_radius(lon, lat, radius_km)` - Radius search
- `mesh.subset_by_bbox(...)` - Bounding box query
- `mesh.lon_elem`, `mesh.lat_elem` - Element center coordinates (lazy)
- `mesh.topology` - Edge and neighbor information (lazy)
- `mesh.geometry` - Areas and gradients (lazy)
**Interpolation:**
- `regrid(data, lon, lat, ...)` - Interpolate to regular grid
- `RegridInterpolator(lon, lat, ...)` - Reusable interpolator
**Visualization:**
- `plot(data, lon, lat, ...)` - 2D map with cartopy
- `transect(data, mesh, start, end, ...)` - Vertical cross-section
- `interpolate_transect(...)` - Interpolate along transect path
- `plot_transect(data, distance, depth, ...)` - Plot pre-interpolated transect
## Testing
Run the test suite:
```bash
# All tests
pytest
# With coverage
pytest --cov=fesomp --cov-report=html
# Specific test file
pytest tests/unit/test_transect.py -v
```
Current test coverage: **108 passing tests**
## Performance Tips
1. **Reuse interpolators** when processing multiple variables:
```python
interp = fesomp.RegridInterpolator(mesh.lon, mesh.lat)
temp_grid = interp(temperature)[0]
salt_grid = interp(salinity)[0] # Much faster!
```
2. **Choose appropriate methods**:
- Use `method="nn"` for fastest interpolation
- Use `method="idw"` for smooth fields (default)
- Use `method="linear"` for highest accuracy
3. **Adjust influence radius** for sparse data:
```python
fesomp.transect(..., influence=150000) # 150 km
```
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes with tests
4. Run the test suite (`pytest`)
5. Commit your changes (`git commit -m 'Add amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request
## Citation
If you use FESOMP in your research, please cite:
```bibtex
@software{fesomp2026,
title = {FESOMP: A Python library for FESOM2 unstructured mesh data},
author = {Koldunov, Nikolay},
year = {2026},
url = {https://github.com/yourusername/fesomp}
}
```
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Acknowledgments
- Developed with assistance from Claude (Anthropic)
- Built for the FESOM2 ocean modeling community
- Inspired by PyFVCOM and other unstructured grid tools
## Related Projects
- [FESOM2](https://github.com/FESOM/fesom2) - The Finite Element Sea ice-Ocean Model
- [PyFVCOM](https://github.com/pwcazenave/PyFVCOM) - Python tools for FVCOM data
- [xarray](https://github.com/pydata/xarray) - N-D labeled arrays and datasets in Python
---
**Questions or issues?** Please open an issue on GitHub or contact the maintainers.