Metadata
NMRTools.NMRBase.NMRExperimentNMRTools.NMRBase.NMRSampleNMRTools.NMRBase.PowerNMRTools.NMRIO.FQListDimensionalData.Dimensions.Lookups.metadataDimensionalData.Dimensions.Lookups.unitsDimensionalData.Dimensions.labelNMRTools.NMRBase.acqusNMRTools.NMRBase.annotationsNMRTools.NMRBase.channelsNMRTools.NMRBase.dbNMRTools.NMRBase.hasannotationsNMRTools.NMRBase.hassampleNMRTools.NMRBase.label!NMRTools.NMRBase.referencepulseNMRTools.NMRBase.sampleNMRTools.NMRBase.samplefileNMRTools.NMRBase.wattsNMRTools.NMRIO.findexperimentsNMRTools.NMRIO.findsampleNMRTools.NMRIO.scanexperimentsNMRTools.NMRIO.scansamplesNMRTools.NMRIO.withreference
Metadata access
DimensionalData.Dimensions.Lookups.metadata — Function
metadata(nmrdata, key)
metadata(nmrdata, dim, key)
metadata(nmrdimension, key)Return the metadata for specified key, or nothing if not found. Keys are passed as symbols.
Examples (spectrum metadata)
:ns: number of scans:ds: number of dummy scans:rg: receiver gain:ndim: number of dimensions:title: spectrum title (contents of title pdata file):filename: spectrum filename:pulseprogram: title of pulse program used for acquisition:experimentfolder: path to experiment:noise: RMS noise level
Examples (dimension metadata)
:pseudodim: flag indicating non-frequency domain data:npoints: final number of (real) data points in dimension (after extraction):td: number of complex points acquired:tdzf: number of complex points when FT executed, including LP and ZF:bf: base frequency, in Hz:sf: carrier frequency, in Hz:offsethz: carrier offset from bf, in Hz:offsetppm: carrier offset from bf, in ppm:swhz: spectrum width, in Hz:swppm: spectrum width, in ppm:region: extracted region, expressed as a range in points, otherwise missing:window:WindowFunctionindicating applied apodization:referenceoffset: referencing (in ppm) applied to the dimension
See also estimatenoise.
DimensionalData.Dimensions.label — Function
label(nmrdata)
label(nmrdata, dim)
label(nmrdimension)Return a short label associated with an NMRData structure or an NMRDimension. By default, for a spectrum this is obtained from the first line of the title file. For a frequency dimension, this is normally something of the form 1H chemical shift (ppm).
See also label!.
NMRTools.NMRBase.label! — Function
label!(nmrdata, labeltext)
label!(nmrdata, dim, labeltext)
label!(nmrdimension, labeltext)Set the label associated with an NMRData structure or an NMRDimension.
See also label.
DimensionalData.Dimensions.Lookups.units — Function
units(nmrdata)
units(nmrdata, dim)
units(nmrdimension)Return the physical units associated with an NMRData structure or an NMRDimension.
NMRTools.NMRBase.acqus — Function
acqus(nmrdata)
acqus(nmrdata, key)
acqus(nmrdata, key, index)Return data from a Bruker acqus file, or nothing if it does not exist. Keys can be passed as symbols or strings. If no key is specified, a dictionary is returned representing the entire acqus file.
If present, the contents of auxilliary files such as vclist and vdlist can be accessed using this function.
Examples
julia> spec = exampledata("2D_HN");
julia> acqus(spec, :pulprog)
"sfhmqcf3gpph.cw"
julia> acqus(spec, "TE")
276.9988
julia> round(acqus(spec, :p, 1) * 1e6; digits=2) # pulse length p1, in µs
9.2
julia> acqus(spec, "D", 1)
0.1See also metadata.
NMRTools.NMRBase.channels — Function
channels(nmrdata)
channels(nmrdata, label)
channels(nmrdata, nucleus)
channels(nmrdata, string)Access spectrometer channels. channels returns a dictionary of all channels keyed by label (:f1…:f8), or nothing if no channel information is available. channel returns a single channel dictionary (or nothing if not found).
Each channel dictionary describes a physical RF channel independently of which dimensions were detected, with keys :label, :nucleus, :bf (base frequency, Hz), :sfo (carrier frequency, Hz), :offsethz and :offsetppm (carrier offset from :bf).
A channel can be looked up by label (channels(spec, :f2)), by Nucleus (channels(spec, C13)), or by a string giving either (channels(spec, "f2"), channels(spec, "13C")). When several channels share a nucleus, the lowest-numbered channel is returned and a warning is issued.
This is the recommended way to obtain the frequency of a nucleus that has no detected axis, e.g. the carbon channel in a ¹³C-edited experiment read out on ¹H.
Examples
julia> spec = exampledata("2D_HN");
julia> channels(spec, C13)[:bf]
1.5092041e8
julia> channels(spec, :f1)[:nucleus]
H1::Nucleus = 0NMRTools.NMRBase.referencepulse — Function
referencepulse(spec, nucleus) -> (pulse_length, power)Get the reference pulse calibration for a given nucleus from pulse programme annotations. Returns a tuple of (pulse_length, power) or nothing if not found.
The reference pulse is the calibrated 90° hard pulse used as the basis for all power calculations on that channel.
Arguments
spec: NMRData object with annotationsnucleus: Nucleus symbol or string (e.g., :19F, "19F", :1H, "1H")
Returns
(pulse_length, power): Tuple where pulse_length is in μs and power is a Power objectnothing: If no reference pulse found for the specified nucleus
Examples
julia> referencepulse(spec, "19F")
(13.29, Power(-9.03 dB, 8.0 W))
julia> referencepulse(spec, :1H)
(9.2, Power(-3.0 dB, 32.0 W))See also annotations.
Annotations
NMRTools.NMRBase.annotations — Function
annotations(nmrdata)
annotations(nmrdata, key)
annotations(nmrdata, key, index)
annotations(nmrdata, key1, key2)
annotations(nmrdata, keys...)Return annotation data from pulse programme, or nothing if it does not exist. Keys can be passed as strings or symbols. If no key is specified, the entire annotations dictionary is returned.
Dotted names are automatically split and dereferenced, e.g. annotations(spec, "cest.duration") is equivalent to annotations(spec, "cest", "duration").
This function provides nested access to annotations stored in metadata[:annotations]. Multiple keys can be chained to access nested dictionaries or specific array elements.
Examples
julia> annotations(spec, "title")
"19F CEST"
julia> annotations(spec, "dimensions")
2-element Vector{String}:
"cest.offset"
"f1"
julia> annotations(spec, "dimensions", 1)
"cest.offset"
julia> annotations(spec, "cest", "duration")
0.5
julia> annotations(spec, "cest.duration")
0.5
julia> annotations(spec, :reference_pulse)
1-element Vector{Dict{String, Any}}:
Dict("channel" => "f1", "pulse" => 9.2e-6, "power" => -3.0)
julia> annotations(spec, "calibration.duration.start")
0.001NMRTools.NMRBase.hasannotations — Function
hasannotations(nmrdata) -> BoolCheck if the NMRData object has any annotations.
Metadata types
NMRTools.NMRBase.Power — Type
Power{T}A type to represent NMR pulse powers that can be described either in Watts (W) or as dB attenuation (dB). Internally stores the dB value as type T.
Constructors
Power(value, :dB)- Create from dB attenuation valuePower(value, :W)- Create from Watts value
Getters
db(p::Power)- Get dB attenuation valuewatts(p::Power)- Get Watts value
Examples
julia> p1 = Power(30.0, :dB)
Power(30.0 dB, 0.001 W)
julia> db(p1), watts(p1)
(30.0, 0.001)
julia> p2 = Power(0.5, :W);
julia> round(db(p2); digits=2)
3.01
julia> db(Power(10, :W)) # integers and other numeric types work
-10.0
julia> db(Power(0.0, :W)) # zero watts is 120 dB attenuation
120.0Conversion
Converting W to dB: -10 * log10(plW) Converting dB to W: 10^(-dB/10)
NMRTools.NMRBase.db — Function
db(p::Power)Get the power level in dB attenuation.
Example
p = Power(20.0, :dB)
db(p) # 20.0NMRTools.NMRBase.watts — Function
watts(p::Power)Get the power level in Watts.
Example
p = Power(20.0, :dB)
watts(p) # 0.01NMRTools.NMRIO.FQList — Type
FQList(values, unit::Symbol, relative::Bool)
FQList(values, unit::Symbol, relative::Bool, bf, sfo)Represents a frequency list. unit can be :Hz or :ppm, and relative indicates whether the frequency is given relative to SFO (true) or BF (false).
bf and sfo optionally record the reference base and carrier frequencies (in Hz) of the spectrometer channel this list belongs to. When present, the list can be converted to ppm or Hz on its own — without a detected frequency axis — using the single-argument ppm and hz methods. See withreference to attach a reference from a channel dictionary.
Raw values can be extracted using the data function, or (better) as absolute chemical shifts (in ppm) or relative offsets (in Hz) using ppm and hz functions.
See also: ppm, hz, withreference.
NMRTools.NMRIO.withreference — Function
withreference(f::FQList, channel) -> FQListReturn a copy of frequency list f with its reference base and carrier frequencies (:bf, :sfo) populated from a channel dictionary (see channels). This makes the list self-describing, so it can be converted to ppm or Hz without a detected frequency axis.
Samples and experiments
NMRTools.NMRBase.NMRSample — Type
NMRSampleA lightweight wrapper around an NMR sample JSON file. Holds the file path and parsed metadata. Access fields via sample.
See also: scansamples, findsample.
NMRTools.NMRBase.NMRExperiment — Type
NMRExperimentA lightweight, metadata-only descriptor for a Bruker NMR experiment folder. Does not load any binary data. Upgrade to a full NMRData via loadnmr.
See also: scanexperiments, findsample, loadnmr.
NMRTools.NMRBase.sample — Function
sample(nmrdata)
sample(nmrdata, keys...)Return the sample metadata associated with the NMRData object, or nothing if not available. Sample metadata follows the schema defined at https://github.com/waudbylab/nmr-sample-schema.
When keys are provided, navigates nested dictionaries using the given keys. Keys can be strings or symbols and are automatically converted to lowercase strings for consistent access.
Examples
julia> sample(spec)
Dict{String, Any} with 6 entries:
"nmr_tube" => Dict{String, Any}("diameter"=>"5 mm", "type"=>"regular", "sample_volume_uL"=>600)
"buffer" => Dict{String, Any}("solvent"=>"10% D2O", "reference_unit"=>"%w/v", "chemical_shift_reference"=>"none")
[...]
julia> sample(spec, "notes")
"here's a note!"
julia> sample(spec, :people, :users)
1-element Vector{Any}:
"Chris"
julia> sample(spec, "sample", "components")
2-element Vector{Any}:
Dict{String, Any}("name" => "HEWL", "isotopic_labelling" => "unlabelled", "unit" => "mM", "concentration" => 10)
Dict{String, Any}("name" => "gadodiamide", "isotopic_labelling" => "unlabelled", "unit" => "mM", "concentration" => 1)
julia> sample(spec, :sample, :components, :name)
2-element Vector{Any}:
"HEWL"
"gadodiamide"When the final key is applied to an array (such as components), the key is mapped over each element and a filtered array is returned.
For isotopic_labelling and solvent, if the stored value is "custom", the corresponding custom_labelling or custom_solvent field is returned automatically.
NMRTools.NMRBase.hassample — Function
hassample(nmrdata) -> BoolCheck if the NMRData object has any associated sample metadata.
NMRTools.NMRBase.samplefile — Function
samplefile(x) -> Union{String, Nothing}Return the path to the JSON sample file associated with x, or nothing if no sample has been matched. Works with NMRData and NMRExperiment.
NMRTools.NMRIO.scanexperiments — Function
scanexperiments(dir; recursive=true, pdatadir=1, warn=true) -> Vector{NMRExperiment}Scan dir for Bruker NMR experiment folders and return a vector of lightweight NMRExperiment descriptors sorted by experiment date (oldest first).
A folder is identified as a Bruker experiment if it contains an acqus file. Once identified, the scanner does not recurse into it, so pdata/ subdirectories are never misidentified as experiments.
Arguments
dir: Root directory to scan.recursive: Iftrue(default), search subdirectories. Iffalse, only check immediate children ofdir.pdatadir: Only include experiments that have apdata/<pdatadir>/subdirectory, i.e. whereloadnmrwould succeed. Passnothingto include all experiments regardless of whether processed data exists.warn: Iftrue(default), warn about folders that cannot be parsed.
Examples
expts = scanexperiments("/nmr/projects/lysozyme/")
# Filter with standard Julia
hsqc = filter(e -> e[:pulseprogram] == "hsqcetfpf3gpsi2", expts)
cest = filter(e -> "cest" in get(annotations(e), "experiment_type", []), expts)
# Load one
spec = loadnmr(expts[1])See also: NMRExperiment, scansamples, findexperiments.
NMRTools.NMRIO.scansamples — Function
scansamples(dir; recursive=false) -> Vector{NMRSample}Scan dir for NMR sample JSON files and return a vector of NMRSample descriptors sorted by creation timestamp. Files that cannot be parsed or have an unsupported schema version are skipped silently.
By default only the immediate directory is searched (not subdirectories), since sample files are typically stored flat in a single directory.
NMRTools.NMRIO.findsample — Function
findsample(expt::NMRExperiment) -> Union{NMRSample, Nothing}
findsample(expt::NMRExperiment, dir::String) -> Union{NMRSample, Nothing}
findsample(expt::NMRExperiment, candidates::Vector{NMRSample}) -> Union{NMRSample, Nothing}Find the sample that matches expt based on experiment date falling within the sample's creation–ejection timestamp window.
- With no second argument, searches the parent directory of the experiment folder.
- With a directory path, searches that directory for JSON sample files.
- With a pre-scanned
Vector{NMRSample}, filters without any disk I/O.
NMRTools.NMRIO.findexperiments — Function
findexperiments(sample::NMRSample, dir::String; kw...) -> Vector{NMRExperiment}
findexperiments(sample::NMRSample, candidates::Vector{NMRExperiment}) -> Vector{NMRExperiment}Find all experiments matching sample based on the experiment date falling within the sample's creation–ejection timestamp window.
- With a directory path, calls
scanexperiments(dir; kw...)then filters. - With a pre-scanned
Vector{NMRExperiment}, filters without any disk I/O.
See also: scanexperiments, findsample.