Bruker NMR Reader#200
Conversation
Adds BrukerReader (reader="bruker") for 1D Bruker TopSpin experiment folders, using the optional nmrglue package. Reads the processed real spectrum from pdata/<procno>/ with a chemical-shift (ppm) axis, or falls back to the raw FID magnitude. Acquisition and processing parameters are lifted into the spectrum's metadata, with the full acqus/procs dictionaries preserved. Also adds NMRSpectrum / NMRSpectrumSeries technique classes, a demonstrator script, and a functional test suite backed by a small real TopSpin 1H NMR dataset vendored under test_data/bruker/ (sourced from the MIT-licensed nmrML repo, MetaboLights MTBLS1; see CREDITS.txt in that folder for full attribution).
|
Addressing this discussion preemptively since this reader also depends on an external package. I think the lazy import at call-time is the right approach here rather than going through |
There was a problem hiding this comment.
Nice work!
Just a few questions and small changes requested here. The biggest is a request for an NMRPlotter that does the xasix inversion so the user doesn't have to (may as well), and a request to build a physically meaningful xseries based on the acquisition parameters for non-processed NMR (nice to have, not need to have).
I agree that the lazy import works fine in this case :)
…ctrum for processed; demo FID plot with time axis
ScottSoren
left a comment
There was a problem hiding this comment.
Looks great!
A trivial comment, otherwise ready to merge. I can see that there are merge conflicts - also look trivial. Can you merge it into main?
Add Bruker TopSpin NMR reader
What this PR does
Adds a reader for Bruker TopSpin NMR experiment folders so that solution-NMR data can be loaded into ixdat.
specis anNMRSpectrum(a new technique class added in this PR) and behaves like any other ixdatSpectrum.The "TopSpin experiment folder":
The folder produced by Bruker's TopSpin NMR software. Typically looks like this:
You point the reader at the top folder (
my_experiment/) and it figures out the rest.How it works
The reader uses [nmrglue](https://nmrglue.readthedocs.io/) (Python package for NMR file I/O) to do the actual binary parsing. ixdat then wraps the result into its standard
Spectrumdata model:pdata/<procno>/, returns the real spectrum with a proper chemical-shift axis in ppm.prefer_processed=False), the reader returns the magnitude of the raw FID against an index axis. Phasing/Fourier transform/referencing is left to the user.nmrglueis not added to ixdat's required dependencies, it's only imported lazily insideBrukerNMRReader.read(). If a user tries to read a Bruker folder without it installed, they get a clearReadErrorexplaining how to install it (pip install nmrglue).Metadata
All the key acquisition parameters from
acqusare moved ontospec.metadatawith their original Bruker names (PULPROG,SOLVENT,NS,DS,TE,BF1,SFO1,O1,SW,TD,NUC1,DATE, ...), and processing parameters fromprocsare exposed underproc_*prefixes (proc_SI,proc_SF,proc_OFFSET,proc_LB,proc_PHC0, ...). The fullacqusandprocsdictionaries are also preserved underspec.metadata["acqus"]/spec.metadata["procs"]so nothing is lost. Everything inmetadatais JSON-serialisable.The acquisition
DATEis parsed into ixdat's standard unix timestamp (spec.tstamp) so NMR data can be co-plotted on a shared time axis with other techniques.New technique class
Adds
NMRSpectrumandNMRSpectrumSeriesinixdat.techniques.nmr, following the same pattern as the existingFTIRSpectrum/FTIRSpectrumSeries. Registered as"NMR"and"NMR_spectra"inTECHNIQUE_CLASSES.Tests
A new
tests/functional/test_bruker_reader.pyis added.The tests run against a real TopSpin 1D ¹H NMR dataset vendored under
test_data/bruker/MTBLS1_ADG19007u_162_10/. It comes from MetaboLights study MTBLS1 (a publicly availiable human-urine 1H NMR dataset, 700 MHz, noesypr1d, 128 scans), MIT-licensed reference repository. I included full attribution intest_data/bruker/MTBLS1_ADG19007u_162_10/CREDITS.txt. Only the files strictly needed by the tests are vendored (~770 KB total).Demo script
development_scripts/reader_demonstrators/demo_bruker_reader.py:Spectrum.read(..., reader="bruker").PULPROG,SOLVENT,NUC1,BF1,NS,TE, ...) and processing parameters (SI,SF,OFFSET,LB,PHC0, ...).Files added / changed
New:
src/ixdat/readers/bruker.py:BrukerNMRReaderimplementation.src/ixdat/techniques/nmr.py:NMRSpectrum/NMRSpectrumSeries.tests/functional/test_bruker_reader.pydevelopment_scripts/reader_demonstrators/demo_bruker_reader.py: demotest_data/bruker/MTBLS1_ADG19007u_162_10/: test datasetModified:
src/ixdat/readers/__init__.py: registers"bruker"inSPECTRUM_READER_CLASSES.src/ixdat/techniques/__init__.py: registers"NMR"and"NMR_spectra"inTECHNIQUE_CLASSES.README.rst: adds an "NMR" row to the techniques/readers table. (EDIT: Accidentally removed the nordic-reader line and then added it back by mistake on main-branch; so we have patched it back here from main to not have merge-issues)NEXT_CHANGES.rst: entries describing the new reader and the new technique classes.Things out of scope for now:
Calculator