Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1. Generating Unphased Data

While automated phasing algorithms (like ACME) are incredibly powerful, heavily distorted baselines, massive solvent peaks, or extreme noise can sometimes trick the optimizer. In these cases, falling back to manual phase correction is necessary.

As discussed in the Phase Correction Pipeline documentation, applying a phase correction mathematically is straightforward. However, guessing the exact p0p_0 and p1p_1 angles blindly is nearly impossible.

To solve this, xmris provides an interactive, browser-based AnyWidget that allows you to click and drag to fix the phase in real-time, and then generates the exact Python code needed to reproduce your manual adjustments.

import matplotlib.pyplot as plt
import numpy as np
import xarray as xr

import xmris

1. Generating Unphased Data

Let’s generate the same ruined synthetic spectrum we used in the pipeline documentation.

Source
# Generate synthetic FID
dwell_time = 0.001
n_points = 1024
t = np.arange(n_points) * dwell_time

rng = np.random.default_rng(42)
clean_fid = np.exp(-t / 0.05) * (
    np.exp(1j * 2 * np.pi * 50 * t) + 0.6 * np.exp(1j * 2 * np.pi * -150 * t)
)
noise = rng.normal(scale=0.08, size=n_points) + 1j * rng.normal(scale=0.08, size=n_points)

da_fid = xr.DataArray(
    clean_fid + noise, dims=["time"], coords={"time": t}
)
da_spec = da_fid.xmr.to_spectrum()

# Intentionally ruin the phase
da_ruined = da_spec.xmr.phase(p0=120.0, p1=-45.0)

2. Launching the Widget

You can launch the interactive viewer directly from the xmris package. Pass your complex-valued 1D frequency-domain DataArray to the phase_spectrum function.

The widget will automatically detect your spectral dimension (e.g., frequency, ppm), set up the coordinates, and calculate the optimal pivot point based on the maximum signal magnitude.

# Launch the interactive widget
da_ruined.xmr.widget.phase_spectrum()
Loading...

Using the Widget

Once the widget is rendered in your notebook, you can interact with it using the following controls:

3. Extracting the Parameters

Interactive widgets are great for exploration, but they are generally bad for reproducible science if the parameters stay trapped in the UI.

When you have achieved the desired phase, click the Close button in the widget control bar. The canvas will unmount, and the widget will generate a strict, reproducible code snippet reflecting your final parameters.

(Screenshot only)

Screenshot of the widget (part 2)

Click the Copy Code button, and paste it into the next cell in your notebook:

# This code is pasted directly from the widget's completion screen!
phased_da = da_ruined.xmr.phase(p0=-120.00, p1=45.00, pivot=50.000)

# Verify the correction
fig, ax = plt.subplots(figsize=(8, 3))
phased_da.real.plot(ax=ax, color="tab:blue")
plt.title("Spectrum Phased via Widget Parameters")
plt.show()
<Figure size 1200x450 with 1 Axes>

Because the pivot value is explicitly hardcoded into the generated snippet, your manual p1p_1 adjustment is guaranteed to produce the exact same mathematical output even if the array is later cropped, padded, or resampled!