API: Analysis1D
The 1D analysis framework: the entry points (relaxation1d, diffusion1d, tract, calibration1d, kinetics1d), the data types they build (Trace, Planes, Region, Dataset1D), the experiment types and their interface hooks, and the interactive window. See Creating New 1D Analyses for how these fit together.
NMRAnalysis.Analysis1D — Module
Analysis1DUnified framework for lightweight 1D NMR analyses (relaxation, TRACT, nutation calibration, kinetics, …). See PLAN.md in this directory for the design.
The analysis core operates on plain Trace/Planes/Dataset1D values and has no GUI or NMRData dependency in its computational path (the agreed "keep the science pure" split). NMRData is touched only by the adapters in nmrdata.jl.
Each analysis lives in a single self-contained expt-<name>.jl holding its entry point, type, interface methods, science and presentation - the layout used by GUI2D and Exchange1D. experiments.jl documents the interface and includes them; see expt-tract.jl for the fullest example.
NMRAnalysis.Analysis1D.BLANK_RICHTEXT — Constant
BLANK_RICHTEXTPlaceholder for "nothing to show". An empty RichText renders zero glyphs, and Makie's GlyphCollection cannot build itself from a zero-length glyph vector: it cannot infer rotations as Vector{Quaternionf} from an empty comprehension, and errors rather than rendering blank. A single space has one glyph and is invisible. Without it, resultstext crashes for every region of a NoFitting experiment and any region not yet fitted.
NMRAnalysis.Analysis1D.GAMMA_H — Constant
¹H gyromagnetic ratio / rad s⁻¹ T⁻¹.
NMRAnalysis.Analysis1D.MIN_GUI_REGION_WIDTH — Constant
Width (ppm) a zero-width region is opened at in the GUI, where it would otherwise be invisible and impossible to grab.
NMRAnalysis.Analysis1D.NOISE_LABEL — Constant
NOISE_LABELThe label of the row in regionlist.csv that records the noise position rather than a signal region. Reserved: a signal region of this name would be read back as the noise marker.
NMRAnalysis.Analysis1D.CurveFitModel — Type
CurveFitModel(func, paramnames, estimate; xlabel, ylabel)A parametric model fitted to (x, y) with func(x, p). estimate(x, y) returns initial parameters. Mirrors the ParametricModel pattern in GUI2D's models.jl.
NMRAnalysis.Analysis1D.Dataset1D — Type
Dataset1D(planes, noisecenter, [label, [sources]])The planes plus the universal noise position (ppm), a label saying where the data came from, and sources, the same per plane. Both are plain Strings, so results files can name what they were computed from without NMRData re-entering the analysis core.
sources is per plane because an experiment may combine files: TRACT loads a TROSY and an anti-TROSY spectrum. It defaults to label repeated. It is not a plane variable, being provenance rather than a coordinate: two files may be replicates with identical coordinates.
Only the noise centre is stored. The noise region takes the width of whichever signal region is being measured, which is what makes its integral a direct estimate of that region's noise (see integrate).
NMRAnalysis.Analysis1D.DiffusionExperiment — Type
DiffusionExperiment(dataset; γ, δ, Δ, σ, Gmax, temp=nothing, solvent=nothing, regions=…)Fit integrated intensity vs relative gradient strength (vars.gradient, 0–1) to the Stejskal–Tanner equation. The fitted D is the diffusion coefficient; postfit! adds the hydrodynamic radius via the Stokes–Einstein relation when the solvent and temperature are known.
NMRAnalysis.Analysis1D.Experiment1D — Type
Experiment1DAbstract supertype for 1D analyses. A concrete experiment is a thin composition supplying a dataset, a list of regions, a series model, and the fit-axis and grouping designation; the generic analyse pipeline does the rest. Only fitaxis is required; every other hook has a default, and the defaults below assume fields named dataset, regions and model.
One file per experiment, expt-<name>.jl, included at the foot of this file. See docs/src/advanced/creating_1d_analyses.md for the file layout and the full list of hooks, and expt-tract.jl for the fullest example.
NMRAnalysis.Analysis1D.Integration — Type
Integration(peakppm, noiseppm, ppmwidth)The integration triple shared with Exchange1D (prob.integration): a peak position, a noise position, and a common width, all in ppm. The noise region always takes the same width as the signal region, so its own uncertainty matches (see integrate). Passing one to an entry point skips the GUI and analyses directly.
NMRAnalysis.Analysis1D.KineticsExperiment — Type
KineticsExperiment(dataset; regions=[defaultregion(dataset)], model=NoFitting())Track integrated intensity of one or more named regions vs time (vars.time), grouped by run (vars.run) when present. regions defaults to a single peak-detected region; use the GUI (press A) to add further named regions of interest interactively rather than specifying them up front. v1 defaults to NoFitting (the deliverable is the intensity-vs-time trace); a kinetic CurveFitModel can be supplied to fit a model. A future iteration will add an NMF reduction over selected ROIs.
NMRAnalysis.Analysis1D.NoFitting — Type
NoFitting()Pass the reduced quantities through without fitting a model (used for kinetics v1, where the deliverable is intensity vs time).
NMRAnalysis.Analysis1D.NutationExperiment — Type
NutationExperiment(dataset; phase=:sine, regions=…)Fit integrated intensity vs pulse duration (vars.duration) to a damped sinusoid and derive the 90° pulse length (1/(4ν)) and B₁ inhomogeneity. Where the planes carry more than one power level (vars.power, in dB), each is fitted as its own series and the results combined into a calibration curve. A height (zero-width region at the observed signal) is the natural reduction but a finite region works identically.
NMRAnalysis.Analysis1D.Planes — Type
Planes(traces, vars)Long-format collection of 1D spectra: one Trace per row, with vars[i] a NamedTuple giving the values of the arrayed acquisition variables for that spectrum (e.g. (; time = 0.1, which = :trosy)). All rows must share the same set of variable names.
NMRAnalysis.Analysis1D.Region — Type
Region(label, lo, hi)
Region(label, δ)A named chemical-shift interval (ppm) used for integration. lo/hi are stored sorted, so the order in which the bounds are supplied does not matter. A zero-width region (lo == hi, or the single-shift constructor) selects the nearest point — i.e. a peak height.
NMRAnalysis.Analysis1D.RegionResult — Type
RegionResultEverything an analysis reports for one region: its series, one SeriesResult per grouping key, and one flat set of parameters. The 1D analogue of GUI2D's Peak.
A series' fitted parameters are named apart by seriesname (:R_trosy, :R_anti) and sit alongside whatever postfit! derives from them (:tauc), so one region is one row of results. Values are untyped: a viscosity looked up from temperature is a plain number where a fitted rate is a Measurement.
Parameters are stored in the unit paramunit names for them (a 90° pulse in µs, τc in ns), not in SI, so one stored number serves both the summary and any tabular export.
NMRAnalysis.Analysis1D.RelaxationExperiment — Type
RelaxationExperiment(dataset; model=:exponential, regions=…)Fit integrated intensity vs relaxation delay (vars.time) to a single exponential (model = :exponential) or to a recovery curve (model = :recovery); any SeriesModel may also be passed directly. A single integration region (override via regions).
NMRAnalysis.Analysis1D.ResultSeries — Type
ResultSeriesOne coloured curve in the result panel: observed points (Vector{Point2f}), errors (Vector{NTuple{3,Float64}} of (x, y, σ)), a fitline (Vector{Point2f}, empty if unfitted), and a label (e.g. the TRACT which, or kinetics' run; empty for an ungrouped single series).
NMRAnalysis.Analysis1D.ResultVisualisation — Type
ResultVisualisationHow an experiment's results are drawn in the fit panel. A hierarchy orthogonal to Experiment1D, joined by visualisationtype, as GUI2D's VisualisationStrategy is to its Experiment, so a presentation can be shared or swapped without touching the science.
A strategy implements three methods:
completeresultstate!(state, expt, ::V)— build the Observables the panel readsresultpanel!(gui, state, expt, ::V)— the live GUI panelplotresult!(ax, expt, result, label, i0, ::V)— the static CairoMakie export
The live and export paths share one data getter (here resultplotdata) so that what is saved is what was on screen.
SeriesVisualisation covers every curve-fit experiment and is the default.
NMRAnalysis.Analysis1D.SeriesModel — Type
SeriesModelAbstract supertype for the rule mapping a quantity series to derived parameters.
CurveFitModel: a continuous fit-axis, fitted by nonlinear least squares.NoFitting: carry the reduced quantities through unfitted, for an experiment whose deliverable is the series itself (kinetics), or one that needs to transform the series before fitting it inpostfit!rather than fitting the measured quantities directly.
NMRAnalysis.Analysis1D.SeriesResult — Type
SeriesResultOne measured series of a region: the planes sharing a grouping key, the quantity measured in each, and the curve fitted through them.
x is the sorted evolution parameter, y the measured quantities, planes the dataset plane each point came from (so the series file can name its source spectrum), and coefficients the model's fitted coefficients in paramnames order, named onto the region by liftparameters!.
NMRAnalysis.Analysis1D.SeriesVisualisation — Type
SeriesVisualisation()Observed points with error bars plus a fitted line, one colour per group. The default, and what relaxation, TRACT, nutation, diffusion and kinetics all use.
NMRAnalysis.Analysis1D.Trace — Type
Trace(δ, y)A single 1D spectrum: a chemical-shift axis δ (ppm) and intensities y.
Plain vectors, with no dependency on NMRData, Makie or GUI state: the analysis layer operates on Traces, and the adapters in nmrdata.jl convert NMRData into them.
NMRAnalysis.Analysis1D.TractExperiment — Type
TractExperiment(dataset; ωN, f, regions=…)Fit TROSY and anti-TROSY decays (grouped by vars.which ∈ {:trosy, :anti}) and derive the rotational correlation time τc from the cross-correlated relaxation-rate difference ΔR = R(anti) − R(trosy). ωN is the ¹⁵N Larmor frequency (rad s⁻¹) and f the dipole/CSA cross-correlation prefactor (see tractf).
NMRAnalysis.B1Calibration — Method
B1Calibration(results::AbstractVector{RegionResult}; kwargs...)
B1Calibration(result::RegionResult; kwargs...)
B1Calibration(specs::AbstractVector; kwargs...)
B1Calibration(spec; kwargs...)The B₁ calibration a nutation analysis measured: the field fitted at each power level, and the smallest of its B₁ inhomogeneity estimates.
Pass the results of calibration1d, having checked the fits in the analysis window, or pass the calibration experiments themselves to have them fitted without a window opening (which is what exchange1d(…; calibration=["cal/1", …]) does; keywords are forwarded to calibration1d). To keep the analysis behind it as well as the calibration itself, use calibrationanalysis, which hands back both. Where several regions were integrated, the first is the calibration; the others are presumably there for comparison.
Every power level has to be known, since a calibration is a map from power to field: give them with power=, or annotate the sequence with calibration.power.
Example
cal = B1Calibration(calibration1d(["cal/1", "cal/2"]))
hz(Power(12.0, :dB), cal) # field at a power the calibration did not measureBase.show — Method
show(io, result::RegionResult)One line per region: its label followed by every parameter reported for it, so that closing an analysis window prints a short table rather than pages of measured points.
Units are absent, being the one thing a RegionResult cannot know: paramunit is dispatched on the experiment. The results panel, summary.txt and the CSVs carry them.
NMRAnalysis.Analysis1D.DampedSinusoidModel — Method
DampedSinusoidModel(; phase = :sine)Nutation of an inhomogeneous B₁ field: A·sin(2π·ν·t)·exp(−½(2π·σ·ν·t)²) (or cos when phase = :cosine), parameters [A, ν, σ].
ν is the mean nutation frequency (Hz), from which the 90° pulse length follows as 1/(4ν), and σ is the width of the B₁ distribution as a percentage of ν, which is what damps the nutation: averaging sin(2πνt) over a Gaussian distribution of ν with mean ν̄ and standard deviation σν̄ gives sin(2πν̄t)·exp(−½(2πσν̄t)²), a Gaussian decay rather than an exponential one. Fitting the envelope this way makes σ the same quantity B1Distribution later samples, instead of an exponential rate needing conversion.
σ is fitted in percent rather than as a fraction so that every inhomogeneity this analysis reports is in the unit it is quoted in, and incidentally so that the three parameters are of comparable magnitude, which is what a Levenberg-Marquardt step prefers.
Relaxation during the pulse damps the nutation too, and is not separated here: σ is therefore an upper bound, worst at the lowest power where the pulses are longest, which is why a multi-power calibration reports the smallest of its estimates.
Only σ² enters, so the fitted sign is arbitrary and postfit! reports |σ|.
NMRAnalysis.Analysis1D.ExponentialModel — Method
ExponentialModel()Single exponential decay A·exp(−R·t), parameters [A, R]. Suitable for T2/T1ρ relaxation and TROSY/anti-TROSY decays.
NMRAnalysis.Analysis1D.RecoveryModel — Method
RecoveryModel()Inversion/saturation recovery A·(1 − C·exp(−R·t)), parameters [A, C, R]. Used only here: TRACT always fits a plain exponential (ExponentialModel, shared in seriesmodels.jl since both experiments use it), never a recovery curve.
NMRAnalysis.Analysis1D.StejskalTannerModel — Method
StejskalTannerModel(; γ, δ, Δ, σ, Gmax)Stejskal–Tanner diffusion decay A·exp(−(γ·δ·σ·g·Gmax)²·(Δ−δ/3)·D), fitted against the relative gradient strength g (0–1). Parameters are [A, D] with D in units of 10⁻¹⁰ m² s⁻¹ (as in the legacy routine), so the physical coefficient is D · 1e-10.
NMRAnalysis.Analysis1D.__init__ — Method
Register the interactive 1D analyses with the analysis-dispatch registry, so analyse routes annotated experiments here. These replace the registrations previously made by the readline-based routines.
Only the analyses that can run from a filename alone are registered: TRACT needs a TROSY/anti-TROSY pair, diffusion needs the gradient list, and kinetics needs named regions, so those are invoked directly rather than dispatched.
NMRAnalysis.Analysis1D.addregion! — Method
addregion!(state, lo, hi)Add a new region spanning lo..hi (order-independent) and select it. Callers that want the user to immediately name it (as the GUI's 'A' shortcut does) follow up by entering rename mode themselves.
NMRAnalysis.Analysis1D.analyse — Method
analyse(e, [dataset, regions]; isfitting=true) -> Vector{RegionResult}Run the full analysis: measure, fit, then post-fit. The return type does not depend on the experiment or on whether anything was fitted, which is what lets the GUI's state[:result] Observable keep a stable element type while it is still empty.
NMRAnalysis.Analysis1D.analyse1d — Method
analyse1d(experiment) -> Vector{RegionResult}Run a 1D analysis. Equivalent to analyse on an Experiment1D; provided under a distinct name so it can be re-exported without colliding with the registry-based analyse dispatcher in the parent module.
NMRAnalysis.Analysis1D.askdurations — Method
Pulse durations, asked for in µs (as they are set on the spectrometer) but returned in the seconds the analysis works in.
NMRAnalysis.Analysis1D.asknutationphase — Method
Offer the choice of modulation. Without prompting, a sine modulation is assumed.
NMRAnalysis.Analysis1D.askpowers — Method
Power levels, asked for in the dB attenuation the spectrometer sets them as. Returns nothing without prompting, an unknown power costing only the calibration curve.
NMRAnalysis.Analysis1D.askrelaxationmodel — Method
Offer the choice of relaxation model. Without prompting, a plain decay is assumed.
NMRAnalysis.Analysis1D.baseparam — Method
baseparam(name) -> SymbolThe quantity a parameter name refers to, with any series suffix removed: :R_trosy → :R. Labels and units are looked up under this name.
NMRAnalysis.Analysis1D.beginrename! — Method
beginrename!(state; initiator=:mouse)Begin renaming the active region (shared by the button and the 'R' key). When triggered :keyboard, the same keypress that opened rename mode also emits a unicode-input event for its own character (e.g. 'r') a moment later — enter the intermediate :renamingstart mode so setupkeyboard!'s unicode handler can swallow that spillover character rather than prepending it to the new name (mirrors the 2D fitting GUI's rename handshake).
NMRAnalysis.Analysis1D.calibration1d — Method
calibration1d(spec; durations=nothing, phase=nothing, power=nothing, regions=nothing,
integration=nothing, window=true, prompt=isinteractive())
calibration1d(specs::AbstractVector; ...)Analyse a 1D nutation calibration, reporting the nutation frequency, 90° pulse length and B₁ inhomogeneity, then open the analysis window.
Given several spectra recorded at different power levels, each is fitted separately and the results combined into a calibration curve: the field at a reference power and the linearity of the amplifier's response, 1 being the ideal ν₁ ∝ √W. A single spectrum still calibrates, with the linearity assumed ideal. Either way B1Calibration(results) turns the analysis into the calibration that exchange1d takes, so CEST and R₁ρ are simulated with measured field strengths and a measured B₁ inhomogeneity rather than nominal ones.
Pulse durations are taken from durations if given, else from the calibration.duration annotation, and otherwise you are asked for them; the modulation likewise from phase, else the calibration.model annotation, else a question; the power level from power, else the calibration.power annotation, else a question. None of the annotations is required, and an unknown power costs only the calibration curve, not the analysis.
Arguments
durations: pulse durations, in seconds, one per spectrum of the series. Applies to every spectrum given; where they differ, each spectrum's own annotation is what to rely on.phase::sine(starting from equilibrium) or:cosine(from transverse magnetisation).power: the power each spectrum was recorded at, asPowers or as numbers in dB, one per spectrum.regions: integration regions to start from, instead of one on the tallest peak.integration: a(; peakppm, noiseppm, ppmwidth)triple, which skips the window and analyses that region directly.window: whether to open the analysis window at all.falseanalyses the default region (the tallest peak) without one, which is howcalibrationanalysisfits a calibration without interrupting the analysis that asked for it.prompt: whether to ask for anything that could not be determined. Defaults tofalseoutside an interactive session, where a missing value raises an error instead.
Example
results = calibration1d(["cal/1", "cal/2", "cal/3"])
cal = B1Calibration(results) # ready for exchange1d(...; calibration=cal)NMRAnalysis.Analysis1D.calibrationanalysis — Method
calibrationanalysis(specs; kwargs...) -> (calibration, save)Fit nutation calibration experiments without a window, returning the B1Calibration they measure and a function that writes the analysis into a folder, given one.
Whether and where those results are kept is for the analysis that asked for the calibration to decide: a calibration fitted on the way to an exchange fit belongs inside that fit's output folder, written when it is written, and not written at all if the fit is abandoned. Keywords are calibration1d's.
Example
cal, save = calibrationanalysis(["cal/1", "cal/2"])
save(joinpath("out", "calibration")) # fit.pdf, calibration.pdf, summary.txt, …NMRAnalysis.Analysis1D.calibrationplot — Method
calibrationplot(cal) -> FigureThe calibration curve: the field measured at each power level, the fitted power law through them, and the residuals from it.
ν₁ is drawn on a log axis against power in dB, the coordinates in which the ideal law is a straight line, so amplifier compression shows as curvature. The deviations are a percent or two and invisible against a decade of field strength, hence the residual panel underneath, in percent rather than in σ: what matters here is how far the amplifier departs from the law, not how that compares with the fitting uncertainty.
NMRAnalysis.Analysis1D.centre — Method
centre(region) -> Float64Midpoint of a region (ppm). Regions are stored by their bounds, but centre-and-width is the natural handle for interaction, so both views are available.
NMRAnalysis.Analysis1D.column — Method
column(planes, name) -> VectorReturn the values of variable name across all planes.
NMRAnalysis.Analysis1D.commitondefocus! — Method
commitondefocus!(tb::Textbox)Commit tb's displayed text to stored_string when it loses focus. Makie's Textbox only commits on Enter; clicking away otherwise leaves the typed text on screen without ever applying it to stored_string (and hence to whatever listens on it).
NMRAnalysis.Analysis1D.completeresultstate! — Method
completeresultstate!(state, expt, ::SeriesVisualisation)Per-series plot data for the active region (one entry per group, e.g. TRACT's TROSY/anti-TROSY), flattened into the contiguous, coloured arrays Makie plot objects want - one scatter!/lines! per panel rather than a variable number of separate plot calls.
NMRAnalysis.Analysis1D.coordinatetext — Method
One coordinate's value with its unit, as a label: (:power, 11.11) → "11.11 dB".
NMRAnalysis.Analysis1D.coordinateunit — Method
coordinateunit(expt, name) -> StringASCII unit for a coordinate, the fit axis or a grouping variable, as it appears in a column header. Kept apart from paramunit because the two name spaces are independent: nothing stops an experiment arraying a variable named like a fitted parameter. Categorical coordinates (:which, :run) and relative ones (:gradient) have no unit.
NMRAnalysis.Analysis1D.datasetfromspec — Method
datasetfromspec(spec, vars; noisecenter=defaultnoisecentre(spec)) -> Dataset1DBuild a Dataset1D from a pseudo-2D spec and a vector of per-plane variable NamedTuples (length(vars) == number of planes).
NMRAnalysis.Analysis1D.defaultamideregion — Method
defaultamideregion(; label="amide") -> RegionTRACT integrates the bulk backbone amide envelope rather than a single resolved peak, so its default region is the conventional 7.5-9.5 ppm amide window - unlike every other experiment's defaultregion, which centres a narrow window on the tallest peak.
NMRAnalysis.Analysis1D.defaultnoisecentre — Method
defaultnoisecentre(spec; frac=0.9) -> Float64A fallback noise position: frac of the way across the chemical-shift axis. The GUI lets the user reposition it.
NMRAnalysis.Analysis1D.defaultregion — Method
defaultregion(dataset; label="signal", width=defaultregionwidth(...)) -> RegionA sensible default single integration region: width ppm wide (2% of the spectral width by default) centred on the tallest peak (by absolute intensity) of the strongest plane. Used as the default regions for every experiment with a single signal; the GUI lets the user reposition and resize it, or add further regions.
The strongest plane rather than the first, because the first plane of a nutation calibration is recorded at the shortest pulse length and holds no signal, so its tallest point is noise. For a decay or a gradient ramp the first plane is the strongest, and the region is the same either way.
NMRAnalysis.Analysis1D.defaultregionwidth — Method
defaultregionwidth(δ) -> Float64A default region width: 2% of the chemical-shift range spanned by δ, matching the noise marker's drag-handle width.
NMRAnalysis.Analysis1D.deleteregion! — Method
deleteregion!(state, i)Remove region i, if it exists.
NMRAnalysis.Analysis1D.diffusion1d — Function
diffusion1d()
diffusion1d(spec, gradients=nothing; coherence=SQ(H1), δ=nothing, Δ=nothing,
σ=nothing, Gmax=nothing, regions=nothing, integration=nothing,
prompt=isinteractive())Analyse a diffusion experiment, fitting the Stejskal-Tanner equation to extract the diffusion coefficient (and the hydrodynamic radius where the solvent and temperature are known), then open the analysis window.
Called interactively, the acquisition parameters are read from the experiment and offered for confirmation before the window opens, exactly as they must be: Bruker records the gradient pulse length δ (2·p30), the diffusion delay Δ (d20) and the gradient shape (gpnam6), but not the gradient ramp itself, so the initial and final gradient strengths have to be supplied. Anything passed as an argument is taken as given and not asked about.
Arguments
gradients: relative gradient strengths (0 to 1), one per spectrum. Supply these for any ramp other than a linear one, which is what the prompt constructs.coherence: the coherence whose gyromagnetic ratio applies (defaultSQ(H1)).δ: gradient pulse length, in seconds.Δ: diffusion delay, in seconds.σ: gradient shape factor (0.9 for the smoothed-squareSMSQshapes, 0.6366 forSINE).Gmax: maximum gradient strength, in T m⁻¹ (0.55 on a typical Bruker system).regions: integration regions to start from, instead of one on the tallest peak.integration: a(; peakppm, noiseppm, ppmwidth)triple, which skips the window and analyses that region directly.prompt: whether to ask for anything that could not be determined. Defaults tofalseoutside an interactive session, where a missing value raises an error instead.
Examples
diffusion1d("106") # asks for the gradient ramp
diffusion1d("106", 0.05:0.05:0.95) # ramp given explicitly
diffusion1d("106", g; δ=4e-3, Δ=0.1, σ=0.9, Gmax=0.55) # nothing left to askNMRAnalysis.Analysis1D.displaylabel — Method
displaylabel(expt, name) -> Stringparamlabel for a parameter as stored on a region, which for a fitted one carries the series it came from: :R_trosy shows as "Relaxation rate (trosy)". The quantity comes from baseparam, so an experiment's label table needs only bare names.
NMRAnalysis.Analysis1D.estimatefrequency — Method
estimatefrequency(x, y, trig) -> Float64Initial estimate of the nutation frequency: the frequency whose modulation correlates best with the data, scanned over the frequencies the sampling can resolve.
How much of a period a calibration covers is not something the data say - the annotated sequence runs to a nominal 720°, and the B₁ inhomogeneity is only measurable over several periods - so assuming half a period, as this did before, starts the fit a factor of four out on a real experiment. A coarse matched filter costs nothing next to the fit it seeds, and the scan runs from half a period across the sampled range up to the Nyquist frequency of the pulse-duration increment.
NMRAnalysis.Analysis1D.experimentinfo — Function
experimentinfo(expt, [dataset]) -> StringMulti-line description of the experiment, written as the comment header of every CSV. Generic across every experiment - the analysis name, where the data came from, how many spectra and which variables are arrayed are all already known to the framework - so experiments need not override it (GUI2D's equivalent is written out per experiment).
The dataset is passed explicitly because the one the experiment was constructed with still carries the noise position it started at, where the GUI's live dataset carries wherever the user dragged the marker to. Provenance has to describe the data as analysed.
NMRAnalysis.Analysis1D.fitaxis — Function
fitaxis(expt) -> SymbolThe arrayed variable forming the x-axis of every series: a relaxation delay, a gradient strength, a pulse duration. Required of every experiment, there being no sensible default.
NMRAnalysis.Analysis1D.fitseries — Method
fitseries(model, x, y) -> NamedTupleFit model to evolution values x and reduced quantities y (a Vector{Measurement}). Returns (; params, names, model, converged) with params a Vector{Measurement} (value ± standard error). The fit is noise-weighted using the uncertainties carried by y (addressing the "scale fitting by noise" TODO).
NMRAnalysis.Analysis1D.fitvalues — Method
fitvalues(series) -> Vector{Float64}The model evaluated at the measured coordinates, for the I_fit column - not on a fine grid, so that a residual is a subtraction. NaN (written NA) where nothing was fitted.
NMRAnalysis.Analysis1D.fmt — Function
Compact, consistently-rounded rendering of a Measurement (or plain number).
NMRAnalysis.Analysis1D.gradientramp — Method
gradientramp(n; prompt=true) -> Vector{Float64}Ask for the gradient ramp, which Bruker does not store: the initial and final gradient strengths (%) of a linear ramp over n spectra, matching TopSpin's dosy dialogue. Its quadratic and exponential ramps are not generated here; pass those gradient strengths to diffusion1d directly.
NMRAnalysis.Analysis1D.groupname — Method
groupname(expt, group) -> StringHuman-readable label for a grouping key: (which = :trosy,) → "trosy", (power = 11.11,) → "11.11 dB".
The unit comes from coordinateunit, the same table that labels the coordinate's column in series.csv, because a curve labelled 11.11 names nothing a reader can act on. A categorical coordinate has no unit and is shown as it stands.
NMRAnalysis.Analysis1D.groupseries — Method
groupseries(planes, cols) -> Vector{Pair{NamedTuple,Vector{Int}}}Group plane indices by the values of the variables named in cols, preserving order of first appearance. With cols = () every plane falls in one group keyed by the empty NamedTuple. A series is the set of planes sharing all grouping variables, differing only in the fit axis.
NMRAnalysis.Analysis1D.gui! — Method
gui!(expt::Experiment1D; call=nothing)Launch the interactive analysis window for expt. call is the AnalysisCall the entry point recorded, which summary.txt prints as a line repeating the analysis; it is nothing when gui! is driven directly rather than through an entry point. The left column overlays all spectral planes with draggable integration region(s) and a noise marker; the result panel below shows the live fit for the active region. The active region is whichever the mouse is over (or was last clicked), named in the right-hand column. Returns the GUI state when the window closes.
Keyboard shortcuts (mirroring the 2D fitting GUI)
A: add a region. A quick tap adds a default-width region under the cursor; press, drag, and release to choose the width.R: rename the active region.D: delete the active region.- Left/Right arrows: step through spectra.
- Up/Down arrows: scale the spectrum's y-axis (×2 / ÷2).
- Shift+scroll: resize the active region, about its own centre.
Q: close the window.
NMRAnalysis.Analysis1D.hasvar — Method
hasvar(planes, name) -> BoolWhether the planes carry an arrayed variable called name.
NMRAnalysis.Analysis1D.integrate — Function
integrate(region, expt[, dataset]) -> Vector{Measurement{Float64}}Stage 1: reduce region to one measured quantity per plane. The default integrates; an experiment that measures its regions some other way overrides this method.
dataset is separate from the experiment's own so the GUI can measure against interactively-positioned regions and noise.
NMRAnalysis.Analysis1D.integrate — Method
integrate(region, dataset) -> Vector{Measurement{Float64}}Integrate region over every plane of dataset, with an uncertainty attached to each.
The uncertainty is measured rather than taken from spec[:noise]: the noise on an integrated region depends on its width and on the noise where it actually sits, not on the whole-spectrum RMS level. So a noise region of the same width, centred at dataset.noisecenter, is integrated over every plane and the standard deviation of those integrals taken. With uniform noise this approaches sqrt(n points), the trace intensities already being noise-normalised, but it tracks a locally noisier baseline.
NMRAnalysis.Analysis1D.integrate — Method
integrate(region, trace) -> Float64Summed intensity of region in one plane (a height when the region has zero width — the nearest point is taken). The summed intensity is the convention used by the legacy 1D routines and by GUI2D's intensity analysis.
NMRAnalysis.Analysis1D.isconverged — Method
isconverged(result) -> BoolWhether every one of a region's series fitted successfully.
NMRAnalysis.Analysis1D.kinetics1d — Method
kinetics1d(spec, times; run=nothing, regions=nothing, model=NoFitting(), integration=nothing)Track integrated intensity of one or more named regions against times, optionally tagged by run for several time series.
regions defaults to a single peak-detected region; add further named regions of interest interactively in the GUI (press A) rather than specifying them up front.
NMRAnalysis.Analysis1D.liftparameters! — Method
liftparameters!(result)Name every series' fitted coefficients onto the region, via seriesname. Runs as each region is measured, so postfit! has only to add what it derives.
NMRAnalysis.Analysis1D.nextlabel — Method
Number the default label uniquely against the current region list. "peak" rather than "region", so the heading built from it ("Region: peak2") doesn't repeat "region" - and to match the vocabulary GUI2D uses for the same idea.
NMRAnalysis.Analysis1D.nplanesfromspec — Method
nplanesfromspec(spec) -> IntNumber of 1D traces spec will contribute: the product of every axis but the chemical shift, counted the same way tracesfromspec flattens them.
NMRAnalysis.Analysis1D.nutationexperiment — Method
nutationexperiment(specs; durations, phase, power, regions, prompt)
-> (expt, dataset, regions, call)Everything calibration1d resolves before it fits: the spectra loaded, their pulse durations and power levels found, the experiment built from them, and the call that would repeat the analysis.
Separate from the entry point so that a calibration fitted on behalf of another analysis can be saved afterwards from the same pieces the entry point would have saved - see calibrationanalysis.
NMRAnalysis.Analysis1D.nutationphase — Method
nutationphase(annotation) -> Symbol or nothingThe modulation named by a calibration.model annotation, or nothing where there is no annotation to read - so the entry point can fall through to asking.
NMRAnalysis.Analysis1D.panelwidth — Method
panelwidth(expt, result, activelabel) -> IntThe label-column width for the results panel: the longest display label among the parameters shown for activelabel, plus a gap, or nothing when there is nothing to show yet. Computed across the whole panel so "Amplitude (trosy)" and "Correlation time (τc)" share one column.
NMRAnalysis.Analysis1D.param — Method
param(result, name) -> valueValue of parameter name (a Symbol or a String) for a region.
NMRAnalysis.Analysis1D.paramblock — Function
paramblock(io, expt, params, width=nothing)Write every entry of a parameter dictionary as name value unit, in insertion order, the names padded to width (computed from params alone when omitted) so the values line up. The GUI panel passes a width computed across every region (panelwidth) so the column does not jump as regions are selected; summary.txt leaves it to align to its own block.
NMRAnalysis.Analysis1D.paramblock — Function
paramblock(io, expt, result::RegionResult, width=nothing)Everything a region reports, a block per series under a heading naming it, then the quantities derived across them. See paramgroups.
NMRAnalysis.Analysis1D.parameternames — Method
parameternames(results) -> Vector{Symbol}Every parameter name present across results, in order of first appearance. The union, so the table stays rectangular when one region derived something another did not.
NMRAnalysis.Analysis1D.paramgroups — Method
paramgroups(result) -> Vector{Pair{NamedTuple,OrderedDict{Symbol,Any}}}A region's parameters split into one block per series, each keyed by that series' grouping key and holding its parameters under their bare names, followed by a block keyed by the empty NamedTuple for whatever belongs to the region rather than to any one series - the quantities postfit! derived from all of them.
This is what turns a flat dump of nu_11.11, nu_31.11, pulse90_11.11 … into something a reader can take in: each condition's results together, under a heading naming it. A region with a single series has one block with an empty key, so nothing is grouped and nothing is indented that was not before.
NMRAnalysis.Analysis1D.paramlabel — Method
paramlabel(expt, name) -> StringDisplay name for parameter name (fitted or derived). Experiment-dispatched: the default falls back to the small shared table above, then to the bare symbol. An experiment that introduces its own parameters overrides this with its own local table - see e.g. NUTATION_PARAM_LABELS in expt-nutation.jl.
NMRAnalysis.Analysis1D.paramnames — Method
paramnames(model) -> Vector{String}The model's fitted parameter names, in coefficient order. Empty for NoFitting, which fits nothing.
NMRAnalysis.Analysis1D.paramtext — Function
paramtext(expt, params, width=nothing) -> Stringparamblock, returned as a string rather than written to an IO - the form the GUI panel wants, built from the same alignment logic summarytext uses for summary.txt so the two never drift apart. Empty (not a blank line) when params is empty, so a caller can skip a block that has nothing to show.
NMRAnalysis.Analysis1D.paramunit — Method
paramunit(expt, name) -> StringUnit for parameter name, dispatched and overridden as paramlabel is.
Units are held in ASCII ("s-1", "us", "1e-10 m2/s"), because that is the form the CSV column headers carry and a file header must survive being opened on any machine - see docs/src/advanced/conventions.md. prettyunit turns one into the typeset form for the GUI panel and summary.txt, so there is one table rather than two that can drift.
NMRAnalysis.Analysis1D.paramwidth — Method
paramwidth(expt, groups) -> IntWidth of the label column across every block of paramgroups, indentation included, so the values line up down the whole region and not just within a block. Zero where there is nothing to show.
NMRAnalysis.Analysis1D.pickregion — Method
pickregion(traces; peakppm=nothing, noiseppm=nothing, ppmwidth=defaultregionwidth(...)) -> (; peakppm, noiseppm, ppmwidth)
pickregion(specs; kwargs...)Interactively choose a single integration region and a noise position, returning the integration triple. All traces are overlaid, so a region can be chosen that suits every spectrum at once - which is what is wanted when one region must serve a whole set of experiments (e.g. Exchange1D's integrate!, which applies one triple to every experiment in the problem). Drag the peak region or noise marker to move it, its edges to resize it, type an exact ppm value into the text boxes, or Shift+scroll to resize - matching gui!'s main GUI.
This is the region-selection front-end on its own, without any fitting: use it where the heavy fitting lives elsewhere.
NMRAnalysis.Analysis1D.plaintext — Method
plaintext(text) -> RichTextWrap text in an explicit font=:regular span. A RichText font is not scoped to each sibling: a plain String child inherits whatever font the previous sibling left active, so without this a parameter block following a bold heading renders bold too.
NMRAnalysis.Analysis1D.planevars — Method
Per-plane variables for one spectrum of a calibration: the pulse duration always, and the power level where it is known. Powers are rounded to the 0.01 dB they are set to on the spectrometer, so that the series they name carries a legible column header.
NMRAnalysis.Analysis1D.plotresult! — Method
plotresult!(ax, expt, result, label, i0, ::SeriesVisualisation) -> IntDraw region label into a static axis, starting colour indices at i0 + 1; returns the number of series drawn, so callers can decide whether a legend is worthwhile. Shares resultplotdata with the live panel, so an exported plot matches what was on screen.
NMRAnalysis.Analysis1D.plotseries! — Method
plotseries!(ax, series, colour; label=nothing)Draw one measured series and its fit into an axis: error bars, points, and the fitted curve where there is one. The one place a series becomes marks on a plot, so an experiment laying its series out differently (resultfigure) draws them the same way.
NMRAnalysis.Analysis1D.postfit! — Method
postfit!(result, expt)Stage 2: derive the quantities reported for one region from its fitted series, recording them with setpost! - nutation's 90° pulse from ν, diffusion's rH from D, TRACT's τc from both rates. result holds every series of the region, so anything combining conditions belongs here rather than in postfitglobal!. The default derives nothing.
NMRAnalysis.Analysis1D.postfitglobal! — Method
postfitglobal!(results, expt)Stage 3: fit or derive quantities spanning every region of the analysis, and record them on the relevant results. Runs after every postfit!. Mirrors GUI2D's postfitglobal!(expt).
NMRAnalysis.Analysis1D.powerdb — Method
powerdb(power) -> Vector{Float64} or nothingPower levels as dB attenuation: Powers converted, bare numbers taken to be dB already, and nothing where any of them is missing - a calibration curve needs every power or none.
NMRAnalysis.Analysis1D.ppmbox! — Method
ppmbox!(fig, parent, row, col, obs; digits=3, boxwidth=90)A chemical-shift text box two-way bound to obs: typing a number sets it, and dragging the corresponding marker on the plot rewrites the displayed text.
NMRAnalysis.Analysis1D.preparestate — Method
preparestate(expt) -> Dict{Symbol,Any}Build the Observable graph for expt: regions (position/width/label), the noise marker position, current spectrum, GUI interaction mode, and the live analysis result with its derived plot data.
NMRAnalysis.Analysis1D.prettyparamunit — Method
Display unit for a parameter stored on a region: its quantity's unit, typeset.
NMRAnalysis.Analysis1D.prettyunit — Method
prettyunit(unit) -> StringThe typeset form of an ASCII unit, for display only: "s-1" → " s⁻¹", "us" → " µs". Includes the leading space so it appends to a formatted value, and returns "" for a dimensionless quantity. Anything not in the table is shown as written ("Hz", "ns").
NMRAnalysis.Analysis1D.primaryparam — Method
primaryparam(expt) -> SymbolThe experiment's headline quantity: the parameter a reader wants first, listed first among the derived columns of any tabular export. Defaults to the amplitude A that every CurveFitModel here fits. Mirrors GUI2D's primaryparam(expt).
NMRAnalysis.Analysis1D.quit! — Method
Close the GUI window, deferred so the click/keypress event finishes first (matches GUI2D's quit!) - calling GLMakie.closeall() synchronously from inside the renderloop's own event callback tears down the GL context while it is still being polled.
NMRAnalysis.Analysis1D.readregions! — Method
readregions!(state, filepath) -> IntRestore a saved region list, replacing whatever is currently set, and return the number of signal regions read. The row labelled noise sets the noise position from its centre; every other row is a region.
Written for regionlist.csv but deliberately tolerant, so that a hand-made list works and so does a results.csv from before the region bounds moved out of it: any file with a label column and lo/hi columns is read, and a # Noise position / ppm: comment is honoured where there is no noise row.
NMRAnalysis.Analysis1D.rebuildregionspans! — Method
(Re)create one vspan! per region, coloured to highlight the active one. Called once at startup and again whenever the number of regions changes (add/delete); simple position/width/active-state changes are handled by the spans' own Observables and don't need a rebuild.
Each span's position/colour Observables are plain Observables kept in sync by an explicit on listener (rather than lifting straight off state[:regions]/ state[:active], index i baked in) so the listener can be off'd here before the next rebuild. Without that, an old listener for index i stays registered on state[:regions] after its span is deleted, and fires (indexing out of bounds) the next time a region is removed and the list is shorter than i.
NMRAnalysis.Analysis1D.recentre — Method
recentre(region, c) -> RegionThe same region, same width and label, moved to be centred on c.
NMRAnalysis.Analysis1D.regionlisttable — Method
regionlisttable(regions, noisecentre, defaultwidth) -> (header, rows)Column names and rows for regionlist.csv: what the user picked, as opposed to what the fit produced. One row per region, plus one for the noise position.
The noise marker has a position but no width of its own - the width used to estimate a region's uncertainty always matches that region's own (see integrate) - so it is written as a region defaultwidth wide, or as wide as the widest signal region where that is wider. Reading its centre back is what matters; the width is there so the row means something on its own and so the file needs no separate convention for it.
NMRAnalysis.Analysis1D.relaxation1d — Method
relaxation1d(spec; tau=nothing, model=nothing, regions=nothing, integration=nothing,
prompt=isinteractive())Analyse a 1D relaxation experiment (T1/T2, or inversion recovery) from a pseudo-2D spec (a path or an NMRData), then open the analysis window.
Relaxation delays are taken from tau if given, else from the relaxation.duration annotation, else from the vdlist; if none of those is available you are asked for them. The model is taken from model if given, else from the relaxation.model annotation, and otherwise you are asked to choose one. Neither annotation is required.
Arguments
tau: relaxation delays, in seconds, one per spectrum.model::exponentialfor a decayA exp(-Rt),:recoveryfor an inversion/saturation recoveryA [1 - C exp(-Rt)], or anySeriesModel.regions: integration regions to start from, instead of one on the tallest peak.integration: a(; peakppm, noiseppm, ppmwidth)triple, which skips the window and analyses that region directly.prompt: whether to ask for anything that could not be determined. Defaults tofalseoutside an interactive session, where a missing value raises an error instead.
Examples
relaxation1d("11") # annotations or vdlist, or asks
relaxation1d("11"; tau=[0.01, 0.05, 0.1, 0.5]) # delays given explicitly
relaxation1d("11"; model=:recovery) # inversion recoveryNMRAnalysis.Analysis1D.relaxationmodel — Method
relaxationmodel(annotation) -> Symbol or nothingThe model named by a relaxation.model annotation, or nothing where there is no annotation to read - so the entry point can fall through to asking.
NMRAnalysis.Analysis1D.relaxationseriesmodel — Method
relaxationseriesmodel(model) -> SeriesModelThe curve fitted for a named relaxation model. A SeriesModel passes straight through, so an unusual decay can be supplied directly without a name having to be invented for it.
NMRAnalysis.Analysis1D.resultfigure — Method
resultfigure(expt, result, labels) -> FigureThe figure an analysis saves for the regions named in labels: every series of every region on one axis, with a legend where there is more than one.
An experiment whose series do not share an x-range overrides this. A nutation calibration is the case in point: the 90° pulse at the lowest power can be ten times the longest duration sampled at the highest, so one axis shows one series and a spike at the origin.
NMRAnalysis.Analysis1D.resultfigure — Method
resultfigure(expt::NutationExperiment, result, labels) -> FigureOne panel per power level rather than one axis for all of them.
The whole point of calibrating at several powers is that they nutate at different rates, so their pulse durations differ by the same factor: 123 µs against 1220 µs here, which on a shared axis leaves the fast series as a spike against the origin. Each series gets its own axis, autoscaled to its own durations, stacked in the order they were measured and labelled once underneath.
NMRAnalysis.Analysis1D.resultkeys — Method
resultkeys(expt) -> Vector{Symbol}The grouping coordinates that, with the region label, identify a row of results.csv: (:which,) for TRACT, (:run,) for a multi-run kinetics series, none for a single-series experiment.
NMRAnalysis.Analysis1D.resultlabels — Method
axis labels for the result panel
NMRAnalysis.Analysis1D.resultpanel! — Method
resultpanel!(gui, state, expt, ::SeriesVisualisation)Build the live fit panel into gui[:panelresult], and record its axis as gui[:axfit].
NMRAnalysis.Analysis1D.resultplotdata — Method
resultplotdata(expt, result, activelabel) -> Vector{ResultSeries}Plot primitives for the active region, one ResultSeries per series, so each is drawn in its own colour.
NMRAnalysis.Analysis1D.resultstable — Method
resultstable(expt, results) -> (header, rows)Column names and rows for results.csv: one row per region, carrying every parameter reported for it, with the experiment's primaryparam first. A region measured under several conditions keeps them all on that row under the names seriesname gave them, so TRACT writes R_trosy and R_anti beside the tauc computed from the two.
The region bounds are not here: they are what the user picked, and live in regionlist.csv (see regionlisttable).
NMRAnalysis.Analysis1D.resultstext — Function
resultstext(expt, result, activelabel, width=nothing) -> RichTextEvery parameter reported for the active region, as one block - the fitted ones under the names their series gave them, then whatever the experiment derived from them. Doesn't repeat the region name, which is already shown elsewhere in the panel.
width aligns the values to a fixed column - see panelwidth; omitted, the block aligns only to its own labels.
NMRAnalysis.Analysis1D.resultxfactor — Method
resultxfactor(expt) -> Float64Multiplier applied to the result panel's x-values for display, 1.0 except where a time-valued axis reads better in ms or µs (see timescale). Fitting always uses the raw values.
NMRAnalysis.Analysis1D.richtext — Method
richtext(spans) -> RichTextrich(spans...), substituting BLANK_RICHTEXT when spans is empty - see its docstring for why that substitution is load-bearing, not decorative.
NMRAnalysis.Analysis1D.roiindices — Method
roiindices(region, trace) -> Vector{Int}Indices of trace.δ falling within region. For a zero-width region (or one that contains no grid points) the single nearest point is returned, giving a peak height.
NMRAnalysis.Analysis1D.run1d — Method
run1d(expt; integration=nothing, call=nothing) -> Vector{RegionResult}Launch the GUI for expt and return the results standing when its window is closed, or - when an integration triple is supplied - skip the GUI and return the analysis for that region directly.
call is the AnalysisCall the entry point recorded, carried through to summary.txt; it is unused on the scripted path, which writes no files. Both paths return the same thing. gui! returns the whole GUI state, of which this is one entry.
NMRAnalysis.Analysis1D.sanitizeregionlabel — Method
Strip commas (region labels are written unescaped into CSV cells) and rename the reserved noise marker (see NOISE_LABEL) to noise_, so a signal region can never be mistaken for it.
NMRAnalysis.Analysis1D.saveanalysis — Method
saveanalysis(expt, dataset, result, regions, folder; call=nothing) -> StringWrite an analysis's output folder, with or without a window having been open: the files saveresults describes, in the folder named. Returns the folder written.
The Save button goes through here, and so does an analysis run without a window - a calibration fitted on behalf of exchange1d, say - so what is saved does not depend on how the analysis was run.
NMRAnalysis.Analysis1D.saveextras! — Method
saveextras!(expt, results, folder)Write any further files an experiment reports, beyond the shared set every analysis saves (summary.txt, results.csv, series.csv, fit.pdf and the per-region plots and data). The default writes nothing; nutation writes its calibration curve. Called by saveresults once the shared files are written. Returns the path written, or nothing where there was nothing to write.
NMRAnalysis.Analysis1D.saveextras! — Method
saveextras!(expt::NutationExperiment, results, folder)Write calibration.pdf, the calibration curve, where several power levels were measured. One power level is a point rather than a curve, and gets no plot. As with B1Calibration, the first region carrying a curve is the calibration; any others are there for comparison.
NMRAnalysis.Analysis1D.saveresults — Method
Save the results, covering every region (not just the active one shown live in the GUI panels), to the output folder, in the layout described in docs/src/advanced/conventions.md: summary.txt to read, results.csv and series.csv to compute with (results.csv is also the file a region list is restored from
- see
readregions!), an overlay of every region infit.pdf, and aregions/folder
holding each region's own plot and the data behind it under the same basename. An experiment with anything further to report adds it through saveextras!.
NMRAnalysis.Analysis1D.scaleyaxis! — Method
Scale the spectrum axis's y-view by factor - factor=2 makes peaks look twice as tall (divides both bounds by 2, i.e. halves the range), factor=0.5 half as tall (doubles the range). Scales ymin/ymax directly rather than re-centring on the current view's midpoint, so it stays anchored to the data's own zero rather than drifting off-centre over repeated presses. The axis's y-interaction is locked (yzoomlock), so this is the controlled replacement for scroll/drag y-zoom - a button/keyboard shortcut rather than the mouse.
NMRAnalysis.Analysis1D.seriescolor — Method
Colour for the i-th result series, cycling through a fixed palette.
NMRAnalysis.Analysis1D.seriesname — Method
seriesname(name, group) -> SymbolThe name a series' fitted parameter takes among its region's parameters: bare when the region has one series, suffixed with the grouping values when it has several, so TRACT's two decay rates become :R_trosy and :R_anti. Parameter names carry no underscore of their own, so baseparam can strip the suffix again.
NMRAnalysis.Analysis1D.seriesnames — Method
seriesnames(expt) -> Union{Nothing,Vector{String}}Fixed group names (in seriescolor order) for the result panel's legend, when the experiment's groups are few and consistently named (e.g. TRACT's TROSY/anti-TROSY pair) - axislegend is used instead of labelling each curve directly. nothing (the default) keeps the inline curve labels, which suit experiments whose group count/names vary per dataset (e.g. kinetics' runs, when several are present).
NMRAnalysis.Analysis1D.seriesresults — Method
seriesresults(e, [dataset, regions]; isfitting=true) -> Vector{RegionResult}Measure and fit every region's series, for every grouping key, without the post-fit stage. This is the pipeline shared by every curve-fit experiment.
The dataset/regions arguments default to the experiment's own, but can be supplied explicitly so the GUI can refit live against interactively-positioned regions and noise. isfitting=false (the GUI's Fitting toggle switched off) substitutes NoFitting for the experiment's own model: the measured quantities still come through for the plotted points, but no curve_fit call runs and the region's parameters come back empty.
NMRAnalysis.Analysis1D.seriestable — Method
seriestable(expt, dataset, results) -> (header, rows)Column names and rows for series.csv: the measurements themselves, long, one row per region per plane.
source and plane are always written, even when constant. They are provenance, so whatever physical variable distinguishes several datasets (TRACT's which, a concentration) gets its own coordinate column as well. plane is load-bearing where the planes share one file: every row of a pseudo-2D experiment has the same source.
NMRAnalysis.Analysis1D.setpost! — Method
setpost!(result, name, value)Record a derived quantity on the region and mark it post-fitted.
NMRAnalysis.Analysis1D.setregionedge! — Method
setregionedge!(state, i, fixed, moving)Move one edge of region i to moving, keeping the opposite edge at fixed - so both the centre and width update together. Used for edge-dragging (as opposed to setregioncentre!, which drags the whole region and keeps its width fixed).
NMRAnalysis.Analysis1D.setregionwidth! — Method
setregionwidth!(state, i, w)Resize region i to width w about its current centre (as opposed to setregionedge!, which changes the centre along with the width). Used by shift+scroll resizing.
NMRAnalysis.Analysis1D.setupkeyboard! — Method
Wire keyboard shortcuts: A to add a region (tap or drag), R to rename, D to delete, Left/Right to step through spectra, Up/Down to scale the spectrum's y-axis, Q to quit, matching the 2D fitting GUI's key bindings.
NMRAnalysis.Analysis1D.setupmouse! — Method
Wire mouse dragging of the region/noise spans, and hover-highlighting of the region under the cursor, on the spectrum axis.
NMRAnalysis.Analysis1D.setwidth — Method
setwidth(region, w) -> RegionThe same region, same label and centre, with width w.
NMRAnalysis.Analysis1D.shapefactor — Method
Gradient shape factor from the Bruker shape name (as in the legacy routine), falling back to 1.0 where the shape is unrecognised or was not recorded at all.
NMRAnalysis.Analysis1D.solventname — Method
The solvent as viscosity names it, or nothing for one it does not know (which leaves the diffusion coefficient reported but not the hydrodynamic radius).
NMRAnalysis.Analysis1D.sources — Method
sources(dataset) -> Vector{String}Where each plane came from, one entry per plane. This is what the source column of series.csv carries.
NMRAnalysis.Analysis1D.speclabel — Method
Where a spectrum came from, for results-file provenance: the full path, since a saved file has to say where its data were on the disk. What is shown on screen is shortened instead, by shortpath, which has a panel's width to live within.
NMRAnalysis.Analysis1D.spectruminfo — Method
spectruminfo(expt, vars) -> StringOne-line description of a single plane, built from its arrayed variables vars (the NamedTuple for that plane, e.g. (; time=0.4, which=:anti)) - shown next to the spectrum slider so the displayed slice is identifiable at a glance (e.g. "0.4 s delay (anti-TROSY)"). The generic fallback lists every variable as key=value; each experiment overrides it with wording natural to its own variables.
NMRAnalysis.Analysis1D.stepslice! — Method
Step the spectrum slider by delta planes (clamped to range), moving its visual thumb via set_close_to! (not just .value, which the slider's thumb doesn't track - see setupkeyboard!). Shared by the ←/→ buttons and the Left/Right key shortcuts.
NMRAnalysis.Analysis1D.summarytext — Method
summarytext(expt, result, activelabel) -> StringHuman-readable summary of the fit for the active region only, shown in the GUI and written to summary.txt (matching the result panel and plot, which are likewise restricted to the active region).
Note
Output-format consistency across the different 1D/2D analyses (units, significant figures, CSV vs text) is an open question — see PLAN.md.
NMRAnalysis.Analysis1D.timescale — Method
timescale(times) -> (factor, unit)Pick a display unit (s / ms / µs) and its multiplying factor for a set of raw times (in s), so values don't show as awkward tiny fractions - e.g. nutation's calibration pulses (tens of µs to ~1 ms) read far more naturally in µs than in s, just as sub-2s relaxation delays read better in ms.
NMRAnalysis.Analysis1D.tracesfromspec — Method
tracesfromspec(spec) -> Vector{Trace}Extract one Trace per plane from an N-dimensional NMRData whose first axis is the chemical shift (F1Dim): a pseudo-2D, or a pseudo-3D such as an off-resonance R1ρ spectrum (shift × spinlock × delay). The non-shift axes are flattened in column-major order into one list of planes.
Intensities are divided by the spectrum's RMS noise level (spec[:noise], computed once by NMRTools on load), so every downstream Trace is in signal-to-noise units. This is distinct from the noise region a user positions, which estimates the uncertainty on an integral (see integrate).
NMRAnalysis.Analysis1D.tract — Method
tract()
tract(trosy, antitrosy; tau=nothing, regions=nothing, integration=nothing,
prompt=isinteractive())Analyse a TRACT pair, deriving τc from the TROSY / anti-TROSY relaxation-rate difference, then open the analysis window. The two spectra are combined into one dataset tagged by which ∈ {:trosy, :anti}, sharing a single integration region.
Called with no arguments, you are asked for the two experiment folders. Relaxation delays are taken from tau if given, else from each spectrum's own vdlist, and otherwise you are asked for them.
Arguments
tau: relaxation delays, in seconds, one per spectrum, used for both experiments.regions: integration regions to start from, instead of the 7.5-9.5 ppm amide window.integration: a(; peakppm, noiseppm, ppmwidth)triple, which skips the window and analyses that region directly.prompt: whether to ask for anything that could not be determined. Defaults tofalseoutside an interactive session, where a missing value raises an error instead.
NMRAnalysis.Analysis1D.tractf — Method
tractf(; B0, θ=17π/180) -> Float64Dipole/CSA cross-correlation prefactor used in the TRACT τc relation, given the static field B0 (T). Constants follow the standard ¹⁵N–¹H amide treatment.
NMRAnalysis.Analysis1D.tracttauc — Method
tracttauc(f, ωN, ηxy) -> Float64Rotational correlation time τc (ns) from the cross-correlated cross-relaxation rate ηxy, by the analytic inversion of
ηxy = f · [4·J(0) + 3·J(ωN)], J(ω) = (2/5)·τc / (1 + ω²τc²)i.e. ηxy = f·(8/5·τc + 6/5·τc/(1+(ωN·τc)²)), as in the routine this replaces.
The (2/5) spectral-density convention is the easy thing to lose here: an earlier version of this docstring quoted the relation as 4/5·τc + 3/5·τc/(1+(ωN·τc)²), a factor of two out from what the inversion below actually solves (the code was right, the docstring was not). test/analysis1d_test.jl now round-trips this against the forward relation above, so the two cannot drift apart again silently.
NMRAnalysis.Analysis1D.valueerr — Method
Value and uncertainty cells for a parameter that may carry neither.
NMRAnalysis.Analysis1D.visualisationtype — Method
visualisationtype(expt) -> ResultVisualisationThe strategy drawing expt's results. Defaults to SeriesVisualisation, which suits every curve-fit experiment; override it in an expt-*.jl only where that shape genuinely will not do.
NMRAnalysis.Analysis1D.windowtitle — Method
analysis-type name shown in the GUI's bold in-panel title, e.g. "NMRAnalysis: Relaxation"
NMRAnalysis.Analysis1D.writeresults! — Method
writeresults!(expt, dataset, results, regions, folder) -> StringWrite the whole result set into folder: regionlist.csv (what was picked), series.csv, results.csv where anything is reported per region, and one regions/<label>.csv per region holding that region's own rows of series.csv. Returns the path of the series file.
NMRAnalysis.Analysis1D.writesummary — Function
writesummary(filepath, expt, dataset, results, regions, call=nothing)Write summary.txt: the human-readable record of the analysis, and the one output where numbers are rounded for reading rather than written at full precision.
NMRAnalysis.callstring — Method
callstring(call, regions, noisecentre) -> String or nothingThe Reproduce: line for summary.txt: the recorded call with the region actually used appended as an integration triple, so pasting it back repeats the analysis without the window opening.
Only a single-region analysis can be repeated in one call, the integration triple carrying one region and one noise position. With several regions the call is still printed, without them, and writesummary adds a line pointing at the Load button, which restores every region and the noise position from results.csv.