Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2164c9a
Major changes to the code implmentation
carlosbornes Apr 26, 2025
8793d93
Delete repeated file
carlosbornes Apr 26, 2025
5bfa6f5
Lazy implementation for csd files
carlosbornes Apr 28, 2025
540dedf
Added mike to have dev and main docs
carlosbornes May 2, 2025
466d184
Fixed bug #18
MSoares98 May 31, 2025
1a65310
Did an initial draft for the calculator
carlosbornes Jun 17, 2025
3f412d2
Implementation of Simpson calculation and ability to run from python
carlosbornes Dec 17, 2025
a1b3a54
Fixed some problems with referencing and with how to center the spect…
carlosbornes Jan 12, 2026
4c6416d
Increase tests, improve changelog, and docs to reflect new functions
carlosbornes May 5, 2026
901329f
Update README and github actions
carlosbornes May 5, 2026
a1ef551
Apply suggestions from code review
carlosbornes May 6, 2026
42daed1
Apply suggestions from code review
carlosbornes May 6, 2026
a5dfd2b
Apply suggestions from code review
carlosbornes May 6, 2026
d7687db
Apply suggestions from code review
carlosbornes May 6, 2026
71faef3
Fixed ruff lint, problem with hz to ppm convertion, csdmpy dependenci…
carlosbornes May 7, 2026
bbab7c3
Remove leftovers from mike to fix docs build
carlosbornes May 7, 2026
dd2c40b
Another try at fixing docs problems
carlosbornes May 7, 2026
76469c3
Fixed problems with the CPMAS template, added it to docs, and rerun t…
carlosbornes May 7, 2026
8dc0e7e
Fix multi-channel offset, CT SW estimation, and axis reference conven…
carlosbornes May 8, 2026
9497a07
Address @jkshenton review
carlosbornes May 14, 2026
79e0d68
Add citation file according to #23 and fix miss match of license
carlosbornes May 14, 2026
8dfe72f
Delete .claude permissions
carlosbornes May 19, 2026
062c0b9
Fix review findings: read_simp keyword crash, xreim writing, and rela…
Jun 12, 2026
37f3dd0
Fix negative-gamma conventions and remaining review findings
Jun 12, 2026
690689f
Apply suggestions from code review
MSoares98 Jun 15, 2026
d036671
Divide the test_pr24 test into several test files. Rerun the notebook…
carlosbornes Jun 15, 2026
5c0a2eb
Add test to read_vasp
carlosbornes Jun 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ jobs:

steps:
- name: Check out repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: pip
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.12"

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ env/
ENV/
env.bak/
venv.bak/

# UV ignore
uv.lock
63 changes: 55 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,67 @@ 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.2.0]

### Added

- `SimpCalc` class for generating SIMPSON input files from Python.
- `simulate_spectrum()` convenience function with smart defaults (auto-calculates sw, offset, and ref from chemical shifts).
- CPMAS pulse sequence template.
- Support for custom pulse sequences via `CustomPulseSequence`.
- `Simpy` unified data container with lazy FID/spectrum conversion and automatic ppm calculation.
- `.csdf` (csdmpy) file format support, both reading and writing (`Simpy.write(format='csdf')`).
- GUI support for opening `.xreim` / `.csdf` files and saving in all supported formats.
- Comprehensive test suite.

### Changed

- Renamed `SimpSim` to `SimpCalc`.
- Bumped minimum Python version to 3.10.
- Replaced `print()` statements with `warnings.warn()` and `logging`.
- Replaced bare `except Exception:` catches with specific exception types.
- Added type hints and NumPy-style docstrings across all modules.
- Made VASP OUTCAR parser (`converter.py`) more robust with clear error messages for missing sections.
- DRY-ed up isotope data loading in `utils.py`.

### Fixed

- Time unit conversion bug (`* 10e3` should be `* 1e3` for seconds to milliseconds).
- `generate_spinsys()` double-wrapping mutation bug on repeated calls.
- `write_simp()` had wrong parameter names and caused circular import.
- `from_spe()` unnecessarily truncated spectral width with `int()`.
- `add_spectra()` accessed private `_spe_data` and crashed on FID-only input.
- `get_larmor_freq()` had copy-pasted docstring from `hz2ppm()`.
- Uninitialized variables in `read_spe()` / `read_fid()` gave confusing errors on malformed files.
- `read_simp()` was called with `format=` while its keyword was `fmt`, crashing `SimpCalc.run(read_output=True)`, `simulate_spectrum()`, and GUI file opening. The keyword is now `format` everywhere.
- `Simpy.write(format='xreim')` wrote a SIMP-header file without the time axis; it now writes the 3-column `time real imag` format that SIMPSON's `-xreim` flag produces and `read_simp()` expects.
- `Simpy.write(format='spe')` now preserves a shifted frequency axis via the `REF` header and writes `NP` as an integer.
- `read_csdf()` underestimated the spectral width by one bin (used the coordinate span instead of N x step).
- `_proton_freq_to_b0()` passed kHz/GHz strings through unconverted, causing a downstream `ValueError`; all Hz-based units are now normalised to MHz.
- GUI `open_files()` crashed with `UnboundLocalError` on uppercase or unknown file extensions; unsupported files are now skipped with a warning.
- `SimpCalc.run()` cleanup no longer deletes pre-existing files that share the output file name.
- `hz2ppm()` / `ppm2hz()` used the signed Larmor frequency, mirroring the ppm axis of every negative-gamma nucleus (e.g. 29Si, 15N, 17O). SIMPSON places +delta at +delta*|nu_L| regardless of the sign of gamma, so both conversions now use the magnitude (verified empirically against SIMPSON for 13C and 29Si).
- `simulate_spectrum()` spectral-width estimation used the signed Larmor frequency, collapsing the SW for negative-gamma nuclei; widths now use |nu_L|.
- `simulate_spectrum()` auto-centering put negative-gamma peaks off by 2x the center: the carrier `offset` follows the sign of gamma (rotating-frame frequency) while `ref` is always `-center_hz` (absolute axis).
- `_proton_freq_to_b0()` rejected scientific notation; `'8e8'` now parses to `'800.0MHz'`.
- `channels`/`nuclei` extraction regexes used `[\w\s]+`, which matches newlines and swallowed the following spinsys lines, so per-site nucleus detection from `detect_operator` could pick a token from the wrong line.
- `pulse_90` template failed on multi-channel spin systems (`pulse: arguments must match number of channels`); extra channels are now padded with `0 0`.
- `add_spectra()` set the combined spectral width to the coordinate span ((N-1) x step) instead of N x step when interpolating onto a common grid.

## [0.1.1]

- Added a GUI for Simpyson
- Implemented FID to SPE convertion within GUI
- Implemented Hz to ppm convertion within GUI
- Added a GUI for Simpyson.
- Implemented FID to SPE conversion within the GUI.
- Implemented Hz to ppm conversion within the GUI.

## [0.1.0]

## Added
### Added

- Tutorial on converting DFT structures to Simpson simulations.
- Tutorial on reading and processing Simpson simulation results.
- Added isotopes data to convert from Hz to ppm.
- Added `SimpSim` class to prepare Simpson input files.
- Tutorial on converting DFT structures to SIMPSON simulations.
- Tutorial on reading and processing SIMPSON simulation results.
- Added isotope data to convert from Hz to ppm.
- Added `SimpSim` class to prepare SIMPSON input files.
- Added `read_vasp` to convert VASP NMR tensors into a format readable by Soprano.
- Templates for 90-degree pulse `pulse_90` and no-pulse `no_pulse` experiments.

Expand Down
60 changes: 60 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
cff-version: 1.2.0
title: Simpyson
message: >-
If you use this software, please cite it using the
metadata from this file.
type: software
authors:
- given-names: Carlos
family-names: Bornes
affiliation: >-
Department of Physical and Macromolecular Chemistry,
Faculty of Science, Charles University in Prague, 128
43, Prague, Czech Republic
orcid: 'https://orcid.org/0000-0002-0325-2356'
- given-names: Márcio
family-names: Soares
affiliation: >-
Department of Chemistry & CICECO-Aveiro Institute of
Materials, University of Aveiro, 3810-193, Aveiro,
Portugal
orcid: 'https://orcid.org/0000-0001-8012-2662'
- given-names: Daniel
family-names: Pereira
affiliation: >-
Institute of Molecular Physical Science,
Department of Chemistry and Applied Biosciences,
ETH Zürich, Vladimir-Prelog-Weg 1-5 / 10,
8093 Zurich, Switzerland
orcid: 'https://orcid.org/0000-0001-7329-2516'
- given-names: J. Kane
family-names: Shenton
affiliation: >-
Scientific Computing, Science & Technology Facilities
Council, Rutherford Appleton Laboratory, Harwell Science
Campus, Oxfordshire, OX11 0QX, United Kingdom
orcid: 'https://orcid.org/0000-0003-4485-3446'
identifiers:
- type: doi
value: 10.5281/zenodo.20042403
repository-code: 'https://github.com/nuts-org/simpyson'
url: 'https://nuts-org.github.io/simpyson/'
abstract: >-
Simpyson is a Python interface to the SIMPSON solid-state NMR simulation
software. It provides tools for building SIMPSON input files from DFT
outputs (VASP, CASTEP, Quantum ESPRESSO), running simulations
programmatically, and reading simulation results into a unified data
container. Key features include automatic spectral width and offset
estimation, built-in pulse sequence templates (including CPMAS), CSDM
file support for interoperability with EasyNMR, and an interactive GUI
for visualising and combining spectra.
keywords:
- solid-state NMR
- NMR simulation
- SIMPSON
- DFT
- computational chemistry
- Python
license: MIT
version: 0.2.0
date-released: '2026-05-20'
61 changes: 50 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,64 @@
# SimPYson: A Pythonic Interface for SIMPSON

[![DOI](https://zenodo.org/badge/813117518.svg)](https://doi.org/10.5281/zenodo.14041918)
![Python - Version](https://img.shields.io/pypi/pyversions/simpyson)
![PyPI - Version](https://img.shields.io/pypi/v/simpyson?color=blue)

SimPYson is a Python package designed to simplify the use of [SIMPSON](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson), a powerful code to simulate solid-state NMR experiments. Born out of the need to streamline the process, SimPYson makes it easier to prepare input files from DFT calculations and analyze results from SIMPSON simulations all within a Python.
SimPYson is a Python package that makes it easier to work with [SIMPSON](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson), a code for simulating solid-state NMR experiments. It handles preparing input files from DFT calculations, running simulations, and reading results all from Python.

## Features 🤌
## Features

- **Convert DFT data to SIMPSON input files**: Prepare SIMPSON input files from DFT data (CASTEP, Quantum Espresso, VASP).
- **Run SIMPSON simulations from Python**: Use `simulate_spectrum()` for smart defaults or `SimpCalc` for full control over spin systems, pulse sequences, and output.
- **Convert DFT data to SIMPSON input files**: Prepare spin systems from CASTEP, Quantum Espresso, and VASP calculations via ASE and Soprano.
- **Read SIMPSON output files**: Load `.spe`, `.fid`, `.xreim`, and `.csdf` files into a unified `Simpy` object with automatic FID↔spectrum conversion and ppm scaling.
- **Pulse sequence templates**: Built-in templates for no-pulse, 90° pulse, and CPMAS experiments. Custom Tcl sequences are also supported.
- **Graphical User Interface**: Launch with `simpyson gui` to inspect and process spectra without any coding.

- **Read SIMPSON output files**: Load and manipulate NMR data from SIMPSON `.spe`, `.fid`, and `.xreim` files directly in Python for further analysis and visualization.
## Quick Start

- **Graphical User Interface**: You can type `simpyson gui` in your terminal to get Simpyson graphical user interface, and manipulate the data without any coding required.
**Read a SIMPSON output file:**

- **Templates for common experiments**: Use ready-made templates for typical Simpson NMR simulations, currently 90-degree pulse and no-pulse. More soon.
```python
from simpyson import read_simp

## Documentation 📖
data = read_simp("ethanol.spe", b0="400MHz", nucleus="1H")
print(data.ppm['ppm']) # ppm axis, auto-calculated
print(data.spe['hz']) # Hz axis
```

To learn more about simpyson, including some tutorials check the [documentation](https://nuts-org.github.io/simpyson/).
Accessing `.fid` on a spectrum file (or `.spe` on a FID) triggers automatic conversion via FFT — no manual processing needed.

# Planned Features 🔜
**Simulate a spectrum directly from Python:**

- **Expand number of pulse sequences**: Additional templates for more complex NMR experiments.
```python
from simpyson import simulate_spectrum

- **Expand number of DFT codes**: Improve the support of other DFT codes, suggestions are welcomed.
spinsys = """
channels 13C
nuclei 13C 13C
shift 1 10p 0 0 0 0 0
shift 2 50p 0 0 0 0 0
"""

result = simulate_spectrum(spinsys, proton_frequency=400e6, spin_rate=10000)
print(result.ppm['ppm'])
```

`simulate_spectrum()` automatically estimates the spectral width and carrier offset from the chemical shifts. For full control over all parameters, use `SimpCalc` directly — see the [documentation](https://nuts-org.github.io/simpyson/).

## Installation

```bash
pip install git+https://github.com/nuts-org/simpyson.git
```

Requires Python ≥ 3.10 and a working [SIMPSON](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson) installation for running simulations.

## Documentation

Full documentation and tutorials are available at [nuts-org.github.io/simpyson](https://nuts-org.github.io/simpyson/).

## Planned Features

- Additional pulse sequence templates for more complex NMR experiments.
- Broader support for DFT codes — suggestions welcome.
2 changes: 1 addition & 1 deletion docs/about/contributors.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# People

SimPYson was originally developed by [Carlos Bornes](https://physchem.cz/people/carlos-bornes/).
SimPYson is currently maintained by Carlos, Márcio and Daniel as part of NUTS.

## Active Maintainers

Expand Down
Binary file added docs/images/gui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 13 additions & 11 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
`SimPYson` is a Python package developed to streamline the use of [SIMPSON](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson), a simulation software for solid-state NMR. Born out of the frustration of trying to learn and use SIMPSON on my own, SimPYson aims to simplify the process of converting DFT calculation results into SIMPSON input files and read Simpson simulation, all within python
`SimPYson` is a Python package developed to streamline the use of [SIMPSON](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson), a simulation software for solid-state NMR. Born out of the frustration of trying to learn and use SIMPSON on our own, SimPYson aims to simplify the process of converting DFT calculation results into SIMPSON input files, running simulations, and reading SIMPSON output all within Python.

## Current features 🤌
## Current features

- Convert results from DFT calculations (e.g., CASTEP, Quantum Espresso, VASP) into SIMPSON input files.
- Read and process output files from SIMPSON simulations.
- Provide ready-to-use templates for common SIMPSON NMR experiments, such as 90-degree pulse and no-pulse.
- **Convert DFT data to SIMPSON input**: Prepare SIMPSON input files from DFT calculations (CASTEP, Quantum Espresso, VASP) using [ASE](https://ase-lib.org/) and [Soprano](https://ccp-nc.github.io/soprano/intro.html).
- **Run simulations from Python**: Use `SimpCalc` or `simulate_spectrum()` to generate, execute, and read SIMPSON simulations without writing Tcl manually.
- **Read and process output files**: Load `.spe`, `.fid`, `.xreim`, and `.csdf` files from SIMPSON into the unified `Simpy` data container.
- **Pulse sequence templates**: Ready-made templates for no-pulse, 90-degree pulse, and CPMAS experiments, plus support for custom pulse sequences.
- **Graphical User Interface**: Launch with `simpyson gui` to view, combine, and convert spectra interactively (PyQt5 + Plotly).

## Why choose SimPYson? 🙎‍♂️
## Why choose SimPYson?

No particular reason. One possible advantage lies in its seamless integration with other Python packages, making it easy to incorporate into your existing Python workflow. However, depending on your needs/taste, there are a few alternatives that may better suit you, hera are some examples:
One possible advantage lies in its seamless integration with other Python packages, making it easy to incorporate into your existing Python workflow. However, depending on your needs/taste, there are a few alternatives that may better suit you, here are some examples:

- [Simplot](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson): From the developers of Simpson offers a user-friendly interface to analyze the results.
- [Simview](https://github.com/zdetos/Simpson-View): From [Zdeněk Tošner](https://optimal-nmr.net/about.html) (Simpson dev) provides a GUI to run SIMPSON simulations and plot results within a clean, intuitive interface
- [Simplot](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson): From the developers of SIMPSON, offers a user-friendly interface to analyze the results.
- [Simview](https://github.com/zdetos/Simpson-View): From [Zdenek Tosner](https://optimal-nmr.net/about.html) (SIMPSON dev), provides a GUI to run SIMPSON simulations and plot results within a clean, intuitive interface.
- [EasyNMR](https://easynmr.pastis.dk/): A cloud-based platform that allows you to run and analyze SIMPSON simulations remotely.

## Future
We are open to suggestions.
## Future
We are open to suggestions.
22 changes: 19 additions & 3 deletions docs/installation/install.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
# Installation

If you have Python and pip installed, you can easily install SimPYson with the following command:
## Prerequisites

- **Python >= 3.10**
- **SIMPSON** -- required only for *running* simulations (not needed for reading/converting files). Download from the [SIMPSON website](https://inano.au.dk/about/research-centers-and-projects/nmr/software/simpson) and make sure the `simpson` command is available in your PATH.

## Install SimPYson

If you have Python and pip installed, you can install SimPYson with:

```bash
pip install git+https://github.com/nuts-org/simpyson.git
```

All dependecies are installed automatically.
All dependencies are installed automatically.

## Verify the installation

To verify that the package has been installed successfully, open a Python console and run:
Open a Python console and run:

```python
import simpyson
print(simpyson.__version__)
```

To check that the GUI works:

```bash
simpyson gui
```
Loading