{"id":42570468,"url":"https://github.com/koldunovn/fesomp","last_synced_at":"2026-01-28T21:07:05.345Z","repository":{"id":333305530,"uuid":"1136534957","full_name":"koldunovn/fesomp","owner":"koldunovn","description":"helper functions to work with FESOM2 data","archived":false,"fork":false,"pushed_at":"2026-01-18T17:46:27.000Z","size":6838,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-18T21:52:16.778Z","etag":null,"topics":["ocean-modelling","ocean-sciences","oceanography"],"latest_commit_sha":null,"homepage":"https://fesomp.readthedocs.io/en/latest/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/koldunovn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-17T21:33:49.000Z","updated_at":"2026-01-18T17:54:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/koldunovn/fesomp","commit_stats":null,"previous_names":["koldunovn/fesomp"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/koldunovn/fesomp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldunovn%2Ffesomp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldunovn%2Ffesomp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldunovn%2Ffesomp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldunovn%2Ffesomp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/koldunovn","download_url":"https://codeload.github.com/koldunovn/fesomp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldunovn%2Ffesomp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28851838,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ocean-modelling","ocean-sciences","oceanography"],"created_at":"2026-01-28T21:07:04.529Z","updated_at":"2026-01-28T21:07:05.340Z","avatar_url":"https://github.com/koldunovn.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FESOMP\n\nA modern Python library for working with FESOM2 (Finite Element Sea ice-Ocean Model) unstructured mesh data.\n\n[![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n### Mesh Management\n- 🔄 **Flexible I/O**: Load meshes from NetCDF or ASCII formats\n- ⚡ **Lazy Loading**: Topology, geometry, and spatial indices computed on-demand\n- 📍 **Dual Coordinates**: Automatic handling of node and element (triangle center) data\n- 🔍 **Spatial Queries**: Fast nearest-neighbor search, radius queries, and bounding box selection\n\n### Data Interpolation\n- 🎯 **Three Methods**: Nearest neighbor (fast), inverse distance weighting (smooth), and linear interpolation\n- 🌐 **Regular Grid**: Interpolate unstructured data to regular lon/lat grids\n- 💾 **Caching**: Reusable interpolators for efficient multi-variable processing\n- 🌍 **Spherical Geometry**: Accurate great circle calculations on the sphere\n\n### Visualization\n- 🗺️ **Map Plots**: Cartopy integration with multiple projections (PlateCarree, Robinson, Polar, etc.)\n- 📊 **Transect Plots**: Vertical cross-sections with automatic vertical coordinate detection\n- 🎨 **Customizable**: Full control over colormaps, contours, labels, and styling\n- 🔄 **Auto-Detection**: Automatically determines if data is on nodes/elements and levels/layers\n\n## Installation\n\n### From PyPI\n\n```bash\npip install fesomp\n```\n\n### From source\n\n```bash\ngit clone https://github.com/nkolduno/fesomp.git\ncd fesomp\npip install -e .\n```\n\n### Dependencies\n\nCore dependencies:\n- `numpy \u003e= 1.20`\n- `scipy \u003e= 1.7`\n- `xarray \u003e= 0.19`\n- `pandas \u003e= 1.3`\n- `matplotlib \u003e= 3.5`\n- `cartopy \u003e= 0.20`\n- `netCDF4 \u003e= 1.5`\n\nDevelopment dependencies:\n```bash\npip install -e \".[dev]\"  # Includes pytest, pytest-cov, hypothesis\n```\n\n## Quick Start\n\n### Load a mesh\n\n```python\nimport fesomp\n\n# From NetCDF\nmesh = fesomp.load_mesh(\"path/to/fesom.mesh.diag.nc\")\n\n# From ASCII directory\nmesh = fesomp.load_mesh(\"path/to/mesh/directory/\")\n\nprint(mesh)\n# Mesh(n2d=126859, nelem=237843, nlev=47, lon=[-180.00, 180.00], lat=[-90.00, 90.00])\n```\n\n### Plot 2D data on a map\n\n```python\nimport xarray as xr\n\n# Load surface temperature\nsst = xr.open_dataset(\"sst.fesom.1958.nc\")['sst'][0, :].values\n\n# Create a map\nfig, axes, interp = fesomp.plot(\n    sst,\n    mesh.lon,\n    mesh.lat,\n    mapproj=\"robinson\",\n    title=\"Sea Surface Temperature\",\n    units=\"°C\",\n    cmap=\"RdYlBu_r\",\n)\n```\n\n### Create a vertical transect\n\n```python\n# Load 3D temperature data\ntemp_3d = xr.open_dataset(\"temp.fesom.1958.nc\")['temp'][0, :, :].values\n\n# Atlantic meridional transect\nfig, ax, interp = fesomp.transect(\n    temp_3d,  # shape: (nlev, n2d)\n    mesh,\n    start=(-30, -60),  # 30°W, 60°S\n    end=(-30, 60),     # 30°W, 60°N\n    title=\"Temperature along 30°W\",\n    units=\"°C\",\n    depth_limits=(0, 2000),  # Top 2000 meters\n)\n```\n\n### Interpolate to regular grid\n\n```python\n# Quick interpolation\ndata_reg, lon_reg, lat_reg = fesomp.regrid(\n    sst,\n    mesh.lon,\n    mesh.lat,\n    res=(360, 180),\n    method=\"idw\",\n)\n\n# Reusable interpolator (faster for multiple variables)\ninterp = fesomp.RegridInterpolator(\n    mesh.lon, mesh.lat,\n    res=(360, 180),\n    method=\"idw\",\n)\n\ntemp_reg, lon_reg, lat_reg = interp(sst)\nsalt_reg, _, _ = interp(salinity)  # Reuses pre-computed weights\n```\n\n## Advanced Features\n\n### Automatic Detection\n\nThe library automatically detects:\n\n**Horizontal location:**\n```python\n# Data on nodes (n2d points)\ntemp_nodes = temp_3d  # shape: (nlev, n2d)\nfesomp.transect(temp_nodes, mesh, ...)  # Uses mesh.lon, mesh.lat\n\n# Data on elements (nelem points)\nu_velocity = u_3d  # shape: (nlev, nelem)\nfesomp.transect(u_velocity, mesh, ...)  # Uses mesh.lon_elem, mesh.lat_elem\n```\n\n**Vertical coordinate:**\n```python\n# Data on levels (interfaces) - nlev points\nw_velocity  # shape: (nlev, n2d)\n\n# Data on layers (centers) - nlev-1 points\ntemperature  # shape: (nlev-1, n2d)\n\n# Automatically uses mesh.depth_levels or mesh.depth_layers\n```\n\n### Interpolation Methods\n\n```python\n# Nearest neighbor - fastest, best for categorical data\nfesomp.transect(..., method=\"nn\")\n\n# Inverse distance weighting - smooth, good balance (default)\nfesomp.transect(..., method=\"idw\", influence=80000)  # 80 km radius\n\n# Linear - most accurate but slower\nfesomp.transect(..., method=\"linear\")\n```\n\n### Spatial Queries\n\n```python\n# Find nearest nodes\nnearest_idx = mesh.find_nearest(lon=10.5, lat=54.3, k=5)\n\n# Find nodes within radius\nindices = mesh.find_in_radius(lon=0, lat=0, radius_km=100)\n\n# Bounding box query\nindices = mesh.subset_by_bbox(\n    lon_min=-10, lon_max=10,\n    lat_min=40, lat_max=60\n)\n\n# Access mesh topology\nedges = mesh.topology.edges\nneighbors = mesh.topology.face_neighbors\n\n# Access mesh geometry\nareas = mesh.geometry.elem_area\nnode_areas = mesh.geometry.node_area\n```\n\n## Examples\n\nSee the [examples/](examples/) directory for Jupyter notebooks:\n\n- `mesh_tutorial.ipynb` - Mesh loading and exploration\n- `plotting_tutorial.ipynb` - 2D map plotting\n- `transect_plotting.ipynb` - Vertical transect visualization\n\n## Documentation\n\n### Project Structure\n\n```\nfesomp/\n├── src/fesomp/\n│   ├── mesh/           # Mesh handling\n│   │   ├── mesh.py           # Core Mesh class\n│   │   ├── topology.py       # Topology computation\n│   │   ├── geometry.py       # Geometric calculations\n│   │   ├── spatial.py        # Spatial indexing\n│   │   └── readers/          # I/O for NetCDF and ASCII\n│   └── plotting/       # Visualization\n│       ├── plot.py           # 2D map plotting\n│       ├── regrid.py         # Grid interpolation\n│       └── transect.py       # Vertical transects\n├── tests/              # Test suite (108 tests)\n└── examples/           # Jupyter notebooks\n```\n\n### API Overview\n\n**Mesh Operations:**\n- `load_mesh(path)` - Load mesh from file or directory\n- `mesh.find_nearest(lon, lat, k)` - Find k nearest nodes\n- `mesh.find_in_radius(lon, lat, radius_km)` - Radius search\n- `mesh.subset_by_bbox(...)` - Bounding box query\n- `mesh.lon_elem`, `mesh.lat_elem` - Element center coordinates (lazy)\n- `mesh.topology` - Edge and neighbor information (lazy)\n- `mesh.geometry` - Areas and gradients (lazy)\n\n**Interpolation:**\n- `regrid(data, lon, lat, ...)` - Interpolate to regular grid\n- `RegridInterpolator(lon, lat, ...)` - Reusable interpolator\n\n**Visualization:**\n- `plot(data, lon, lat, ...)` - 2D map with cartopy\n- `transect(data, mesh, start, end, ...)` - Vertical cross-section\n- `interpolate_transect(...)` - Interpolate along transect path\n- `plot_transect(data, distance, depth, ...)` - Plot pre-interpolated transect\n\n## Testing\n\nRun the test suite:\n\n```bash\n# All tests\npytest\n\n# With coverage\npytest --cov=fesomp --cov-report=html\n\n# Specific test file\npytest tests/unit/test_transect.py -v\n```\n\nCurrent test coverage: **108 passing tests**\n\n## Performance Tips\n\n1. **Reuse interpolators** when processing multiple variables:\n   ```python\n   interp = fesomp.RegridInterpolator(mesh.lon, mesh.lat)\n   temp_grid = interp(temperature)[0]\n   salt_grid = interp(salinity)[0]  # Much faster!\n   ```\n\n2. **Choose appropriate methods**:\n   - Use `method=\"nn\"` for fastest interpolation\n   - Use `method=\"idw\"` for smooth fields (default)\n   - Use `method=\"linear\"` for highest accuracy\n\n3. **Adjust influence radius** for sparse data:\n   ```python\n   fesomp.transect(..., influence=150000)  # 150 km\n   ```\n\n## Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes with tests\n4. Run the test suite (`pytest`)\n5. Commit your changes (`git commit -m 'Add amazing feature'`)\n6. Push to the branch (`git push origin feature/amazing-feature`)\n7. Open a Pull Request\n\n## Citation\n\nIf you use FESOMP in your research, please cite:\n\n```bibtex\n@software{fesomp2026,\n  title = {FESOMP: A Python library for FESOM2 unstructured mesh data},\n  author = {Koldunov, Nikolay},\n  year = {2026},\n  url = {https://github.com/yourusername/fesomp}\n}\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Acknowledgments\n\n- Developed with assistance from Claude (Anthropic)\n- Built for the FESOM2 ocean modeling community\n- Inspired by PyFVCOM and other unstructured grid tools\n\n## Related Projects\n\n- [FESOM2](https://github.com/FESOM/fesom2) - The Finite Element Sea ice-Ocean Model\n- [PyFVCOM](https://github.com/pwcazenave/PyFVCOM) - Python tools for FVCOM data\n- [xarray](https://github.com/pydata/xarray) - N-D labeled arrays and datasets in Python\n\n---\n\n**Questions or issues?** Please open an issue on GitHub or contact the maintainers.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoldunovn%2Ffesomp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkoldunovn%2Ffesomp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoldunovn%2Ffesomp/lists"}