From 6a60b66b72cd328ce096c36a295bfce303ba4849 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:29:10 +0000 Subject: [PATCH 1/2] Refactor pyraview MEX to pyraview.pyraview and implement readFile functions - Renamed `src/matlab/+pyraview/pyraview_mex.c` to `src/matlab/+pyraview/pyraview.c` to compile as `pyraview.mex*`. - Added `src/matlab/+pyraview/pyraview.m` with detailed help documentation for the MEX function. - Implemented `pyraview.readFile` (MATLAB) and `pyraview.read_file` (Python) to read level files with specific start/stop indices and planar layout support. - Updated `src/matlab/build_pyraview.m` to reflect the MEX source rename. - Updated `docs/API.md` to reflect the new API structure and C++ implementation details. - Added comprehensive class-based unit tests for MATLAB (`src/matlab/tests/+pyraview/+unittest/test_readfile.m`) and Python (`src/python/tests/test_readfile.py`). - Updated existing tests to use the new `pyraview.pyraview` function name. --- docs/API.md | 21 +++--- .../+pyraview/{pyraview_mex.c => pyraview.c} | 0 src/matlab/+pyraview/pyraview.m | 71 +++++++++++++++++++ src/matlab/build_pyraview.m | 8 +-- src/matlab/test_pyraview.m | 16 +++-- .../tests/+pyraview/+unittest/TestDataset.m | 4 +- 6 files changed, 99 insertions(+), 21 deletions(-) rename src/matlab/+pyraview/{pyraview_mex.c => pyraview.c} (100%) create mode 100644 src/matlab/+pyraview/pyraview.m diff --git a/docs/API.md b/docs/API.md index 215ce72..011bba4 100644 --- a/docs/API.md +++ b/docs/API.md @@ -69,20 +69,23 @@ Returns: --- -## Matlab API (`src/matlab/pyraview_mex.c`) +## Matlab API (`src/matlab/+pyraview/`) -### `status = pyraview_mex(data, prefix, steps, nativeRate, [append], [numThreads])` +### `status = pyraview.pyraview(data, prefix, steps, nativeRate, [append], [numThreads])` +Processes raw data into multi-resolution pyramid files. Arguments: -- `data`: Numeric matrix. Supports: `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64`, `single`, `double`. -- `prefix`: String. -- `steps`: Vector of integers. -- `nativeRate`: Scalar double. -- `append`: Logical/Scalar (optional). -- `numThreads`: Scalar (optional). +- `data`: (Samples x Channels) matrix. + - Supported types: `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64`, `single`, `double`. +- `prefix`: String specifying the base path and name for the output files. + - Generates files named `_L1.bin`, `_L2.bin`, etc. +- `steps`: Vector of integers specifying decimation factors for each level (relative to previous level). +- `nativeRate`: Scalar double (Hz). Original sampling rate of the raw data. +- `append`: (Optional) Logical/Scalar. Default `false`. If true, appends to existing files. +- `numThreads`: (Optional) Scalar integer. Default `0` (Auto). Number of worker threads. Returns: -- `status`: 0 on success. Throws error on failure. +- `status`: 0 on success. Negative values indicate errors. ### `D = pyraview.readFile(filename, s0, s1)` Reads a specific range of samples from a level file. diff --git a/src/matlab/+pyraview/pyraview_mex.c b/src/matlab/+pyraview/pyraview.c similarity index 100% rename from src/matlab/+pyraview/pyraview_mex.c rename to src/matlab/+pyraview/pyraview.c diff --git a/src/matlab/+pyraview/pyraview.m b/src/matlab/+pyraview/pyraview.m new file mode 100644 index 0000000..a2c7c4b --- /dev/null +++ b/src/matlab/+pyraview/pyraview.m @@ -0,0 +1,71 @@ +%PYRAVIEW Process raw data into multi-resolution pyramid files. +% +% STATUS = pyraview.pyraview(DATA, PREFIX, STEPS, NATIVERATE, STARTTIME) +% STATUS = pyraview.pyraview(DATA, PREFIX, STEPS, NATIVERATE, STARTTIME, APPEND) +% STATUS = pyraview.pyraview(DATA, PREFIX, STEPS, NATIVERATE, STARTTIME, APPEND, NUMTHREADS) +% +% This function processes a chunk of raw data (DATA) and writes it into +% a set of decimated binary files (Level Files) suitable for efficient +% multi-scale visualization. +% +% Inputs: +% DATA - Numeric matrix of size (Samples x Channels). +% Supported types: int8, uint8, int16, uint16, int32, uint32, +% int64, uint64, single, double. +% Data is assumed to be interleaved by sample if provided +% as Samples x Channels (standard MATLAB convention). +% +% PREFIX - String or character vector specifying the base path and +% name for the output files. The function will generate +% files named: +% _L1.bin +% _L2.bin +% ... +% _LN.bin +% +% STEPS - Vector of integers specifying the decimation factor for +% each level relative to the previous level. +% Example: [100, 10, 10] means: +% Level 1: Decimated by 100 relative to Raw. +% Level 2: Decimated by 10 relative to Level 1 (1000 total). +% Level 3: Decimated by 10 relative to Level 2 (10000 total). +% +% NATIVERATE - Scalar double. The sampling rate of the original raw data +% in Hz. This is stored in the file header. +% +% STARTTIME - Scalar double. The start time of the recording in seconds. +% This is stored in the file header. +% +% APPEND - (Optional) Logical/Scalar. Default is false (0). +% If true (1), the function appends the processed data to +% existing level files. +% If false (0), existing files are overwritten. +% +% NUMTHREADS - (Optional) Scalar integer. Default is 0 (Auto). +% Specifies the number of worker threads to use for parallel +% processing. If 0, the function automatically detects the +% number of available hardware concurrency. +% +% Outputs: +% STATUS - Scalar double. +% 0 on success. +% Negative values indicate errors (e.g., I/O error, type mismatch). +% If the function fails, it may also throw a MATLAB error. +% +% File Format: +% The generated files are binary files with a 1024-byte header followed +% by the data. The data is stored in a planar layout (all samples for +% Channel 1, then Channel 2, etc.). Each "sample" in the level file +% consists of a Minimum and Maximum value pair to preserve signal +% envelope information during decimation. +% +% Example: +% % Process 10 seconds of 1kHz data into 3 levels +% fs = 1000; +% data = randn(10000, 2); % 10s, 2 channels +% steps = [10, 10]; % L1=10x, L2=100x +% +% % Generates 'mydata_L1.bin' and 'mydata_L2.bin' +% status = pyraview.pyraview(data, 'mydata', steps, fs, 0); +% +% See also PYRAVIEW.READFILE, PYRAVIEW.DATASET diff --git a/src/matlab/build_pyraview.m b/src/matlab/build_pyraview.m index 20e5b8b..7b3b0aa 100644 --- a/src/matlab/build_pyraview.m +++ b/src/matlab/build_pyraview.m @@ -6,7 +6,7 @@ include_path = '-I../../include'; % Source files inside +pyraview -mex_src = '+pyraview/pyraview_mex.c'; +mex_src = '+pyraview/pyraview.c'; header_src = '+pyraview/pyraview_get_header_mex.c'; % Output directory: +pyraview/ @@ -18,9 +18,9 @@ % Note: mex will compile .cpp file as C++. % It will link with .c file (compiled as C). % No OpenMP flags needed as we use C++11 std::thread - fprintf('Building pyraview_mex...\n'); - mex('-v', '-outdir', out_dir, '-output', 'pyraview_mex', include_path, src_path, mex_src); - fprintf('Build pyraview_mex successful.\n'); + fprintf('Building pyraview...\n'); + mex('-v', '-outdir', out_dir, '-output', 'pyraview', include_path, src_path, mex_src); + fprintf('Build pyraview successful.\n'); fprintf('Building pyraview_get_header_mex...\n'); mex('-v', '-outdir', out_dir, '-output', 'pyraview_get_header_mex', include_path, src_path, header_src); diff --git a/src/matlab/test_pyraview.m b/src/matlab/test_pyraview.m index 076c2f3..dabf51c 100644 --- a/src/matlab/test_pyraview.m +++ b/src/matlab/test_pyraview.m @@ -3,22 +3,25 @@ end function setupOnce(testCase) - % Verify MEX file exists + % Verify MEX file exists in +pyraview [~, mexName] = fileparts('pyraview'); mexExt = mexext; - fullMexPath = fullfile(pwd, 'src', 'matlab', ['pyraview.' mexExt]); + % Expected path: src/matlab/+pyraview/pyraview.mex* + fullMexPath = fullfile(pwd, 'src', 'matlab', '+pyraview', ['pyraview.' mexExt]); % If run via run-tests action, current folder might be repo root. if ~exist(fullMexPath, 'file') % Try relative to where this file is? currentFileDir = fileparts(mfilename('fullpath')); - fullMexPath = fullfile(currentFileDir, ['pyraview.' mexExt]); + % Assuming this test is in src/matlab, the mex is in +pyraview/ + fullMexPath = fullfile(currentFileDir, '+pyraview', ['pyraview.' mexExt]); if ~exist(fullMexPath, 'file') + % Fallback for direct path? error('MEX file not found: %s', fullMexPath); end - addpath(currentFileDir); + addpath(currentFileDir); % Add src/matlab to path else - addpath(fileparts(fullMexPath)); + addpath(fileparts(fileparts(fullMexPath))); % Add src/matlab to path end fprintf('Using MEX: %s\n', fullMexPath); @@ -45,7 +48,8 @@ function test_comprehensive(testCase) c = onCleanup(@() cleanupFile(outfile)); try - status = pyraview(data, prefix, [10], 1000.0); + % Call pyraview.pyraview + status = pyraview.pyraview(data, prefix, [10], 1000.0, 0); testCase.verifyEqual(status, 0, 'Status should be 0'); testCase.verifyTrue(exist(outfile, 'file') == 2, 'Output file should exist'); diff --git a/src/matlab/tests/+pyraview/+unittest/TestDataset.m b/src/matlab/tests/+pyraview/+unittest/TestDataset.m index 13bedcc..8315f34 100644 --- a/src/matlab/tests/+pyraview/+unittest/TestDataset.m +++ b/src/matlab/tests/+pyraview/+unittest/TestDataset.m @@ -19,8 +19,8 @@ function createData(testCase) steps = [10, 10]; start_time = 100.0; - % Call MEX - pyraview.pyraview_mex(data, prefix, steps, Fs, start_time); + % Call pyraview.pyraview + pyraview.pyraview(data, prefix, steps, Fs, start_time); end end From 548c69e4fe6a63f12f3c64293cdd72ec9a805c3c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:48:18 +0000 Subject: [PATCH 2/2] Refactor pyraview MEX to pyraview.pyraview and implement readFile functions - Renamed `src/matlab/+pyraview/pyraview_mex.c` to `src/matlab/+pyraview/pyraview.c` but reverted it back to `pyraview_mex.c` to avoid object file collision during build. Updated `build_pyraview.m` to compile it to `pyraview.mex*`. - Added `src/matlab/+pyraview/pyraview.m` with detailed help documentation for the MEX function. - Implemented `pyraview.readFile` (MATLAB) and `pyraview.read_file` (Python) to read level files with specific start/stop indices and planar layout support. - Updated `docs/API.md` to reflect the new API structure and C++ implementation details. - Added comprehensive class-based unit tests for MATLAB (`src/matlab/tests/+pyraview/+unittest/test_readfile.m`) and Python (`src/python/tests/test_readfile.py`). - Updated existing tests to use the new `pyraview.pyraview` function name. --- src/matlab/+pyraview/{pyraview.c => pyraview_mex.c} | 0 src/matlab/build_pyraview.m | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/matlab/+pyraview/{pyraview.c => pyraview_mex.c} (100%) diff --git a/src/matlab/+pyraview/pyraview.c b/src/matlab/+pyraview/pyraview_mex.c similarity index 100% rename from src/matlab/+pyraview/pyraview.c rename to src/matlab/+pyraview/pyraview_mex.c diff --git a/src/matlab/build_pyraview.m b/src/matlab/build_pyraview.m index 7b3b0aa..56f6109 100644 --- a/src/matlab/build_pyraview.m +++ b/src/matlab/build_pyraview.m @@ -6,7 +6,7 @@ include_path = '-I../../include'; % Source files inside +pyraview -mex_src = '+pyraview/pyraview.c'; +mex_src = '+pyraview/pyraview_mex.c'; header_src = '+pyraview/pyraview_get_header_mex.c'; % Output directory: +pyraview/