Metadata-Version: 2.4
Name: pyovf
Version: 0.2.14
Summary: Python library for reading and writing OVF (OOMMF Vector Field) files
Author-email: Flavio Abreu Araujo <flavio.abreuaraujo@uclouvain.be>
Maintainer-email: Flavio Abreu Araujo <flavio.abreuaraujo@uclouvain.be>
License-Expression: MIT
Project-URL: Homepage, https://gitlab.flavio.be/flavio/pyovf
Project-URL: Documentation, https://gitlab.flavio.be/flavio/pyovf/-/blob/main/README.md
Project-URL: Repository, https://gitlab.flavio.be/flavio/pyovf.git
Project-URL: Issues, https://gitlab.flavio.be/flavio/pyovf/-/issues
Keywords: ovf,oommf,mumax3,micromagnetics,magnetism,scientific-computing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: C++
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=2.0.2
Provides-Extra: dev
Requires-Dist: pytest>=9.0.2; extra == "dev"
Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
Requires-Dist: black>=25.12.0; extra == "dev"
Requires-Dist: isort>=7.0.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=9.1.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=3.0.2; extra == "docs"
Requires-Dist: myst-parser>=4.0.1; extra == "docs"
Dynamic: license-file

[![PyPI](https://img.shields.io/pypi/v/pyovf)](https://pypi.org/project/pyovf) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyovf)](https://pypi.org/project/pyovf) [![PyPI - Wheel](https://img.shields.io/pypi/wheel/pyovf)](https://pypi.org/project/pyovf) [![PyPI - License](https://img.shields.io/pypi/l/pyovf)](https://pypi.org/project/pyovf) [![Downloads](https://pepy.tech/badge/pyovf)](https://pypi.org/project/pyovf) [![pipeline status](https://gitlab.flavio.be/flavio/pyovf/badges/main/pipeline.svg)](https://gitlab.flavio.be/flavio/pyovf/-/commits/main)

# pyOVF

A Python library for reading and writing OVF (OOMMF Vector Field) files used in micromagnetic simulations.

## Features

- **Fast I/O**: C++ backend for high-performance file operations (via [ovf-rw](https://gitlab.flavio.be/flavio/ovf-rw))
- **NumPy Integration**: Seamless conversion between OVF files and NumPy arrays
- **Pure Python Fallback**: Works even without the C++ extension (slower but functional)
- **OOMMF & mumax3 Compatible**: Supports files from both simulation packages
- **Binary Format**: Reads and writes OVF 2.0 Binary 4 format
- **Wide Python Support**: Python 3.8 - 3.14

## Installation

```bash
pip install pyovf
```

### Windows Users: Building from Source

> **⚠️ Git Bash / MINGW64 Users**: If you're building from source on Windows using Git Bash, see [WINDOWS_BUILD_SETUP.md](WINDOWS_BUILD_SETUP.md) for special instructions.

> **⚠️ Windows MAX_PATH Error**: If `pip install pyovf` fails with a CMake error about path length exceeding 260 characters (`MSB4018` / `System.InvalidOperationException`), see [the path length fix](#windows-max-path-260-character-limit) below.

**Quick Git Bash Install:**
```bash
cd pyovf
chmod +x install_from_gitbash.sh
./install_from_gitbash.sh
```

**Or use PowerShell:**
```powershell
cd pyovf
.\install_build_tools.ps1
```

For complete Windows setup instructions, see [WINDOWS_BUILD_SETUP.md](WINDOWS_BUILD_SETUP.md).

### From Source (Linux/Mac)

```bash
git clone https://gitlab.flavio.be/flavio/pyovf.git
cd pyovf
pip install -e .
```

### Building with ovf-rw

The C++ bindings are built from the [ovf-rw](https://gitlab.flavio.be/flavio/ovf-rw) library. When building from source, the build system will automatically fetch the required sources.

```bash
# Clone both repositories
git clone https://gitlab.flavio.be/flavio/pyovf.git
git clone https://gitlab.flavio.be/flavio/ovf-rw.git

# Build pyovf (it will find ovf-rw in the parent directory)
cd pyovf
pip install -e .
```

## Quick Start

```python
import pyovf
import numpy as np

# Read an OVF file
ovf = pyovf.read("magnetization.ovf")

# Or read with mesh objects (X and Y)
# X, Y, ovf = pyovf.read('magnetization.ovf', return_mesh=True)

print(f"Data shape: {ovf.data.shape}")
print(f"Grid: {ovf.xnodes}x{ovf.ynodes}x{ovf.znodes}")

# Access and modify data
mx = ovf.data[..., 0]  # X component
my = ovf.data[..., 1]  # Y component
mz = ovf.data[..., 2]  # Z component

# Create a new OVF file from scratch
data = np.zeros((1, 100, 100, 3), dtype=np.float32)
data[..., 2] = 1.0  # Uniform mz = 1

ovf_new = pyovf.create(
    data,
    xstepsize=5e-9,  # 5 nm cells
    ystepsize=5e-9,
    zstepsize=10e-9,
    title="m"
)

pyovf.write("uniform_state.ovf", ovf_new)
```

## API Reference

### Functions

#### `pyovf.read(filename) -> OVFFile`

Read an OVF file and return an OVFFile object.

#### `pyovf.write(filename, ovf)`

Write an OVFFile object to disk.

#### `pyovf.create(data, **kwargs) -> OVFFile`

Create a new OVFFile from a NumPy array.

### OVFFile Properties

| Property | Type | Description |
| -------- | ---- | ----------- |
| `data` | np.ndarray | Field data (z, y, x, [dim]) |
| `xnodes`, `ynodes`, `znodes` | int | Grid dimensions |
| `xstepsize`, `ystepsize`, `zstepsize` | float | Cell sizes |
| `valuedim` | int | Components (1=scalar, 3=vector) |
| `Title` | str | Data description |
| `TotalSimTime` | float | Simulation time |

## Data Layout

OVF files store data in column-major order:

- For a vector field: `data[z, y, x, component]`
- For a scalar field: `data[z, y, x]`

## Supported Python Versions

| Python Version | Status |
| -------------- | ------ |
| 3.8 | ✅ Supported |
| 3.9 | ✅ Supported |
| 3.10 | ✅ Supported |
| 3.11 | ✅ Supported |
| 3.12 | ✅ Supported |
| 3.13 | ✅ Supported |
| 3.14 | ✅ Supported (experimental) |

## Project Structure

```txt
pyovf/
├── pyovf/              # Main package
│   ├── __init__.py     # Package initialization
│   ├── _version.py     # Dynamic version (auto-generated by setuptools-scm)
│   ├── helper_funcs.py # Helper functions
│   └── ovf_handler.py  # OVF file handler + C++ backend loader
├── src/                # C++ pybind11 binding sources
├── tests/              # Unit tests
├── release.sh          # Single entry-point: build / test / tag / deploy
├── pyproject.toml      # Build configuration
├── setup.py            # CMake integration for C++ extension
└── CMakeLists.txt      # CMake build configuration
```

## Related Projects

- **[ovf-rw](https://gitlab.flavio.be/flavio/ovf-rw)**: The underlying C++ library for OVF file I/O, providing:
  - MATLAB bindings via MEX
  - Python bindings via Cython
  - High-performance binary file operations

## Development

### Setting up a development environment

```bash
git clone https://gitlab.flavio.be/flavio/pyovf.git
cd pyovf
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
```

### Running tests

```bash
pytest tests/ -v --cov=pyovf
```

### Building wheels

```bash
./release.sh build              # builds wheel + sdist with current python3
./release.sh build --python 3.12  # build with a specific version
```

## Versioning

This project uses [setuptools-scm](https://github.com/pypa/setuptools-scm) for dynamic versioning based on git tags. Version numbers are automatically determined from git history:

- Tagged commits (e.g., `v1.0.0`) produce release versions (`1.0.0`)
- Commits after a tag produce development versions (`1.0.1.dev3+g1234567`)

To create a new release use `release.sh` — it validates the working tree, creates an annotated tag, and pushes it to trigger the CI/CD pipeline:

```bash
./release.sh tag 0.3.0       # stable   → CI deploys to PyPI + GitLab Registry
./release.sh tag 0.3.0-rc1   # pre-release → CI deploys to Test PyPI + GitLab Registry
```

For a manual local deploy (bypass CI):

```bash
export PYPI_TOKEN="pypi-..."
./release.sh build && ./release.sh test && ./release.sh deploy --pypi
```

## Troubleshooting

### Windows MAX_PATH (260-character) Limit

**Symptom**: `pip install pyovf` fails with a CMake / MSBuild error like:

```
error MSB4018: System.InvalidOperationException: ... Le nom du fichier qualifié complet doit contenir moins de 260 caractères.
```

or in English:

```
The fully qualified file name must be less than 260 characters.
```

**Cause**: Windows limits file paths to 260 characters by default. The pip temporary build directory is already deep enough that the nested CMake scratch paths exceed this limit.

**Fix 1 — Enable long paths (recommended, requires admin)**

Run PowerShell as Administrator:

```powershell
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
    -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
```

Restart your terminal, then `pip install pyovf` will work normally.

**Fix 2 — Install from local source (no admin needed)**

If you have the repository cloned, build from a short local path instead of pip's deep temp directory:

```bash
cd pyovf
pip install -e .
```

**Fix 3 — Use a shorter TEMP directory (no admin needed, per-session)**

```cmd
set TEMP=C:\T
set TMP=C:\T
mkdir C:\T
pip install pyovf
```

For more Windows build troubleshooting, see [WINDOWS_BUILD_SETUP.md](WINDOWS_BUILD_SETUP.md).

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Author

Prof. Flavio ABREU ARAUJO  
Email: <flavio.abreuaraujo@uclouvain.be>

## Citation

If you use this software in your research, please cite:

```bibtex
@software{pyovf,
  author = {Abreu Araujo, Flavio},
  title = {pyovf: Python library for OVF file I/O},
  year = {2021},
  url = {https://gitlab.flavio.be/flavio/pyovf}
}
```
