MATLAB Toolbox to access and modify deeply nested data using path-based syntax with wildcard support
  • MATLAB 99.9%
  • PowerShell 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-19 09:46:46 -04:00
assets Integrate MPath logo assets 2026-09-04 20:29:29 -04:00
dev Plan project links for installed documentation 2026-09-19 09:46:46 -04:00
doc Separate API and topic links in documentation 2026-09-18 02:47:03 -04:00
src Use compact signatures in public source help 2026-09-19 03:25:29 -04:00
tests Test get type-inference error translation 2026-09-17 03:46:54 -04:00
.gitignore Define MPath release version conventions 2026-08-30 18:34:25 -04:00
AGENTS.md Standardize reference-page presentation 2026-09-16 09:35:58 -04:00
CHANGELOG.md Document MPath 1.0 capabilities in the changelog 2026-09-18 11:47:16 -04:00
CONTRIBUTING.md Prepare MPath 1.0.0 for RC1 2026-09-19 01:44:57 -04:00
LICENSE Initial commit 2025-06-23 03:20:02 +02:00
README.md Prepare MPath 1.0.0 for RC1 2026-09-19 01:44:57 -04:00
setup.m Build reproducible MPath toolbox installers 2026-08-30 20:02:00 -04:00
VERSION Prepare MPath 1.0.0 for RC1 2026-09-19 01:44:57 -04:00

MPath logo

MPath

Version: 1.0.0

A MATLAB package for accessing deeply nested data using path-based syntax.

MPath lets you refer to members at arbitrary depth with delimited string paths, including wildcards for matching multiple members at once. This makes it easier to work with nested structs and other hierarchical data without extra data wrangling code.

You can reduce or eliminate:

  • nested loops
  • temporary variables
  • hardcoded sibling member names
  • anonymous functions
  • lengthy boilerplate code

MPath provides five ways to access data:

Access function Description
mpath.get Get values from paths.
mpath.set Set values at paths.
mpath.exists Check whether paths exist.
mpath.remove Remove members at paths.
mpath.resolve Show which locations a path selects.

Examples

The examples below show the advantages of MPath interface over traditional MATLAB approaches.

Nested structs

Consider experimental data collected with multiple subjects and trials stored hierarchically:

data: 1×1 struct with fields:
└─╴Subject1, Subject2, Subject3: 1×1 struct with fields:
   ├─╴Mass, Height: 1×1 double
   ├─╴Survey: 1×2 table with variables:
   │  └─╴Response A, Response B: 1×1 double
   └─╴Trial1, Trial2, Trial3, Trial4: 1×1 struct with fields:
      ├─╴StartTime: 1×1 datetime
      └─╴TimeSeries: 1×151 double

Let's say you are interested in calculating the average subject mass given the data structure above. Without MPath, there are a few options:

% Direct access to the fields requires knowing the number of subjects in advance
mean_mass = mean( [data.Subject1.Mass, data.Subject2.Mass, data.Subject3.Mass] )

% Works with any number of subjects but requires temporary variables and a loop
masses = [];
for subject = string(fieldnames(data)).'
    masses = [masses; data.(subject).Mass];
end
mean_mass = mean(masses)

% One-liner that avoids the loop and temporary variables but requires an anonymous function
mean_mass = mean( arrayfun( @(subject) data.(subject).Mass, string(fieldnames(data)) ) )

With MPath, the code you write doesn't require knowing the number of subjects in advance while also eliminating the need for temporary variables, loops, and anonymous functions:

% MPath approach - single line without temporary variables, loops, or anonymous functions
mean_mass = mean( mpath.get(data, "/*/Mass") )

Struct arrays

Now consider struct arrays. In this example, each of three subjects has their lower-limb body segments measured twice and recorded.

Subjects: 1×3 struct with fields:
├─╴LegLengths: 1×2 double
└─╴SegmentLengths: 1×2 struct with fields:
   └─╴Shank, Thigh: 1×1 double

Let's say you want to create a bar chart by running bar(thighLength) where thighLength is a 3×2 matrix containing both measurements of each subject's thigh length. Without MPath, there are a few options to form thighLength:

% Explicitly specifying each entry requires knowing the number of subjects and measurements in advance
thighLength = [
    Subjects(1).SegmentLengths(1).Thigh, Subjects(1).SegmentLengths(2).Thigh;
    Subjects(2).SegmentLengths(1).Thigh, Subjects(2).SegmentLengths(2).Thigh;
    Subjects(3).SegmentLengths(1).Thigh, Subjects(3).SegmentLengths(2).Thigh]

% Number of measurements no longer needs to be known in advance, but the number of subjects still does
thighLength = [
    Subjects(1).SegmentLengths.Thigh;
    Subjects(2).SegmentLengths.Thigh;
    Subjects(3).SegmentLengths.Thigh]

% Works with any number of subjects and measurements but requires nested loops and multiple lines
thighLength = nan(numel(Subjects), numel(Subjects(1).SegmentLengths));
for i = 1 : numel(Subjects)
    for j = 1 : numel(Subjects(i).SegmentLengths)
        thighLength(i, j) = Subjects(i).SegmentLengths(j).Thigh;
    end
end
thighLength

% Works with any number of subjects and measurements but requires a temporary variable and reshape
SSL = [Subjects.SegmentLengths];
thighLength = reshape([SSL.Thigh], 2, 3).'

% Single statement that works with any number of subjects and measurements but requires an anonymous function
thighLength = cell2mat(arrayfun(@(subject) [subject.SegmentLengths.Thigh], Subjects.', UniformOutput=false))

With MPath, the code you write doesn't require knowing the number of subjects and measurements beforehand while also not needing temporary variables, loops, and anonymous functions:

% MPath approach - single line without temporary variables, loops, anonymous functions
thighLength = mpath.get(Subjects, "/SegmentLengths/Thigh")

Features

Using the same experimental data structure above, here are some of the key features:

Simple member access

Simple paths behave like dot notation for accessing members.

% Access individual struct fields through slash-delimited string
desc = mpath.get(data, "/Description");                  % Returns 1×18 char
mass = mpath.get(data, "/Subject1/Mass");                % Returns 1×1 double
date = mpath.get(data, "/Subject2/Trial1/StartTime");    % Returns 1×1 datetime

% You can also access table columns; variable names can be quoted to allow special characters
surv = mpath.get(data, '/Subject3/Survey/"Response A"')  % Returns 1×1 double

Wildcard matching

Wildcards allow matching multiple members simultaneously using glob-like syntax. The wildcard * matches zero or more characters, and the wildcard ? matches exactly one character.

% Get the mass of all subjects - * matches {Subject1, Subject2, Subject3}
mass = mpath.get(data, "/*/Mass");                        % Returns 3×1 double

% Get trial data for the first subject - Trial? matches {Trial1, Trial2, Trial3, Trial4}
data = mpath.get(data, "/Subject1/Trial?/TimeSeries");   % Returns 4×151 double

% Wildcards in multiple segments automatically sizes the result
time = mpath.get(data, "/*/Trial?/StartTime");            % Returns 3×4 datetime

List operations

You can select multiple members directly using list notation.

% Get anthropometrics from first subject
anthro = mpath.get(data, "/{Subject1, Subject2, Subject3}/Mass");  % Returns 3×1

% Get start times for all trials across all subjects
times = mpath.get(data, "/{Subject1, Subject2, Subject3}/{Trial1, Trial2, Trial3, Trial4}/StartTime");  % Returns 3×4

Dimension control

You can control the resulting shape when segments match multiple members by appending # followed by a dimension.

% Transpose of the earlier example, `/*/Trial?/StartTime`
time = mpath.get(data, "/*#2/Trial?#1/StartTime");          % Returns 4×3 datetime

% Helpful when the data being fetched is not a scalar
signal = mpath.get(data, "/*/Trial*#3/TimeSeries");         % Returns 3×151×4 array

% Flatten all subjects and trials into single dimension
signal = mpath.get(data, "/*#1/Trial*#1/TimeSeries");       % Returns 12×151 array

Setting values

The same notation can be used to set values.

% Reassign the mass of the third subject
data = mpath.set(data, "/Subject3/Mass", 71.3);

Installation

MPath supports MATLAB R2025a and later on Windows, Linux, macOS, and MATLAB Online. MPath 1.0 has been tested with MATLAB R2025a on Windows 11.

Downloads for published versions are available from the MPath releases page. Choose one of the three ways to install the MPath toolbox:

1. Install as a MATLAB add-on (recommended)

Download mpath-<version>.mltbx, open it in MATLAB, and approve the installation prompt. MATLAB installs the MPath toolbox as an add-on and keeps it available across sessions.

2. Install from the ZIP file

Download and extract mpath-<version>.zip. In MATLAB, navigate to the extracted MPath folder and run:

cd path/to/mpath-<version>
setup()

setup() adds MPath for the current MATLAB session and rebuilds its local documentation index. To keep MPath available in future sessions, run setup --savepath user-startup. Run setup --help for other setup options.

3. Install by cloning the stable source

Clone the stable release channel:

git clone --branch stable https://git.usercurt.com/UserCurt/mpath.git

In MATLAB, navigate to the cloned repository and run:

cd path/to/mpath
setup()

setup() adds MPath for the current MATLAB session and rebuilds its local documentation index. To keep MPath available in future sessions, run setup --savepath user-startup. Run setup --help for other setup options.

Documentation

For comprehensive documentation, including examples and detailed syntax information, run doc in MATLAB and then navigate to Supplemental Software and click on MPath Toolbox.

Development

For upcoming features and releases, see the development roadmap. If you are interested in contributing to the project, please see the contributor guide.

Disclaimers

This project is an independent work and is not affiliated with, endorsed by, or in any way officially connected with MathWorks or MATLAB. MATLAB is a registered trademark of The MathWorks, Inc.

The source code in this repository is licensed under the Mozilla Public License Version 2.0.