🇯🇵 日本語
Open any NMR data.
Read 3 vendors (Bruker / Varian / JEOL) · 1D + 2D · 10 nuclei.
Validated on 365+ real datasets, silent failure = 0. 1,485 tests PASS.
Runs instantly on MATLAB Desktop or MATLAB Online — no setup required.
| User type | Typical task |
|---|---|
| Legacy data recovery | Revive old Varian / JEOL archives — read .fid directories and .jdf files that current vendor software can no longer open |
| Batch processing | Process hundreds of spectra with a single reproducible MATLAB script |
| Metabolomics / ML | Multi-vendor feature extraction (binning) → PCA / PLS-DA with a unified API |
| qNMR / purity analysis | Automated internal-standard quantification with full GUM uncertainty |
| Multi-vendor labs | One nmrData struct and identical processing API across Bruker, Varian, and JEOL |
All functions accept and return nmrData. Pipelines are composable.
See algorithm_guide.md for details.
Requirements: MATLAB R2025b, Signal Processing Toolbox, Curve Fitting Toolbox
% 1. Add path
addpath(genpath("src"));
% 2. Load data (choose your vendor)
nmrData = nmr.io.loadBruker("path/to/bruker/1"); % Bruker
nmrData = nmr.io.loadVarian("path/to/sample.fid"); % Varian
nmrData = nmr.io.loadJeol("path/to/sample.jdf"); % JEOL
% 3. 1D processing pipeline
nmrData = nmr.processing.applyWindow(nmrData, 'em', 'lb', 0.3);
nmrData = nmr.processing.doFFT(nmrData);
nmrData = nmr.processing.autoPhase(nmrData);
nmrData = nmr.processing.correctBaseline(nmrData);
nmrData = nmr.processing.pickPeaks(nmrData);
% 4. Plot
nmr.visualization.plotSpectrum1D(nmrData);First-time users can try scripts/quick_look.m for a one-click demo.
See docs/quickstart.md for the full guide.
Note: The Quick Start above is for standard 1H (zg/zg30).
Water-suppressed experiments and qNMR require additional settings. → See Automation Levels.
For interactive processing without writing code, an App Designer GUI is available.
| Option | How to launch |
|---|---|
NmrAnalyzerApp (.mlapp) |
Open src/+nmr/+app/NmrAnalyzerApp.mlapp in the MATLAB file browser and click Run |
| nmrAppProto (uifigure prototype) | addpath(genpath("src")); nmrAppProto |
Tabs: Load → FID → Spectrum/Phase → Baseline → Peaks/Export
Design spec → docs/app_designer_spec.md
addpath(genpath("src"));
fidDirs = dir("D:/archive/**/*.fid"); % find all .fid directories
for k = 1:numel(fidDirs)
fidPath = fullfile(fidDirs(k).folder, fidDirs(k).name);
nmrData = nmr.io.loadVarian(fidPath);
nmrData = nmr.processing.applyWindow(nmrData, 'em', 'lb', 0.5);
nmrData = nmr.processing.doFFT(nmrData);
nmrData = nmr.processing.autoPhase(nmrData);
nmr.io.exportJson(nmrData, sprintf("result/batch/sample_%03d.json", k));
endaddpath(genpath("src"));
% Load and process Bruker dataset (swap loadBruker for loadVarian / loadJeol as needed)
dirs = ["data/sample_A/1", "data/sample_B/1", "data/sample_C/1"];
dataArr = arrayfun(@nmr.io.loadBruker, dirs, 'UniformOutput', false);
dataArr = cellfun(@(d) nmr.processing.applyWindow(d, 'em'), dataArr, 'UniformOutput', false);
dataArr = cellfun(@nmr.processing.doFFT, dataArr, 'UniformOutput', false);
dataArr = cellfun(@nmr.processing.autoPhase, dataArr, 'UniformOutput', false);
dataArr = cellfun(@nmr.processing.correctBaseline, dataArr, 'UniformOutput', false);
T = nmr.ml.buildFeatureMatrix([dataArr{:}]); % uniform binning + PQN normalisation
result = nmr.ml.runPCA(T); % scores, loadings, explained varianceNMR samples and experiment conditions vary widely; not all data can be processed with default settings. This tool defines three levels of automation so you know upfront what is needed:
| Level | Meaning | Example experiments |
|---|---|---|
| 🟢 Auto | Works with defaults — no configuration needed | Standard ¹H (zg/zg30), ¹³C (s2pul), ¹⁹F, ¹⁵N |
| 🟡 Preset | Requires experiment-type configuration — one applyPreset call (v0.14+) |
Water-suppressed (presat / metnoesy / zgpr) |
| 🔵 Manual | Requires data-specific parameters (integration regions, reference, etc.) | qNMR quantification, compound assignment |
Preset catalog by experiment type → docs/preset_catalog.md
% Water-suppressed (noesypr1d / metnoesy / presat / zgpr) — one line with applyPreset
nmrData = nmr.io.loadBruker("path/to/bruker/1");
nmrData = nmr.processing.applyPreset(nmrData, 'water_suppressed_1H');
nmr.visualization.plotSpectrum1D(nmrData, 'YLimFraction', 0.1);Scenario-by-scenario code examples → docs/scenario_validation.md
NMR measurements are long-term research assets. Spectra collected years ago on older instruments should remain useful today, but they often end up locked in vendor-specific binary formats and become harder to access over time.
This project aims to bring past measurement assets back into a usable state for modern workflows.
- Vendor-independent — unified API across Bruker, Varian, and JEOL
- Environment-independent — runs on MATLAB Desktop or MATLAB Online without additional setup
- Future-proof —
nmrDatastruct is decoupled from any vendor binary format
- Robustness over completeness — Stability is prioritized over feature completeness
- Real data over synthetic assumptions — Design decisions are grounded in real datasets
- No silent failure — Anomalies are always reported
Detailed compatibility matrix (vendor × nucleus × experiment × feature) →
docs/compatibility_matrix.md
| Format | 1D FID | 1D Spectrum | 2D | Notes |
|---|---|---|---|---|
Bruker (TopSpin fid/ser + acqus) |
✅ | N/A¹ | ✅ | TopSpin 1.x–4.x / XWIN-NMR. GRPDLY auto-correction |
Varian / Agilent (.fid folder) |
✅ | N/A¹ | ✅ | VnmrJ / DD2. Multi-block averaging |
JEOL Delta (.jdf binary) |
✅ | N/A¹ | ✅ | Delta 5.x |
JCAMP-DX (.jdx / .dx) |
✅ | ✅ | AFFN + ASDF (SQZ/DIF/DUP). Only IUPAC official spec (JDX-7) ¹H / ¹³C supported. Vendor dialects ¹⁹F / ³¹P / ¹⁵N are frozen | |
nmrML (.nmrML XML) |
⬜ | Complex128/64. nmrCV mapping. Only nmrML spec-conformant test data verified; real instrument output not verified |
¹ Vendor binaries contain only FID (raw data). FFT and beyond are re-run through this tool by design.
| Nucleus | Bruker | Varian | JEOL | JCAMP-DX |
|---|---|---|---|---|
| ¹H | ✅ | ✅ | ✅ | |
| ¹³C | ✅ | ✅ | ✅ | |
| ¹⁹F | ✅ | ✅ | ✅ | ⬜ |
| ³¹P | ✅ | ✅ | ✅ | ⬜ |
| ¹⁵N | ✅ | ✅ | 🚧 | ⬜ |
| ¹¹B / ²H / ²⁹Si / ²³Na / ¹⁷O | 🚧 | 🚧 | 🚧 | 🚧 |
✅ = verified with real data /
⚠️ = spec/test data only (real instrument output unverified) / ⬜ = implemented but unverified / 🚧 = Blocked (Data) — unblockable once data is available / ❄️ = frozen (design or dependency reasons) ¹¹B / ²⁹Si: Phase 1 data acquired. Phase 2–4 validation is a future task.⚠️ (JCAMP-DX): Only the IUPAC JDX-7 official test suite verified. Bruker / Varian / JEOL vendor-generated JCAMP-DX files not verified.⚠️ (nmrML): Only nmrML spec-conformant test data verified. Real instrument-exported nmrML files not verified (no column in nuclei table — see Formats table).
| Experiment | Bruker | Varian | JEOL |
|---|---|---|---|
| COSY | ✅ | ✅ | ✅ |
| DQF-COSY | ✅ | 🚧 | ⬜ |
| TOCSY | ✅ | ✅ | 🚧 |
| NOESY | ✅ | ✅ | 🚧 |
| ROESY | ✅ | ⬜ | ⬜ |
| HSQC (¹H-¹³C) | ✅ | ✅ | ✅ |
| HMQC | ✅ | ⬜ | ⬜ |
| HMBC | ✅ | 🚧 | ✅ |
| ¹⁵N-HSQC | ✅ | ✅ | ⬜ |
| J-resolved | ✅ | ⬜ | ⬜ |
| DEPT-HSQC | ⬜ | ⬜ | |
| DOSY | ✅ | ✅ | ✅ |
¹ DEPT-HSQC: read and displayed. DEPT classification done. Integrated atlas planned. ✅ = verified with real data / ⬜ = unverified (target for exploration) / 🚧 = Blocked (Data) (no verified raw FID in public DBs — data donations welcome → CONTRIBUTING.md) F1 detection mode: QF / TPPI / States / States-TPPI / Echo-AntiEcho all supported.
| Feature | 1D | 2D | Automation | Notes |
|---|---|---|---|---|
| FFT | ✅ | ✅ | 🟢 Auto | — |
| Window function | ✅ | ✅ | 🟡 Preset | lb depends on nucleus (¹H: 0.3, ¹³C: 2.0, ¹⁹F: 1.0 Hz) |
| Zero-fill | ✅ | ✅ | 🟢 Auto | factor=2 default |
| Auto phase correction | ✅ | ✅ | 🟢/🟡 | Standard: Auto. Water-suppressed: Preset (method='abs') |
| Manual phase correction | ✅ | ✅ | 🔵 Manual | Explicit ph0/ph1 |
| Baseline correction | ✅ | ⬜ | 🟡 Preset | Method selection recommended (¹H → als, ¹³C → snip) |
| Peak detection | ✅ | ✅² | 🟢/🟡 | Standard: Auto. Water-suppressed: excludeRegions required |
| Peak fitting | ✅ | ⬜ | 🟡 Preset | Lorentzian/Voigt selection |
| ppm calibration | ✅ | ✅ | 🔵 Manual | Reference compound required |
| SNR estimation | ✅ | ⬜ | 🟢 Auto | Manual noise region improves accuracy |
| Integration | ✅ | ⬜ | 🔵 Manual | ppm region specification required |
² 2D cross-peak detection (
detectCorrelations) implemented. 🟢 = works by default / 🟡 = experiment-type config needed / 🔵 = data-specific params needed
| Feature | Status | Feature | Status |
|---|---|---|---|
| qNMR internal standard | ✅ | PCA | ✅ |
| GUM uncertainty | ✅ | PLS-DA | ✅ |
| ICH Q2 validation | ✅ | T1/T2 relaxation fitting | ✅ |
| 2D cross-peak detection | ✅ | Feature extraction (binning/interp) | ✅ |
| DEPT multiplicity classification | ✅ | Manual assignment management | ✅ |
| DOSY diffusion coefficient fit | ✅ | DOSY 2D map visualization | ✅ |
ML features (PCA/PLS-DA/binning) support 1D spectra only.
JSON · PNG (300–600 DPI) · PDF (vector) · CSV · MAT — all ✅
- Vendor Agnostic: JEOL / Bruker / Varian processed through a unified
nmrDatastruct - Legacy Support: Recovers data from discontinued Varian/Agilent instruments
- Fault Tolerance: Zero silent failures for missing params, truncated FID, endian mismatch, etc.
- Large-Scale Validation: 365+ real datasets (TopSpin 1.x–4.x, XWIN-NMR, Delta 5.x, VnmrJ, DD2)
- Open Format Hub: JCAMP-DX / nmrML →
nmrData→ JSON. Vendor binaries and open formats unified
The following features are acknowledged but not currently being implemented. Contributions (data donation / Pull Requests) may unblock some of them.
| Feature | Status | Reason |
|---|---|---|
| DOSY analysis | ✅ | Stejskal-Tanner single-exponential fit. Multi-component (CONTIN) planned |
| 2D JCAMP-DX (NTUPLES) | ✅ | IUPAC test suite 8/8 PASS |
| JEOL Arrayed FID (J-03) | ✅ | T1/T2 arrayed FID (legacy Delta format) supported |
| ¹¹B real-data validation | 🚧 Blocked (Data) | No raw FID in public DBs (Phase I–VI survey done). Data donations welcome |
| ²H / ²⁹Si / ²³Na validation | 🚧 Blocked (Data) | No raw FID in public DBs. Instrument data required |
| Varian DQF-COSY / HMBC validation | 🚧 Blocked (Data) | All public DBs searched (Zenodo / Figshare / Workbench / OSF / HMDB). No raw FID found. Data donations welcome |
| JEOL TOCSY / NOESY validation | 🚧 Blocked (Data) | All public DBs searched (4985 chemserv entries, MRRC, Zenodo). No raw FID found. Data donations welcome |
| Bruker/JEOL JCAMP-DX dialects | 🚧 Blocked (Data) | Vendor-specific sample data unavailable. Data donations welcome |
| 2D nmrML / NP-MRD | 🚧 Blocked (Data) | NP-MRD API not public. No raw 2D data available |
| RDKit structure integration | ❄️ Frozen | Python dependency + large implementation cost. Collaborators needed |
| Deep Learning | ❄️ Frozen | Training data collection is the barrier |
🚧 = Blocked (Data) — unblockable once data is available. See CONTRIBUTING.md Wanted Data section. ❄️ = Frozen (design, dependencies, or other reasons beyond data). ⬜ = in progress or planned.
- MATLAB R2025b, Signal Processing Toolbox, Curve Fitting Toolbox
- Python 3.11 (specific tasks only, isolated in
venv/)
ProjectRoot/
├─ main_nmr.m # Single entry point (section-by-section execution)
├─ scripts/
│ └─ quick_look.m # Quick demo for first-time users
├─ src/
│ ├─ +nmr/ # NMR-specific logic (MATLAB packages)
│ │ ├─ +io/ # Vendor parsers (nmr.io.loadVarian etc.)
│ │ ├─ +processing/ # FFT, windowing, phase, baseline
│ │ ├─ +visualization/ # Plot functions
│ │ ├─ +app/ # App Designer GUI (NmrAnalyzerApp.mlapp)
│ │ ├─ +pipeline/ # Orchestration, artifact creation
│ │ └─ +util/ # Log helper (nmr.util.log)
│ ├─ config/ # Config loader
│ └─ util/ # Common utilities
├─ tests/
│ ├─ unit/ # matlab.unittest-based unit tests (1,485 tests)
│ ├─ smoke/ # Real-data smoke tests
│ └─ regression/ # Regression tests
├─ data/ # External NMR data (not tracked by Git)
├─ result/ # Run artifacts (not tracked by Git)
├─ config/
│ └─ settings.example.json
└─ docs/ # Design specs, release notes
- Logic only under
src/. NMR-specific logic insrc/+nmr/packages - All parser outputs normalized to the common
nmrDatastruct - Artifacts saved to
result/runs/<YYYYMMDD_HHMMSS>/(not Git-tracked) - Logging via
nmr.util.log.info/.warn/.err/.progress(fprintfnot used)
| File | Contents |
|---|---|
docs/algorithm_guide.md |
Algorithm rationale and test validation strategy for all functions |
docs/function_reference.md |
Full signatures and option lists for all functions |
docs/function_catalog.md |
Compact function catalog (60 functions, all packages) |
docs/test_catalog.md |
Test class catalog (50 classes, 1,485 tests) |
docs/quickstart.md |
Step-by-step guide and FAQ |
docs/compatibility_matrix.md |
Vendor × nucleus × experiment × feature detailed matrix |
MIT License. See LICENSE for details.
This project implements algorithms described in published academic papers. See THIRD_PARTY_NOTICES.md for algorithm attributions.
This repository contains no NMR raw data.
data/external/is distributed empty. Place your own data there.- Redistribution of data downloaded from MetaboLights / BMRB / HMDB etc. is not performed.
- This tool does not transmit any data externally.
This project is developed and maintained as a personal side project.
- Users are responsible for verifying the accuracy of results.
- Support is best-effort. Response times may vary.
- Provided "as-is" (see MIT License disclaimer).
Issues and requests are welcome. See CONTRIBUTING.md for details.
- Bug reports: Include steps to reproduce and your MATLAB version.
- New vendor/experiment support: Describe the format and a public database link if available.
- Analysis requests: Open an Issue to propose new processing/analysis methods.
Pull Requests are welcome, but please discuss via Issue first.

