Skip to content

Repository files navigation

AaltoView

DOI

A data viewer for time-resolved MOKE and FMR measurements (Aalto University, NanoSpin group), the Python successor of the LabVIEW AaltoView, whose name it carries again (it was trmoke-dataviewer until 2026-09-24). Open a scan of any number of dimensions, look at it as a map or as overlaid curves, average what you do not need, take a background out (÷ or − a reference line), and send the result to a figure, a text file, Origin or a Jupyter notebook, or into an analysis module. VNA-FMR fit fits the Kittel mode and standing spin waves in field or VNA frequency sweeps, then fits the dispersion for γ, M_eff, anisotropy, the exchange stiffness and damping. Spin-wave FFT transforms every line of a position × frequency map into k-space, finds the wavevectors and fits a stripe's dispersion (Kalinikos–Slavin, Guslienko pinning). It reads the .nc files the AaltoFlow scan engine writes and needs no instruments.

a 3-D FMR cube: field against frequency at 2 um from the antenna

A three-dimensional measurement (distance from the antenna × field × RF frequency) shown as field against frequency, with the distance held at 2 µm: the Kittel mode and a weaker standing spin wave. The cursor sits on the resonance; Row → 1D sent the spectrum through it to the 1D plots. All screenshots use simulated data (see Try it without lab data).

  • Files — a data folder (day sub-folders included), newest first, with each measurement's axes, shape and detectors, and the selected file's header.
  • Map — any two dimensions as X/Y. Every other dimension gets a row: hold it at one value (a slider showing the coordinate) or average it (all of it, or a range). Colour map, inverse, symmetric limits, automatic (percentile) or typed limits — or drag the colour bar — log, and normalise each row or column. Drawing: with more points than screen pixels, each pixel shows a block's average (smooth), max (keeps a one-point peak, e.g. a tone in a long spectrum) or min (keeps a dip); zoomed in, every point is drawn as it is. Reference: divide by (or subtract) one line, e.g. a VNA field sweep ÷ the highest field, where the resonance is out of the band; ÷ the median line when no reference was measured; or derivative-divide along X or Y. It is applied to the complex values, so |z| and arg z are of the ratio. Click to place a cursor; Row → 1D / Column → 1D send the line through it, as shown (referenced too).
  • 1D plots — a grey preview of the current selection. Add current, or pick a dimension, select several of its values and Add selected (one curve per value). Curves are frozen copies that remember their file, so curves from different measurements overlay. Normalise (peak, 0…1, first point, zero mean), stack as a waterfall, log Y, rename, hide, remove. Reference along the "one per value of" dimension, as on the map: ÷ (or −) the curve at one value (the highest field), ÷ the median curve, or derivative-divide -- for the preview and the curves added. The view fits the visible curves.
  • Export, from both tabs:
    Save image publication-style PNG / PDF / SVG (white background)
    Copy image / Copy data to the clipboard (data tab-separated)
    Save data .dat / .csv with Long Name / Units / Comments header rows; a map as a matrix or XYZ columns
    Send to Origin into a running Origin (or starts one): worksheet + graph, or matrix + colour map
    Notebook a Jupyter notebook that recomputes the view from the .nc files
    Analysis the curves (1D plots) or the whole map (Map) into an analysis module: see below

spectra from two measurements overlaid

1D plots: the spectrum at 100 mT for every distance, added in one go with "one per value of distance", plus the same spectrum from a separate measurement on a different frequency grid. Each curve remembers the file it came from.

spin waves leaving the antenna

A complex lock-in signal shown as its real part, red-blue with symmetric limits: spin waves travelling away from the antenna at 8 GHz. The field is one of three, held on its slider; |z|, arg z, Re z and Im z are one click apart, and averages of a complex signal are taken coherently.

normalised, stacked field sweeps map with every line normalised
Field sweeps at 6–12 GHz, each normalised to its peak and stacked. The same kind of map with every frequency line scaled to its own peak, so the resonance can be followed where the signal is weak. Light theme.
VNA map divided by its reference the same, light theme
S21

Loading scripts

Some files need a correction before anything looks at them. A loading script does it as the file is read: choose one in load with (Files panel, above the file list) and every file you open goes through it. The map, the 1D plots, every export, the notebook (it loads through the same script) and the analysis modules all see the corrected data. The status line says which script was used. Reload (next to the list) reads the open file again through the chosen script, which also picks up a script you have just edited. A script that fails shows nothing, never the previous picture or an uncorrected file.

Scripts are .py files in LoadingScripts/: drop one in and it is listed. The folder's README has the three-line contract. Two come with AaltoView: TR-MOKE unfold (80 MHz laser) and (100 MHz laser). They undo the laser's aliasing, which conjugates the complex lock-in signal on half of the frequencies (a spatial FFT then shows a dashed V instead of one branch).

Analysis modules

Fits and other analyses are separate programs that the viewer sends curves to (1D plots → Analysis) or whole maps (Map → Analysis: the map on screen, reference applied, complex values kept). Several can be open at once, and a busy or crashed module never takes the viewer down. A module is a folder in AnalysisModules/: drop one in and the viewer lists it. Its packages are installed the first time it starts.

  • VNA-FMR fit (AnalysisModules/vna-fmr-fit): complex Lorentzian for VNA data. It gives the resonance position, the linewidth (HWHM and FWHM, with 1σ errors), the amplitude and the mixing phase. It fits Re and Im together, has a fit range, several peaks, and fixed or bounded parameters, and exports its results as a table with one row per curve (.csv, clipboard, Origin). Its Dispersion tab then fits all the resonances with one magnetic model: γ, M_eff, in-plane uniaxial, 4- and 6-fold anisotropy, PSSW exchange (A) and damping (α, ΔH0). It handles field sweeps at any angle, frequency sweeps, and angle series. A map sent to it arrives as one sweep per row.
  • Spin-wave FFT (AnalysisModules/spinwave-fft):
    • the spatial FFT of every line of a map (e.g. lock-in vs pos_x × rf_freq), coherent on complex data, so waves travelling towards +x and −x are separated;
    • a choice of window, offset removal and zero-padding, with k in rad/µm or 1/µm;
    • the peaks of every line, exported as a table;
    • the dispersion fit, Kalinikos–Slavin for a stripe with Guslienko's effective width: μ0Ms, A, thickness, width, field and angle, each fitted or held.

Spin-wave FFT: every frequency line in k-space, peaks and the fitted dispersion

The simulated permalloy stripe, sent from the Map tab. The peaks lie on the stripe's dispersion, and the fit gives back μ0Ms and the width; the tests check that against the numbers the data was made from.

VNA-FMR fit: four field sweeps fitted

The simulated field sweeps at 6–12 GHz, sent from 1D plots and fitted with Fit all. The resonance fields and widths agree with the Kittel formula the data was made from; the tests check that.

Case study: FMR with standing spin waves, background removed, three fits → all. It works through 200 nm YIG measured with a VNA:

  • divide by a reference line to remove the cables;
  • fit the uniform mode + PSSW 1–4 on three sweeps by hand;
  • let the dispersion predict, bound and fit the other nine;
  • end with one exchange stiffness.

It is reproduced by tools/case_study_fmr_pssw.py, and every number is checked against the truth the data was made from.

Writing a new module: docs/ANALYSIS_MODULES.md (tools/new_analysis_module.py sets one up).

Install and run

git clone https://github.com/FlashLukas/AaltoView.git
cd aaltoview
uv sync --extra gui                  # add --extra origin for "Send to Origin"
uv run aaltoview             # or: uv run aaltoview path\to\scan.nc --folder D:\data

uv brings its own Python (3.11 or newer). Analysis modules install their own packages the first time they start (uv sync --all-packages --extra gui does all of them at once). The origin extra installs OriginLab's originpro package and works on Windows with Origin 2021 or newer installed; without it, every other export still works.

It starts in the folder you used last time (or the AaltoFlow suite's data directory, if the suite is installed on the same PC).

Try it without lab data

uv run python tools/make_demo_data.py demo_data     # ten simulated measurements
uv run aaltoview --folder demo_data

The simulated measurements are a permalloy-like film: the Kittel mode f = γ/2π·√(B(B + μ0Ms)), a weaker perpendicular standing spin wave, a linewidth growing with frequency, detection phase and noise. They are a field × frequency map, a distance × field × frequency cube, a spin-wave image at 8 GHz for three fields, and field sweeps at four frequencies. Further files cover the analysis modules:

  • an anisotropic film measured at 36 in-plane angles;
  • VNA sweeps with a cable background;
  • 200 nm YIG with four standing spin waves, both as field sweeps and as VNA sweeps;
  • a spin-wave line scan along a permalloy stripe.

tools/render_docs.py regenerates them and every screenshot above.

Without the window

Everything except the window is plain Python and can be used in a script or a notebook:

from aaltoview.data import load
from aaltoview.view import Slice
from aaltoview import export as E

ds = load("demo_data/2026-09-15/101530_fmr_distance_cube.nc").load()

# a map: field x frequency, 2 um from the antenna (distance index 1)
sel = E.Selection("lockin", x="field", y="rf_freq", slices={"distance": Slice("at", 1)})
m, _ = E.make_map(ds, sel, E.MapStyle(cmap="magma"))
E.save_figure(E.figure_map(m), "map.png")

# one spectrum per distance at 100 mT (field index 40), peak-normalised, to a file
curves = E.curves_along(ds, E.Selection("lockin", x="rf_freq",
                                        slices={"field": Slice("at", 40)}),
                        "distance", range(4))
E.write_curves("curves.dat", curves, norm="peak")

The files it reads

netCDF-4 (HDF5), one variable per detector, named coordinates with a units attribute, and these conventions from the AaltoFlow scan engine:

  • a complex detector is stored as <name>_real + <name>_imag (attributes complex_pair / complex_part), because a native complex netCDF variable is not readable by MATLAB or Igor; the viewer recombines it and averages it coherently (the complex mean first, then |z| or arg z);
  • dataset attributes name, comment, dims (outer → inner), n_points, seconds, recipe_json;
  • autosaves are named <YYYY-MM-DD>/<HHMMSS>_<name>.nc, which is where the "measured" time in the file list comes from.

Not yet

AaltoView's TR-MOKE corrections: laser repetition rate (80 / 100 MHz), harmonic, folding of the demodulation frequency, the amplitude correction file, and phase autocorrection.

Tests

uv run pytest -q                              # viewer + modules, offline, GUI offscreen
uv run python tools/render_docs.py            # refresh the screenshots in docs/
uv run --all-packages python tools/case_study_fmr_pssw.py   # and the case study's
$env:AALTOVIEW_TEST_ORIGIN = "1"; uv run pytest -q -k origin    # also pushes into Origin

How to cite

If you publish scientific work with data analysed or plotted using AaltoView, we would be grateful for a citation. CITATION.cff has the details (GitHub's "Cite this repository" button gives it as BibTeX or APA); in short:

L. Flajšman, AaltoView: a viewer for N-dimensional measurement data, NanoSpin group, Aalto University, https://github.com/FlashLukas/AaltoView, doi:10.5281/zenodo.22959226

DOI: 10.5281/zenodo.22959226 (always the latest version; Zenodo lists the DOI of each release too).

Credits and licence

AaltoView was developed by Lukáš Flajšman in the NanoSpin group, Aalto University, as the data viewer of AaltoFlow. The copyright is held by Aalto University.

MIT -- see LICENSE.

About

AaltoView: viewer for N-dimensional measurement data (netCDF) -- the data viewer of AaltoFlow. NanoSpin group, Aalto University.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages