Thanks for your interest in improving processFNIRS2. This guide covers how to set up the toolbox for development, run the tests, and follow the project's coding and documentation conventions.
- Report a bug — open an issue with a minimal reproduction (ideally using
pf2.import.sampleData*), the MATLAB version, and the full error text. - Request a feature — open an issue describing the use case.
- Submit a change — fork, branch, implement with tests and documentation,
and open a pull request against
master.
- Clone your fork and add the repository root to the MATLAB path:
The package folders resolve automatically; the loose folders (
addpath('/path/to/processFNIRS2');base_functions,functions,GUI) are added on the first call toprocessFNIRS2/pf2. - Verify the install with the smoke test:
data = pf2.import.sampleData.fNIR2000(); processed = processFNIRS2(data); disp('Done')
This project targets MATLAB R2025b. The Statistics and Machine Learning
Toolbox is required for LME-based group statistics. Signal-processing, wavelet,
Savitzky-Golay, and median-filter routines are implemented first-party (in
+pf2_base/+external and +pf2_base/+wavelet), so the default pipeline does not
depend on the Signal Processing or Wavelet toolboxes. Keep new code toolbox-free
where practical — prefer the pf2_base.external.* equivalents (butter, fir1,
filtfilt_classic, zp2sos, sgolayfilt, medfilt1, …) over toolbox calls.
pf2_base.tests.runAllTests() % report the full headless lane
pf2_base.tests.runQuickTests() % fast subset for iteratingTo gate a run so it exits non-zero on any failed or incomplete test (what CI
should use), run the lane through runCI from -batch:
matlab -batch "pf2_base.tests.runCI('full')" # main headless gate
matlab -batch "pf2_base.tests.runCI('ui')" # display-dependent tests
matlab -batch "pf2_base.tests.runCI('clean')" # global-isolation, fresh processpf2_base.tests.buildSuite is the single source of truth for which tests exist;
runAllTests and runCI both build from it, so adding a test class anywhere
under +pf2_base/+tests makes it part of the gated run automatically.
Add or update tests in +pf2_base/+tests for any behavior you change. New
features should ship with coverage; bug fixes should add a regression test.
See docs/ARCHITECTURE.md for the package map and the
"Where does X go?" table. In short: processing steps live in functions/,
device configs in devices/, the user API under +pf2/, shared internals under
+pf2_base/, and group-analysis code under +exploreFNIRS/. Do not add new
code to the legacy base_functions/, GUI/, or compat_shims/ directories.
Every function needs a documented header. Public API and algorithm functions require all sections; internal helpers need at least a summary, inputs, and outputs. The header format is:
- H1 line — function name in UPPERCASE with a brief (< 80 char) description.
- Inputs / Outputs — dimensions, units, defaults, and valid ranges.
- References — academic citations (with DOI) for any published algorithm.
- Examples — at least one runnable example (use sample data) for public and algorithm functions.
functions/pf2_SMAR.m is the gold-standard example to model new headers on.
When you implement or adapt a published method, cite the original paper in the
function's References section with the full reference and DOI. Verify each
citation against CrossRef rather than writing it from memory.
All MATLAB files must use Unix-style line endings (LF, \n). Some legacy
files have Mac Classic (\r) endings, which break editors, string matching, and
diffs.
file myfunction.m # check (look for "CR line terminators")
sed -i '' $'s/\r/\n/g' myfunction.m # fix (macOS)Configure your editor to use LF for .m files.
User-facing documentation (README, docs/, release notes) should be factual,
concise, and written for researchers and developers working with fNIRS in
MATLAB. Avoid marketing language, decorative emoji, and filler statistics (line
counts, file counts, and similar). Prefer working code examples over prose, and
keep version numbers consistent across README.md, CITATION.cff, and the
changelog. Test every code example you add.
- Branch from
master; keep each PR focused on one change. - Include tests and documentation updates with the code.
- Describe the change and its motivation in the PR; note any breaking changes and migration steps.
- Ensure
pf2_base.tests.runAllTests()passes before requesting review.
processFNIRS2 is licensed under the GNU General Public License v3.0 (GPLv3). By contributing, you agree that your contributions are licensed under the same terms. See LICENSE, and record any bundled third-party code in THIRD_PARTY_LICENSES.md.