API Reference

MR data types

MagneticResonanceSignals.MRExperimentType
load_twix(twix_file_name)
load_twix(io)

MRExperiment(metadata, coils, quality_control, acq_data)

Container for data from a generic magnetic resonance experiment: a series of Acquisitions, each of which records the coil response due to induced nuclear magnetization. This is currently specialized for the type of raw data produced by a Siemens scanner but could be generalized.

Note that the input pulse sequence is not recorded in Siemens raw format, so it's not available here. The only way to know this in full detail is to simulate the sequence with the same input parameters using the Siemens poet tool from the Siemens proprietary IDEA development environment.

source
MagneticResonanceSignals.PRESSType

A standard Point Resolved Spectroscopy (PRESS) experiment with num_averages acquisitions, possibly with navigator and reference scans included.

This is implemented as "single voxel spectroscopy" and is the standard product sequence for in vivo MR spectroscopy on Siemens scanners as of early 2020.

source
MagneticResonanceSignals.LCOSYType

An L-COSY experiment with (num_averages × nsamp_t1) acquisitions, possibly with reference scans included.

The L-COSY pulse sequence is described in:

  • Thomas, M. Albert, et al. "Localized two‐dimensional shift correlated MR spectroscopy of human brain." Magnetic Resonance in Medicine 46.1 (2001): 58-67.
  • Thomas, M. Albert, et al. "Evaluation of two‐dimensional L‐COSY and JPRESS using a 3 T MRI scanner: from phantoms to human brain in vivo." NMR in Biomedicine 16.5 (2003): 245-251.
source

Querying MR data

MagneticResonanceSignals.sampledataFunction
sampledata(expt, index; downsample=1)

Return the acquired data from expt at a given acqusition index. If downsample>1, the data will be subsampled by the given rate by truncating the tails of the signal in the Fourier spectral domain. This has the effect of removing noise by filtering away irrelevant high and low frequency components.

source

High level file IO and conversion

MagneticResonanceSignals.mr_loadFunction
mr_load(data)

High level function for loading MR data and recognizing which experiment was run. The returned object describes the experimental conditions and acquisition schedule which can be used during data processing. data may be a file name, IO stream, or a data structure describing raw acquisition data, for example, Siemens Twix.

If the experiment is not recognized, throw an exception.

source
mr_load(twix::MRExperiment, repair=false)

If repair=true, attempt to repair the experiment by discarding a subset of broken acquisitions where possible.

Recognizes spectro experiments in Siemens twix format, producing one of:

  • PRESS (Siemens product sequence SVS_SE)
  • L-COSY (Customer sequences srcosy, svs_lcosy)
source

Low level file IO

MagneticResonanceSignals.load_rdaFunction
load_rda(rda_file)

Load header dictionary and spectroscopy data from a Siemens .rda file. Returns header,data, where header is a simple dictionary containing the ASCII header, and data is the time domain induced magnetization signal.

Single voxel spectroscopy data will be loaded as a vector containing the single magnentization signal.

For spectroscopy with a spatial component (that is, CSI data with at least one header field CSIMatrixSize[i] not equal to 1), an array of size N×I×K×J will be returned where I,J,K are the CSI indices 0,1,2 and the FID length is N.

source
MagneticResonanceSignals.load_twixFunction
load_twix(filename; header_only=false, acquisition_filter=(acq)->true,
          meas_selector=last)

Load raw Siemens twix ".dat" format, producing an MRExperiment containing a sequence of acqisitions.

For large files, acquisitions may be filtered out during file loading by providing a predicate acquisition_filter(acq) which returns true when acq should be kept. By default, all acquisitions are retained.

N4 VD-version twix may have data from more than one sequence (for example, the tune-up data may be included). Normally the data you're looking for is in the meas_selector=last chunk, but meas_selector is provided for the cases where you want to select other measurements.

source
MagneticResonanceSignals.save_felixFunction
save_felix(fname, data; bandwidth, frequency)

Create Felix NMR file for 2D NMR experiment with 2D data matrix size npoints = size(data), spectral width bandwidth = (t2_bw, t1_bw) and given spectrometer frequency, which should be unit-compatible with Hz.

data[i,:] is assumed to contain the real time FIDs as acquired in the standard 2D COSY experiment (ie, the "t2" dimension).

source
MagneticResonanceSignals.save_nmrpipeFunction
save_nmrpipe(io, signal, axes; frequency, ref_freq_offset)

Convert twix into NMR Pipe format to be loaded into third party analytical software, such as MNova. This currently supports up to 2 dimension.

At minimal, for each dimension we should have:

  • Signal data
  • Axes
  • Observation frequency (frequency)
  • Carrier frequency (ref_freq_offset)

ref_freq_offset is a tuple containing the relative frequency offset between obs_freq and frequency which will be set to 0 on the ppm scale.

source

High level signal processing

MagneticResonanceSignals.simple_averagingFunction
simple_averaging(spectro_expt)

Simple channel combination and averaging for spectroscopic data acquisition.

Note that this uses a simple mean to combine acquisitions across the phase cycling dimension; it does no frequency alignment or other calibration.

source
simple_averaging(fids)

Do simple averaging from FIDs

source
MagneticResonanceSignals.spectrumFunction
spectrum(lcosy::LCOSY,
         win1=t->sinebell(t, pow=2),
         win2=t->sinebell(t, skew=0.3, pow=2),
         t1pad=4)

Compute spectrum from lcosy data with "standard" L-COSY processing parameters as have traditionally been used by Mountford et. al.

  • Simple averaging
  • T2: skewed sine bell squared window, skew=0.3
  • T1: Sine bell squared window, 4x zero padded
source
spectrum(signal::AxisArray)

Compute the spectrum from time domain signal via Fourier Transform.

source

Low level signal processing

Channel combination

MagneticResonanceSignals.pca_channel_combinerFunction
pca_channel_combiner(signals; signal_range=nothing, channels=:)

Compute channel combination object using PCA, assuming that each acquisition in signals has the same relative geometry of sample and coils. signals[i] is assumed to be an array of shape num_samp × num_chan. We use the first few samples of all acquisition data together in the same calculation to get a good estimate of the correct channel weights.

These assumptions should be valid to assess the relative coil SNR for spectroscopy of a single voxel; for other experiments you may want to use a different method, or restrict calculation of weights to a different signal_range.

channels can be set to a index-like object in order to combine only a subset of channels.

source
MagneticResonanceSignals.combine_channelsFunction
combine_channels(combiner::ChannelCombiner, data)

Combine channels data residing in a NxC matrix data, where N is number of temporal samples and C the number of channels. Alternatively, data can be an acquisition.

See pca_channel_combiner() to create a ChannelCombiner functor.

source

Windows and windowing

MagneticResonanceSignals.apply_windowFunction
apply_window(signal, axis1=>win1, axis2=>win2, ...)

Apply window functions win1 along axis1, win2 along axis2, etc. The windows should be functions over the dimensionless time domain 0..1; the axes should be of type AxisArrays.Axis.

Background

For the purposes of spectroscopy, the MR signal is generally an oscillating decaying signal in the time domain, with different metabolites having different decay constants. When computing a spectrum with a simple Fourier transform, one may window the time domain data to emphasize one metabolite or another in the resulting spectrum. (Spatially resolved spectroscopy involves some kind of MR echo so the initial part of the signal may be increasing, but the this doesn't affect the irreversible decay mechanisms.)

For qualitative exploration of the spectra, one may therefore want to choose out of several windowing functions with convenient parametric forms. Note that for quantitative measurement of metabolite concentration, windowing distorts the relative peak volumes and it's probably better to choose a time domain fitting method.

Note that these MR-specific reasons are subtly different - and apply in addition to - the generic signal processing reasons for time domain windowing.

source
MagneticResonanceSignals.sinebellFunction
sinebell(t; skew=1, pow=1)

The sinebell window on the dimensionless time range t ∈ 0..1.

Use pow=2 for sinebell squared. Setting the skew parameter to something other than the default of 1.0 gives a skewed sinebell window, as in Felix NMR.

source

Plotting