Skip to content

Commit a7fe899

Browse files
Merge pull request #15 from VH-Lab/add-readfile-functions-13897329639786336155
Refactor pyraview MEX and implement readFile functions
2 parents ee2d741 + 548c69e commit a7fe899

5 files changed

Lines changed: 98 additions & 20 deletions

File tree

docs/API.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,23 @@ Returns:
6969

7070
---
7171

72-
## Matlab API (`src/matlab/pyraview_mex.c`)
72+
## Matlab API (`src/matlab/+pyraview/`)
7373

74-
### `status = pyraview_mex(data, prefix, steps, nativeRate, [append], [numThreads])`
74+
### `status = pyraview.pyraview(data, prefix, steps, nativeRate, [append], [numThreads])`
75+
Processes raw data into multi-resolution pyramid files.
7576

7677
Arguments:
77-
- `data`: Numeric matrix. Supports: `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64`, `single`, `double`.
78-
- `prefix`: String.
79-
- `steps`: Vector of integers.
80-
- `nativeRate`: Scalar double.
81-
- `append`: Logical/Scalar (optional).
82-
- `numThreads`: Scalar (optional).
78+
- `data`: (Samples x Channels) matrix.
79+
- Supported types: `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64`, `single`, `double`.
80+
- `prefix`: String specifying the base path and name for the output files.
81+
- Generates files named `<prefix>_L1.bin`, `<prefix>_L2.bin`, etc.
82+
- `steps`: Vector of integers specifying decimation factors for each level (relative to previous level).
83+
- `nativeRate`: Scalar double (Hz). Original sampling rate of the raw data.
84+
- `append`: (Optional) Logical/Scalar. Default `false`. If true, appends to existing files.
85+
- `numThreads`: (Optional) Scalar integer. Default `0` (Auto). Number of worker threads.
8386

8487
Returns:
85-
- `status`: 0 on success. Throws error on failure.
88+
- `status`: 0 on success. Negative values indicate errors.
8689

8790
### `D = pyraview.readFile(filename, s0, s1)`
8891
Reads a specific range of samples from a level file.

src/matlab/+pyraview/pyraview.m

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
%PYRAVIEW Process raw data into multi-resolution pyramid files.
2+
%
3+
% STATUS = pyraview.pyraview(DATA, PREFIX, STEPS, NATIVERATE, STARTTIME)
4+
% STATUS = pyraview.pyraview(DATA, PREFIX, STEPS, NATIVERATE, STARTTIME, APPEND)
5+
% STATUS = pyraview.pyraview(DATA, PREFIX, STEPS, NATIVERATE, STARTTIME, APPEND, NUMTHREADS)
6+
%
7+
% This function processes a chunk of raw data (DATA) and writes it into
8+
% a set of decimated binary files (Level Files) suitable for efficient
9+
% multi-scale visualization.
10+
%
11+
% Inputs:
12+
% DATA - Numeric matrix of size (Samples x Channels).
13+
% Supported types: int8, uint8, int16, uint16, int32, uint32,
14+
% int64, uint64, single, double.
15+
% Data is assumed to be interleaved by sample if provided
16+
% as Samples x Channels (standard MATLAB convention).
17+
%
18+
% PREFIX - String or character vector specifying the base path and
19+
% name for the output files. The function will generate
20+
% files named:
21+
% <PREFIX>_L1.bin
22+
% <PREFIX>_L2.bin
23+
% ...
24+
% <PREFIX>_LN.bin
25+
%
26+
% STEPS - Vector of integers specifying the decimation factor for
27+
% each level relative to the previous level.
28+
% Example: [100, 10, 10] means:
29+
% Level 1: Decimated by 100 relative to Raw.
30+
% Level 2: Decimated by 10 relative to Level 1 (1000 total).
31+
% Level 3: Decimated by 10 relative to Level 2 (10000 total).
32+
%
33+
% NATIVERATE - Scalar double. The sampling rate of the original raw data
34+
% in Hz. This is stored in the file header.
35+
%
36+
% STARTTIME - Scalar double. The start time of the recording in seconds.
37+
% This is stored in the file header.
38+
%
39+
% APPEND - (Optional) Logical/Scalar. Default is false (0).
40+
% If true (1), the function appends the processed data to
41+
% existing level files.
42+
% If false (0), existing files are overwritten.
43+
%
44+
% NUMTHREADS - (Optional) Scalar integer. Default is 0 (Auto).
45+
% Specifies the number of worker threads to use for parallel
46+
% processing. If 0, the function automatically detects the
47+
% number of available hardware concurrency.
48+
%
49+
% Outputs:
50+
% STATUS - Scalar double.
51+
% 0 on success.
52+
% Negative values indicate errors (e.g., I/O error, type mismatch).
53+
% If the function fails, it may also throw a MATLAB error.
54+
%
55+
% File Format:
56+
% The generated files are binary files with a 1024-byte header followed
57+
% by the data. The data is stored in a planar layout (all samples for
58+
% Channel 1, then Channel 2, etc.). Each "sample" in the level file
59+
% consists of a Minimum and Maximum value pair to preserve signal
60+
% envelope information during decimation.
61+
%
62+
% Example:
63+
% % Process 10 seconds of 1kHz data into 3 levels
64+
% fs = 1000;
65+
% data = randn(10000, 2); % 10s, 2 channels
66+
% steps = [10, 10]; % L1=10x, L2=100x
67+
%
68+
% % Generates 'mydata_L1.bin' and 'mydata_L2.bin'
69+
% status = pyraview.pyraview(data, 'mydata', steps, fs, 0);
70+
%
71+
% See also PYRAVIEW.READFILE, PYRAVIEW.DATASET

src/matlab/build_pyraview.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
% Note: mex will compile .cpp file as C++.
1919
% It will link with .c file (compiled as C).
2020
% No OpenMP flags needed as we use C++11 std::thread
21-
fprintf('Building pyraview_mex...\n');
22-
mex('-v', '-outdir', out_dir, '-output', 'pyraview_mex', include_path, src_path, mex_src);
23-
fprintf('Build pyraview_mex successful.\n');
21+
fprintf('Building pyraview...\n');
22+
mex('-v', '-outdir', out_dir, '-output', 'pyraview', include_path, src_path, mex_src);
23+
fprintf('Build pyraview successful.\n');
2424

2525
fprintf('Building pyraview_get_header_mex...\n');
2626
mex('-v', '-outdir', out_dir, '-output', 'pyraview_get_header_mex', include_path, src_path, header_src);

src/matlab/test_pyraview.m

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,25 @@
33
end
44

55
function setupOnce(testCase)
6-
% Verify MEX file exists
6+
% Verify MEX file exists in +pyraview
77
[~, mexName] = fileparts('pyraview');
88
mexExt = mexext;
9-
fullMexPath = fullfile(pwd, 'src', 'matlab', ['pyraview.' mexExt]);
9+
% Expected path: src/matlab/+pyraview/pyraview.mex*
10+
fullMexPath = fullfile(pwd, 'src', 'matlab', '+pyraview', ['pyraview.' mexExt]);
1011

1112
% If run via run-tests action, current folder might be repo root.
1213
if ~exist(fullMexPath, 'file')
1314
% Try relative to where this file is?
1415
currentFileDir = fileparts(mfilename('fullpath'));
15-
fullMexPath = fullfile(currentFileDir, ['pyraview.' mexExt]);
16+
% Assuming this test is in src/matlab, the mex is in +pyraview/
17+
fullMexPath = fullfile(currentFileDir, '+pyraview', ['pyraview.' mexExt]);
1618
if ~exist(fullMexPath, 'file')
19+
% Fallback for direct path?
1720
error('MEX file not found: %s', fullMexPath);
1821
end
19-
addpath(currentFileDir);
22+
addpath(currentFileDir); % Add src/matlab to path
2023
else
21-
addpath(fileparts(fullMexPath));
24+
addpath(fileparts(fileparts(fullMexPath))); % Add src/matlab to path
2225
end
2326

2427
fprintf('Using MEX: %s\n', fullMexPath);
@@ -45,7 +48,8 @@ function test_comprehensive(testCase)
4548
c = onCleanup(@() cleanupFile(outfile));
4649

4750
try
48-
status = pyraview(data, prefix, [10], 1000.0);
51+
% Call pyraview.pyraview
52+
status = pyraview.pyraview(data, prefix, [10], 1000.0, 0);
4953
testCase.verifyEqual(status, 0, 'Status should be 0');
5054

5155
testCase.verifyTrue(exist(outfile, 'file') == 2, 'Output file should exist');

src/matlab/tests/+pyraview/+unittest/TestDataset.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ function createData(testCase)
1919
steps = [10, 10];
2020
start_time = 100.0;
2121

22-
% Call MEX
23-
pyraview.pyraview_mex(data, prefix, steps, Fs, start_time);
22+
% Call pyraview.pyraview
23+
pyraview.pyraview(data, prefix, steps, Fs, start_time);
2424
end
2525
end
2626

0 commit comments

Comments
 (0)