- +pf2 — User-Facing Interface — import, export, data, methods, probe, QC, settings
- +pf2_base — Advanced and Internal Infrastructure — pipelines, core processing, signal/wavelet
- +exploreFNIRS — Analysis & Visualization — Experiment class, stats, connectivity, hyperscanning, graph, report
- Signal Processing Functions (
/functions/) - Supported Devices (
/devices/) - Global Variables
- File Type Associations
The primary user-facing package with intuitive function paths.
| Function | Purpose |
|---|---|
importNIR.m |
Import fNIR Devices/Biopac (.nir) files |
importNIRX.m |
Import NIRx system files |
importHitachiMES.m |
Import Hitachi ETG-4000 (.csv) files |
importOxy3.m |
Import Artinis OxySoft (.oxy3) files. Parses the OXY3 binary container (UTF-16LE XML header + int16 frames), derives channels/wavelengths, and extracts markers from the digital port/trigger channels. Optode geometry is a placeholder unless an OxySoft optodetemplates.xml is supplied via 'OptodeTemplate' |
importSNIRF.m |
Import standardized SNIRF format files (auto-reads BIDS _events.tsv for trial_type labels) |
importDirectory.m |
Batch-import files from a directory tree with auto-format detection |
importEmbeddings.m |
Re-import learned features/predictions from an HDF5 file (foundation-model export contract) into a data.embeddings block aligned to the recording's time base |
fromTable.m |
Build fNIRS-shaped segment structs from a long-format (tidy) data table — survey waves, longitudinal scores, diary measures — so the Experiment class, temporal/bar plots, and the LME engine work on non-device data. Each Subject → one segment, Time → the time axis, each Value → a pseudo-channel. No device/probe, so spatial viz is unavailable |
sampleData.m |
Load included example datasets (bare call loads fNIR1200; sampleData.fNIR2000(), sampleData.experiment(), sampleData.group() for siblings) |
| Function | Purpose |
|---|---|
export.m |
Auto-detect format from extension; batch-capable with 'Format' param |
asNIR.m |
Export to NIR file format (single struct or batch cell array) |
asSNIRF.m |
Export to SNIRF standardized format (single struct, multi-run, or batch) |
asBIDS.m |
Export a cell array as a true BIDS-NIRS dataset — *_nirs.snirf plus JSON/channels.tsv/events.tsv sidecars in a sub-/ses-/nirs tree, with dataset_description.json, participants.tsv, and README. Requires a 'Task' label; entities resolve from each struct's .info |
asTensor.m |
Export as a self-describing HDF5 tensor (foundation-model contract v1.0): [time × channel × feature] payload + montage descriptor + manifest (QC, markers, info, provenance). Supports windowed [window × time × channel × feature] output |
Batch export: pass a cell array and a directory path to write one file per element. Use 'Dir1'..'Dir4' to map .info fields to subdirectories, and 'Prefix' to build filenames from .info values.
| Function | Purpose |
|---|---|
plot.m |
Route to appropriate plot function |
applyChannelMask.m |
Mark bad channels as NaN |
concatenate.m |
Merge multiple devices/probes into one structure (more channels; resamples to a common rate and aligns time) |
concatenateHorizontal.m |
Concatenate segments in time (temporal merge of runs from the same probe — despite the name, this appends rows, not channels) |
defineBlocks.m |
Convert markers to block struct array (auto-labels blocks from the marker dictionary — markerDict/eventTypes/COBI) |
slidingWindows.m |
Tile a continuous recording with fixed-length/overlapping window blocks ('Length', 'Step'/'Overlap') on a regular grid; same block format as defineBlocks, feeds extractBlocks (dynamic FC, resting-state, model input) |
labelMarkers.m |
Stamp a categorical .Label column on the marker table from a {code,'Label'} map or the dataset's marker dictionary |
getMarkerDict.m |
Resolve the dataset's code→label dictionary (info.markerDict → eventTypes → COBI MarkerDict → unique codes) |
setMarkerDict.m |
Set/merge data.info.markerDict (table/cell/Map); 'Merge' (default true) unions, new wins |
editChannelMaskGUI.m |
GUI for channel masking |
extractBlocks.m |
Extract fNIRS segments by block definitions (note: when PreTime/PostTime are omitted, a small default Buffer of 2 s per side is used — set them explicitly to size epochs; passing an embedded data struct as the blocks arg is detected and resolved) |
blockAverage.m |
Trial/grand average of epoched segments onto a common grid (resamples segments to a shared grid first, so marker-epoched data does not average to NaN) |
grandAverage.m |
Alias for blockAverage.m |
importInfo.m |
Import subject-level metadata from CSV/Excel into .info |
importBlockInfo.m |
Import block-level metadata into block structs from a CSV/Excel path, an in-memory MATLAB table, or a numeric per-block vector (assigned to the field named by 'Field', default 'value') |
infoToTable.m |
Extract .info fields to a MATLAB table. Options: 'Fields' to select columns, 'SavePath' to export. Single-field shorthand: infoToTable(allData, 'Group') returns vector |
infoFromTable.m |
Write table (or single field) back into .info. Options: 'Overwrite' (default true), 'Clear' (replace .info entirely). Scalar broadcast: infoFromTable(allData, 'Group', 'Control'). Per-element: infoFromTable(allData, 'Group', ["A";"B";"C"]) |
getMarkers.m |
Extract marker timepoints. Scalar = single code; row vector [50,51] = sequence (50 then 51); column vector [50;51] = either code (OR); warns when no requested code is found |
resample.m |
resample/average fNIRS data |
setT0.m |
Shift time alignment |
split.m |
Extract time segment with optional baseline correction |
auxOnGrid.m |
Resample a named auxiliary signal (nested or flattened) onto the fNIRS time base — anti-aliased and NaN-gap aware; 'Channels' selects a subset |
betasToSegments.m |
Convert GLM betas back to segment-style data format |
| Function | Purpose |
|---|---|
oxy.m |
Plot hemoglobin concentration data |
raw.m |
Plot raw light intensity data |
roi.m |
Plot region-of-interest data |
auxData.m |
Plot auxiliary temporal data |
Type-aware feature extractors that turn a raw auxiliary waveform into a derived
feature series. Aux signals are typed (HR, EKG, PPG, ACCEL, GSR/EDA, EEG, RESP,
TEMP) by pf2_base.auxSignalType and put in canonical form by
pf2_base.normalizeAux.
| Function | Purpose |
|---|---|
heartRateFrom.m |
Derive a heart-rate (bpm) series from a PPG or EKG waveform |
hrvFeatures.m |
Heart-rate variability metrics (SDNN/RMSSD/pNN50/LF/HF/LFHF) from a waveform or beat series |
hrvSeries.m |
Time-resolved HRV via a sliding window over a waveform |
edaDecompose.m |
Split electrodermal activity (GSR) into tonic (SCL) and phasic (SCR) components |
accelFeatures.m |
Motion features (norm, jerk) from a multi-axis accelerometer signal |
eegBandPower.m |
Canonical EEG band-power feature series (delta..gamma) |
respFeatures.m |
Respiration rate (br/min) and RVT from a respiration waveform |
addFeature.m |
Store a derived signal back as a typed Aux feature (survives SNIRF round-trip) |
| Subpackage | Purpose |
|---|---|
+raw/ |
Raw processing stage method configuration |
+oxy/ |
Oxygenation processing stage method configuration |
Each subpackage contains:
list.m- List available methodssetMethod.m- Select active methodconfigureMethods.m- Create/edit methods (GUI)describeMethod.m- Display method documentationimportMethods.m/importMethod.m- Import method configuration filescreate.m- Create a new method programmaticallydelete.m- Delete a methodeditFunction.m- Modify a function in a method chainremoveFunction.m- Remove a function from a method chainexportMethod.m- Export method for sharing
Method-authoring internals — function validation, the default-method seed factories, and the add/edit-function GUI helpers — live under
+pf2_base/+methods(see below), not in the primarypf2.methodsAPI.
| Function | Purpose |
|---|---|
process.m |
Generic processing dispatcher |
processRaw.m |
Execute raw processing stage only |
processOxy.m |
Execute oxy processing stage only |
| Member | Returns |
|---|---|
Device.load(nameOrData) |
Create Device from config name or data struct (cached) |
Device.fromProbeInfo(probeInfo) |
Create Device from already-loaded probeInfo struct |
Device.clearCache() |
Reset persistent cache |
dev.wavelengths() |
[1×C_raw] wavelength per raw column |
dev.channelNumbers() |
[1×C_raw] optode number per raw column |
dev.channelList() |
[1×nCh] unique channel indices |
dev.mniPositions() |
[nCh×3] MNI coordinates |
dev.sdDistances() |
[1×nCh] source-detector distances |
dev.channelTable() |
MATLAB table (TableCh) |
dev.optodeTable() |
MATLAB table (TableOpt) |
dev.layout2D() |
Cell array of subplot positions |
dev.hasMNI() |
logical |
dev.isShortSep() |
[1×nCh] logical mask |
Immutable properties: name, manufacturer, model, nChannels, nShortSep, defaultFs, wavelengthSet, rawMax, rawMin, probeInfo.
Auto-attached as data.device by all import functions and processFNIRS2.
| Function | Purpose |
|---|---|
selectDevice.m |
Load device configuration file |
getDevice.m |
Query current device settings (checks data.device first) |
setRejectLevel.m |
Set channel rejection threshold |
+baseline subfolder:
setBaselineStartTime.m- Set baseline start timesetBaselineLength.m- Set baseline durationuseGlobalMean.m- Use entire signal as baseline
+dpf subfolder:
setDPFmode.m- Set DPF calculation mode (None/Fixed/Calc/PPF; case-insensitive)setFixedDPF.m- Set fixed DPF value
| Function/Subpackage | Purpose |
|---|---|
nearestBrodmann.m |
Find nearest Brodmann areas for each channel |
montage.m |
Portable, self-describing montage export — per-channel table + montage descriptor struct (MNI coords, S-D distances, wavelengths, short-sep flags, nearest Brodmann); optional JSON/CSV/XLSX sidecar |
saveCfg.m |
Write a probe's geometry to a toolbox-native device .cfg (reloadable via pf2.Device.load) — reconstructs src/det coords, channel/wavelength mapping, and sI/dI from the device tables; accepts a data struct, pf2.Device, .snirf path, or config name; prefers 3D (mm), falls back to 2D |
canonicalize.m |
Project channel biomarker series onto a shared Brodmann-region axis for cross-montage/cross-device comparison (region averaging via nearestBrodmann); a cell array yields a common region axis |
+plot/ |
Probe visualization functions |
+project/ |
Project statistical values onto the cortical surface |
+roi/ |
Region of interest management |
+forward/ |
DOT forward model — optical sensitivity (PMDF) on the cortical mesh |
+dot/ |
Diffuse optical tomography — image reconstruction and diagnostics |
Plot functions:
topo.m- Convenience topographic map (2D/3D);'View','movie'animates over timearrangedValues.m- Plot arranged channel valuesimageValues.m- Create 2D heatmap of channel valuesinterpolateValues.m- Interpolate values across probeinterpolateValues3D.m- 3D interpolation visualization ('interpolateType','sensitivity'for a Gaussian optical-sensitivity kernel;'Style','showcase'|'publication'render presets — see below)imageROIvalues.m- Heatmap for ROI valuesinterpolateROIvalues.m- Interpolated ROI visualizationshowProbe3D.m- 3D probe geometry visualizationshowHead3D.m- Colin27 head model (translucent scalp + brain surface) in real MNI mm with the probe overlaid;'Markers','optodes'|'channels'|'both'draws sources/detectors or channel midpoints,'ShowScalp'toggles the scalp layer,'Cortex','colin27'|'cerebro'selects the brain surface (visualization/QC only, not for DOT)movie.m- Animate a biomarker over time on the cortex/probe (MP4/AVI/GIF)connectome.m- Draw a connectivity network anchored at channel/ROI positions (2D/3D)tomographyMovie.m- Animate a time-resolved DOT reconstruction on the cortex (MP4/AVI/GIF)Explore3D.m- Interactive explorer forinterpolateValues3D: live controls for style/material/AO/view/colormap/interpolation/biomarker/labels, with the equivalent generating command shown for copy-paste
3D render styles.
interpolateValues3D(and everything built on it —topo'View','3d',project.*) takes a'Style'preset.'showcase'(default) uses procedural matcap shading, a neutral-gray cortex, sulcal ambient occlusion, an elevated 3/4 "hero" view and 2× supersampled export (inspired by MRIcroGL/Surfice).'publication'is a conservative Gouraud matte look. Pass a struct (pf2_base.plot.RenderStyle.get('showcase')) to override individual fields (matcapMaterial,aoStrength,heroView,supersample, ...). Colormap names now resolve throughpf2_base.plot.brainColormap— MRIcroGL LUTs (actc,warm,cool,blue2red,bone,surface) plus CVD-safe maps (rdbu,viridis,cividis).
Project functions (+pf2/+probe/+project/): 3D cortical-surface projection of per-channel statistics, with significance-based transparency.
pvalues.m- Project p-values onto the cortexfstats.m- Project F-statisticscorrelation.m- Project correlation valuesbiomarker.m- Project biomarker (e.g. mean HbO) valuescounts.m- Project per-channel N countsregions.m- Flat-fill Brodmann parcels from canonicalized region valuesparcels.m- Optode parcel map: per-channel Voronoi cells (nearest-optode) with outlines and on-surface numbers; optional value-fill and highlighted subset (channel-assignment cartoon, not reconstruction)pmdf.m- Project channel values through the physical sensitivity "banana" (honest footprint vs a Gaussian kernel)tomography.m- Render a DOT image reconstruction (signed, sensitivity-masked) on the cortex
Diffuse Optical Tomography (+pf2/+probe/+forward/, +pf2/+probe/+dot/): image-space HbO/HbR reconstruction on the cortical surface via an atlas forward model and a regularized inverse.
forward.sensitivity- Channel-by-vertex PMDF sensitivity matrix on the MNI cortical mesh (options: wavelength, scalp offset, max S-D distance, pruning)forward.coverage- Per-vertex sensitivity support map for a montagedot.reconstruct- Vertex-space HbO/HbR reconstruction (depth-weighted, channel-whitened Tikhonov min-norm; auto-regularization; time-mean/windowed/all-time; priorsminnorm/laplacian/parcel; optional layered head model + scalp regression)dot.montageInfo- Report whether a montage is high-density / multi-distance and its reconstruction suitabilitydot.resolution- Point-spread-function diagnostics (localization error, spread, FWHM)
pf2_base contains both supported expert/low-level interfaces and
implementation machinery. Advanced users may deliberately use documented
pipeline and scientific operations; callbacks, codecs, compatibility plumbing,
and incidental helpers are not thereby public contracts. The advanced API is
an explicit allowlist, not every callable symbol in the package.
| Class | Purpose |
|---|---|
PipelineFunction.m |
Immutable value class encapsulating a single processing function with precomputed argument mappings and zero-overhead execute() |
Pipeline.m |
Ordered chain of PipelineFunction steps — add(), insert(), remove(), setParam(), toMethod(), fromMethod(), params() |
RawPipeline.m |
Stage 1 specialization — hasIntensity2OD() helper |
OxyPipeline.m |
Stage 3 specialization — hasROI(), swapROI(), removeROI() helpers |
ProcessingContext.m |
Execution context passed to PipelineFunction.execute(); carries the working data, settings, and device for an isolated processing run |
PipelineFunction resolves all argument lookups at construction time using uint8 enum types, so execute(ctx) runs with zero string comparison overhead. Supports fromStruct(s) / toStruct() for legacy method round-tripping, detect(funcName) for auto-discovering signatures, and fromString(callStr) for parsing MATLAB call syntax.
Pipeline is a value class — all mutating methods return a new copy. toMethod() converts to the legacy method struct consumed by processStageRaw2OD and processStageFilterHb. fromMethod(name, stage) reconstructs a Pipeline from an existing named method.
Advanced method-authoring tools and the shipped default-method seed factories.
| Function | Purpose |
|---|---|
validateFunction.m |
Validate a processing-function configuration (function existence, argument consistency, output-variable name) before adding it to a method chain |
+seeds/list.m |
Enumerate the seed factories for a stage (raw/oxy) |
+seeds/+raw/*, +seeds/+oxy/* |
Zero-argument factories that build the shipped default methods (e.g. OD_TDDR, LPF); used by pf2_initialize and pf2.methods.resetDefaults |
+functions/add.m / +functions/edit.m |
Launch the GUI to define / edit processing-function metadata |
| Function | Purpose |
|---|---|
pf2_initialize.m |
Initialize system, load default settings |
pf2version.m |
Version information (note: no underscore) |
pf2_defaultRootPath.m |
Get installation path |
pf2_unpackMethod.m |
Parse method configuration; converts legacy structs to PipelineFunction |
pf2_updateCurrentDevice.m |
Sync device configuration |
pf2_describeMethod.m |
Display method information |
pf2_getFNIRSfields.m |
Get standard fNIRS field names |
pf2_getFNIRSbiomFields.m |
Get biomarker field aliases |
normalizeMarkers.m |
Normalize markers (matrix/table/[]) into the canonical table (.Time, .Code, .Duration, .Amplitude + extras) |
markersToArray.m |
Convert a canonical marker table (or matrix) to a numeric [M x 4] array |
mergeMarkers.m |
Row-concatenate two marker sets, unioning their columns |
normalizeMarkerDict.m |
Normalize a code→label dictionary (table/cell/Map/[]) into the canonical dict table (.Code, .Label + per-code attributes), deduped by Code |
mergeMarkerDict.m |
Merge two marker dictionaries, unioning codes and columns (first argument wins on Code conflicts) |
applyLightTheme.m |
Consistent light theme for figures |
| Function | Purpose |
|---|---|
isnestedfield.m |
Check nested struct fields |
mergestructs.m |
Merge structure arrays |
resolveDeviceFromData.m |
Return data.device if present, otherwise pf2.Device.load(data) |
loadDeviceCfg.m |
Load device configuration files |
loadProbeInfo.m |
Load probe geometry information |
buildProbeLayout.m |
Construct probe structure from config |
optTo2d.m |
Map 3D optode positions to 2D |
fitProbe2D.m |
Fit probe positions to 2D plane |
tablerow2struct.m |
Convert table row to struct |
hierarchicalAverage.m |
Hierarchical within-subject averaging |
pf2_plotArranged.m |
Plot data in configured arrangement |
filtfilt_interp.m |
Filtering with interpolation |
filtfilt_piecewise.m |
Piecewise filtering |
quickopen.m / quicksave.m |
Quick file I/O utilities |
getBioColors.m |
Get standard biomarker colors |
getAsset.m |
Load visualization assets (brain models, images) |
listAssets.m |
List available visualization assets |
| Function | Purpose |
|---|---|
tdsep.m |
Temporal Decorrelation Source Separation (TDSEP) — blind source separation via joint diagonalization of time-lagged covariance matrices (Ziehe & Muller 1998) |
lpf.m / hpf.m / bpf.m |
Numerically stable low-pass / high-pass / band-pass Butterworth filters |
Self-contained discrete and continuous wavelet routines (no external Wavelab or Wavelet Toolbox dependency).
| Function | Purpose |
|---|---|
makeONFilter.m |
Generate an orthonormal quadrature mirror filter (Haar, Daubechies, Symmlet, Coiflet, etc.) |
resolveWavelet.m |
Map a user-friendly wavelet name to an orthonormal QMF filter |
fwtPO.m / iwtPO.m |
Forward / inverse periodized orthogonal 1-D discrete wavelet transform |
fwtTI.m / iwtTI.m |
Forward / inverse translation-invariant (stationary) 1-D wavelet transform |
cwt.m |
Batch continuous wavelet transform (Morlet) |
wcoherence.m |
Wavelet coherence without the Wavelet Toolbox |
downDyadHi/Lo, upDyadHi/Lo, upSample, lShift/rShift, mirrorFilt, fwdConv/adjConv |
Filter-bank / convolution helpers |
| Function | Purpose |
|---|---|
sci.m |
Scalp Coupling Index (cross-correlates cardiac across wavelengths; uses data.device for wavelength resolution) |
powerSpectrum.m |
PSD with physiological peak detection (cardiac, respiratory, Mayer) |
plotQuality.m |
Visualize SCI bar charts or PSD line plots with band overlays |
snapshot.m |
One-call headless QC summary — runs the pipeline and writes dashboard + PSD + SCI PNGs to a directory |
takizawa.m |
Four-rule Hb quality check (Takizawa). Rule 4 (body movement) counts discrete movement events; default jump threshold 0.5 mM*mm (generalizes better across devices than the published 0.15) |
ChannelCheck.m |
App Designer GUI for interactive channel quality review (replaces probeCheckGUI) |
| Function | Purpose |
|---|---|
assess.m |
Run configurable quality checks on raw data (saturation, SCI, cardiac, CoV, Takizawa). Default CoV threshold 0.2 (raw intensity runs higher CoV than filtered Hb) |
apply.m |
Apply QC report recommendations to data |
report.m |
Print QC report summary to command window |
plotReport.m |
Visualize QC report as spatial channel map |
| Function | Purpose |
|---|---|
processStageRaw2OD.m |
Raw data to optical density conversion (Stage 1) |
bvoxy.m |
Beer-Lambert conversion to hemoglobin (Stage 2) |
processStageFilterHb.m |
Hemoglobin filtering (Stage 3) |
bvoxy_basic.m |
Simplified Beer-Lambert conversion |
buildROI.m |
Create region of interest from channels |
buildHRF.m |
Build hemodynamic response function |
buildDesignMatrix.m |
Construct GLM design matrices (Legendre or DCT drift) |
fitGLM.m |
Fit general linear model (OLS or AR-IRLS); AR-IRLS returns prewhitened X and residuals |
diagnoseGLM.m |
Comprehensive GLM diagnostic report (collinearity, VIF, partial R², residual ACF, flagging) |
shortChannelRegression.m |
Regress out short-channel signals |
extractShortChannelPCs.m |
Extract PCA components from short channels for GLM |
ezBuildROI.m |
Easy ROI construction |
Signal Processing (first-party replacements for Signal Processing Toolbox functions, called as pf2_base.external.*):
butter.m,fir1.m,zp2sos.m- Filter design (Butterworth, FIR, zero-pole-gain → second-order sections)filtfilt_classic.m- Zero-phase forward-backward filteringsgolay.m,sgolayfilt.m- Savitzky-Golay smoothingmedfilt1.m- One-dimensional median filterhamming.m,hann.m,hanning.m,genCosWin.m- Window functionsbarweb.m- Error bar visualization
Statistical Analysis:
polyparci.m- Polynomial confidence intervals
Visualization:
suptitle.m- Super title for subplotsvline.m- Vertical line annotation
Configuration / Geometry:
INI.m- INI configuration file parsericbm_fsl2tal.m- ICBM to Talairach conversionvrrotvec.m/vrrotvec2mat.m- Rotation vector / rotation matrix utilities
+colormaps subfolder:
brewermap.m- ColorBrewer color schemes+matplotlib/- Python matplotlib colormaps (viridis, plasma, inferno, magma, cividis, twilight, twilight_shifted, tab10, tab20, tab20b, tab20c)
+jsnirfy subfolder (SNIRF I/O):
loadsnirf.m/savesnirf.m- SNIRF file I/Oloadjsnirf.m/savejsnirf.m- JSON SNIRF I/Osnirfdecode.m/snirfcreate.m- SNIRF structure handling
+easyh5 subfolder (HDF5 utilities):
loadh5.m/saveh5.m- HDF5 file I/Ojdataencode.m/jdatadecode.m- JSON data encoding
Advanced GUI for multi-subject analysis and statistics. This is the group-level analysis layer that consumes processed fNIRS structs from processFNIRS2.
processFNIRS2 (per-subject) exploreFNIRS (multi-subject)
───────────────────────────── ─────────────────────────────
Raw → Hemoglobin conversion Statistics & visualization
Single fNIRS struct output Cell array of structs input
Signal processing algorithms LME modeling, FDR correction
| File | Purpose |
|---|---|
exploreFNIRS.m |
Main GUI application |
exploreFNIRS_App.mlapp |
Compiled App Designer version |
browseEx.m |
File browser function |
loadEx.m |
Load data for exploration |
saveEx.m |
Save explorer results |
processMethods.m |
Process method configuration |
plotExTimeline.m |
Plot experimental timeline |
| Subpackage | Purpose | Scriptable |
|---|---|---|
+core/ |
Experiment container, headless plotting (temporal, bar, topo, heatmap, composite, LME, scatter) | Yes |
+connectivity/ |
Connectivity analysis (matrix, dynamic FC, brain states, intra/inter-ROI) | Yes |
+coupling/ |
Coupling functions (Pearson, Spearman, xcorr, coherence, wcoherence, Granger, transfer entropy, HB-ICA) | Yes |
+hyperscanning/ |
Multi-brain hyperscanning analysis, HB-ICA, inter-brain visualization | Yes |
+dataset/ |
Data organization (buildSegmentInfoTable, standardizeROIs) | Yes |
+graph/ |
Graph-theory metrics on connectivity matrices (degree, clustering, efficiency, modularity, small-world, hubs) | Yes |
+report/ |
Publication report generation (HTML pipeline, APA tables, demographics, figure export, LaTeX) | Yes |
+plot/ |
Plotting functions (temporal, barchart, scatter) | GUI-only* |
+export/ |
Data export (mergeGbyTablesLong, mergeGbyTablesWide, connectivityToTable) | Yes |
+fx/ |
Statistical functions (performFDR, performFDR_twostep, autoContrast) | Yes |
+helper/ |
Utilities (getColormap, listColormaps) | Yes |
*Legacy plotting functions in +plot/ require GUI handles. Use +core/plotTemporal and +core/plotBar for headless plotting.
| Function | Purpose |
|---|---|
Experiment.m |
Main experiment container class (select, groupby, aggregate, connectivity, hyperscanning, hbica, intraROI, interROI, plot, export) |
GLMExperiment.m |
GLM wrapper extending Experiment — processing, design matrix, first-level fitting, beta packaging, betaSeriesConnectivity(), ppi(); both support 'Align' for unbalanced channels |
plotTemporal.m |
Headless temporal plots with ROI support |
plotBar.m |
Headless bar charts with ROI support |
plotTopo.m |
Headless topographic maps (single/pergroup layout, time snapshot or window) |
plotHeatmap.m |
Channel × time heatmap (sortable, diverging colormap, ROI support) |
plotComposite.m |
Multi-panel publication figures (tiledlayout, auto panel labels) |
plotLME.m |
LME analysis with bar charts, ANOVA tables, and topographic F-maps (fNIRS, ROI, Aux) |
plotScatter.m |
Scatter correlation with regression, topographic maps, and ROI support |
ColorScheme.m |
Hierarchical color rules for multi-factor plots (set, setBase, setPriority, resolve, preview) |
getGroupColors.m |
Consistent group coloring across plots |
| Function | Purpose |
|---|---|
PlotStyle.m |
Value class with style defaults and MATLAB dark mode support. Static factories: getDefault(), getPublication(), getPresentation(). Theme detection via isDarkMode() |
RenderStyle.m |
3D cortical render presets (get('showcase') / get('publication')): lighting/AO/matcap/view/supersample knobs consumed by interpolateValues3D |
brainColormap.m |
Cortical-overlay colormaps: MRIcroGL/Surfice LUTs (actc,warm,cool,hot,blue2red,bone,surface) + CVD-safe (rdbu,viridis,cividis); returns [N x 3] RGB and an alpha ramp |
matcapTexture.m |
Procedurally generate a lit-sphere matcap image (clay/porcelain/matte/glossy/pewter/jade) — no licensed assets |
matcapShade.m |
Sample a matcap by view-space vertex normals -> per-vertex RGB (view-dependent) |
vertexNormals.m |
Smooth area-weighted outward per-vertex normals for a triangle mesh |
meshCurvature.m |
Per-vertex curvature -> ambient-occlusion shading weight (darkens sulci) |
createFigure.m |
Standardized figure creation (auto Visible=off when SavePath set) |
handleSave.m |
Standardized save-if-requested (delegates to saveFigure) |
saveFigure.m |
Core save logic (PNG, PDF, SVG, FIG, etc.). Forces light mode for exported figures |
PlotStyle Theme Properties:
All plot functions use PlotStyle for theme-aware colors. When MATLAB is in dark mode, colors adapt automatically:
| Property | Light Mode | Dark Mode |
|---|---|---|
FigureColor |
[1 1 1] |
MATLAB's defaultFigureColor |
ForegroundColor |
[0 0 0] |
[1 1 1] |
BackgroundColor |
[1 1 1] |
MATLAB's defaultAxesColor |
ZeroLineColor |
[0 0 0] |
[0.8 0.8 0.8] |
DimColor |
[0.4 0.4 0.4] |
[0.65 0.65 0.65] |
GridColor |
[0.5 0.5 0.5] |
[0.55 0.55 0.55] |
LegendBgColor |
[1 1 1] |
MATLAB's defaultAxesColor |
LegendTextColor |
[0 0 0] |
[1 1 1] |
LegendEdgeColor |
[0.5 0.5 0.5] |
[0.5 0.5 0.5] |
Theme Control:
% Check if dark mode is active
tf = pf2_base.plot.PlotStyle.isDarkMode();
% Force light mode regardless of MATLAB theme (persistent preference)
pf2_base.plot.PlotStyle.setForceLightMode(true);
% Re-enable theme detection
pf2_base.plot.PlotStyle.setForceLightMode(false);Semantic colors (biomarker red/blue, significance markers, group colors) are unaffected by theme. Saved figures always export with a white background and dark text.
| Function | Purpose |
|---|---|
fitLME.m |
Standalone channel-wise LME fitting (fNIRS, ROI, Aux; no visualization) |
fitInfoLME.m |
Fit an LME for an info/behavioral variable |
autoModelLME.m |
Automatic per-channel LME model selection via forward stepwise information criteria |
runContrasts.m |
Post-hoc contrasts with FDR correction across channels |
buildContrasts.m |
Generate standard contrast matrices from a fitted LME model |
summarize.m |
Publication-ready summary tables (ANOVA, contrasts, coefficients, fit, APA) |
permTest.m |
Non-parametric permutation test for paired comparisons |
clusterPermutation.m |
Cluster-based permutation testing across channels |
findClusters.m |
Find spatially contiguous clusters in a thresholded stat map |
effectSize.m |
Effect size with bootstrap confidence intervals |
behavioralTable.m |
Descriptive stats, comparisons, or correlations for behavioral data |
| Function | Purpose |
|---|---|
computeMatrix.m |
Compute channel-pair connectivity matrices (symmetric or directed) |
alignMatrices.m |
Align connectivity/hyperscanning results from subjects with different channels into a common grid. Modes: 'union', 'intersection', numeric threshold |
computeDynamicFC.m |
Sliding-window dynamic functional connectivity → 3D tensor |
detectStates.m |
K-means clustering of dynamic FC matrices into brain states |
computeIntraROI.m |
Within-ROI pairwise coupling analysis |
computeInterROI.m |
Between-ROI coupling (wrapper with UseROI=true) |
computeBetaSeries.m |
Beta-series correlation connectivity (LSA or LSS estimation, condition filtering) |
computePPI.m |
Psychophysiological interaction analysis (gPPI, contrast specification, Wiener deconvolution) |
plotMatrix.m |
Visualize connectivity matrices |
plotBlockComparison.m |
Compare connectivity across blocks |
plotDirected.m |
Directed connectivity visualization (matrix heatmap or circular arc diagram) |
plotDynamicFC.m |
Dynamic FC time series with brain state visualization |
plotChord.m |
Chord diagram / connectogram for ROI/channel connectivity (per-node coloring + colorbar, region anchors, uniform edges) |
plotIntraROI.m |
Intra-ROI bar/radar visualization |
plotInterROI.m |
Inter-ROI chord/matrix visualization |
Brain-anchored network rendering (edges drawn at real channel/ROI positions on the cortex/probe) is provided by
pf2.probe.plot.connectome.
| Function | Purpose |
|---|---|
pearson.m |
Pearson correlation |
spearman.m |
Spearman rank correlation |
xcorr.m |
Cross-correlation |
coherence.m |
Magnitude-squared coherence |
wcoherence.m |
Wavelet coherence |
granger.m |
Granger causality (directed, AR model F-test) |
transferEntropy.m |
Transfer entropy (directed, histogram-based with surrogate p-values) |
hbica.m |
HB-ICA pairwise coupling adapter (product-of-normalized-weights for 2-channel case) |
partialCorr.m |
Partial correlation (controls for confounds; precision-matrix batch in computeMatrix) |
mutualInfo.m |
Mutual information (histogram-based, normalized, surrogate p-values) |
partialCoherence.m |
Partial magnitude-squared coherence controlling for one or more shared signals (e.g. shared physiology) |
plotWcoherence.m |
Wavelet coherence time-frequency heatmap |
plotWindowed.m |
Windowed coupling time series |
| Function | Purpose |
|---|---|
pairSubjects.m |
Pair subjects by matching criteria |
computeDyad.m |
Compute coupling for dyads (supports all 8 coupling methods) |
computeGroup.m |
Group-level statistics with SEM; supports 'Align' for unbalanced channels |
permutationTest.m |
Permutation-based significance testing; supports 'Align' for unbalanced channels |
hbica.m |
HB-ICA decomposition for a dyad (TDSEP ICA + GOF classification, dual regression, UseROI support) |
plotGroup.m |
Group bar chart with significance markers |
plotHBICA.m |
HB-ICA visualization (GOF bar chart, dual-brain spatial patterns, source time courses) |
plotInterBrainTopo.m |
Dual-brain topographic display with coupling lines (synthetic grid) |
plotDualBrain.m |
Dual-brain inter-brain synchrony at real 2D probe geometry, cross-brain edges + optional linked wavelet panel |
plotDyadMatrix.m |
Dyad-level coupling heatmap (channels × dyads) |
plotGroupTemporal.m |
Time-resolved group coupling with SEM error bands |
physioConfoundQC.m |
Flag shared-physiology (LFO/VLFO) confound risk for a hyperscanning dyad |
Network metrics computed on a connectivity matrix (from +connectivity).
| Function | Purpose |
|---|---|
threshold.m |
Convert a connectivity matrix to a graph struct for analysis |
computeMetrics.m |
Compute the full suite of graph-theory metrics from a connectivity matrix |
degree.m |
Node degree and strength |
clusteringCoefficient.m |
Weighted clustering coefficient and transitivity |
charPathLength.m |
Characteristic path length and distance matrix |
efficiency.m |
Global and local network efficiency |
betweenness.m |
Betweenness centrality per node |
modularity.m |
Community detection via the Louvain algorithm |
smallWorld.m |
Small-world indices vs random null networks |
detectHubs.m |
Identify hub nodes via composite z-score |
metricsToTable.m |
Export graph metrics to a long-format table |
plotMetrics.m |
Grouped bar chart comparing node-level metrics |
plotNetwork.m |
Node-link diagram with metric-based sizing and community coloring |
Publication-ready tables and HTML report assembly.
| Function | Purpose |
|---|---|
Pipeline.m |
Orchestrator for reproducible report generation |
generate.m |
Create an HTML report from Pipeline results |
anovaTable.m |
Formatted ANOVA table (df, F, p, partial η²) |
contrastTable.m |
Formatted contrast table with significance stars and CI |
correlationTable.m |
Formatted correlation matrix with significance stars |
demographicsTable.m |
Publication "Table 1" demographics summary |
connectivitySummary.m |
Summary statistics from connectivity analysis |
formatStats.m |
APA-style statistical result string from LME/GLM output |
formatPValue.m |
APA-style p-value formatting |
toLatex.m |
Convert a MATLAB table to a LaTeX tabular string |
saveFigureSet.m |
Batch-save a struct of figure handles with consistent naming |
| Function | Purpose |
|---|---|
performFDR.m |
Benjamini-Hochberg FDR correction for multiple comparisons |
performFDR_twostep.m |
Two-step adaptive FDR (Benjamini-Krieger-Yekutieli 2006) |
autoContrast.m |
Automatic contrast generation for LME models |
FDR Correction Methods:
- Standard FDR (
performFDR): Classic Benjamini-Hochberg (1995) procedure. Controls expected proportion of false discoveries. Returns q-values and the critical index k. - Two-step Adaptive FDR (
performFDR_twostep): More powerful when many null hypotheses are true. Estimates π₀ (proportion of true nulls) in first pass, then adjusts threshold in second pass.
| Function | Purpose |
|---|---|
temporal.m |
Time-series plots with shaded error regions |
barchart.m |
Grouped bar charts with error bars, violin plots, LME analysis |
scatter.m |
Correlation scatter plots with regression lines, topographic maps |
Bar Chart Features:
- Error bar options: SEM, SD, MaxMin, IQR, IQR-NoOutliers, Violin
- Automatic LME model fitting with Satterthwaite degrees of freedom
- Topographic display of ANOVA F-statistics across probe
- Individual data point overlay
- Console output of fitted model statistics
Scatter Plot Features:
- Pearson and Spearman correlation options
- Regression lines with confidence/prediction intervals (SEM, SD, 95%CI, 95%PI)
- Topographic correlation maps with FDR correction
- Hierarchical averaging for within-subject designs
| Function | Purpose |
|---|---|
mergeGbyTablesLong.m |
Export to long format (one row per observation/timepoint) |
mergeGbyTablesWide.m |
Export to wide format (one row per subject) |
Long Format - Preferred for:
- R mixed-effects models (lme4, lmerTest)
- tidyverse/ggplot2 visualization
- Repeated measures with multiple timepoints
Wide Format - Preferred for:
- SPSS repeated measures ANOVA
- Excel pivot tables
- Simple between-subjects comparisons
exploreFNIRS uses the ExFNIRS global variable to maintain GUI state:
ExFNIRS =
data: [cell array] % Loaded fNIRS data structs
settings: [struct] % Current GUI settings
curMethodName: [string] % Active processing method
statusGroupByStr: [string] % Current grouping description
dataHierarchy: [cell] % Within-subject hierarchy variables
currentROI: [table] % Active ROI definitions
figHandles: [struct] % Figure handle references
curChartModels: [cell] % Fitted LME models (populated by barchart)
curChartModelsANOVA: [cell] % ANOVA tables for each model
curChartModelsCoefficents_pval: [table] % p-values by channel/biomarker
curChartModelsANOVACoefficents_Fstat: [table] % F-statisticsThe exGby structure array (passed to plotting functions) contains grouped data:
exGby(i) =
gbyTables: [table] % Subject-level metadata and variables
gbyGrandBar: [struct] % Grand average with summary statistics
.time: [vector] % Time points
.segmentTimes: [Tx3] % [start, middle, end] for each segment
.HbO/.HbR/etc: [struct] % Biomarker data
.data: [TxCxN] % Raw values (time x channel x observation)
.Mean: [TxC] % Mean across observations
.SEM: [TxC] % Standard error
.SD: [TxC] % Standard deviation
.N: [TxC] % Sample size
.ROI: [struct] % ROI-averaged data (if computed)
.Aux: [struct] % Auxiliary data (if present)
.info: [struct] % Hierarchy and observation metadata
gbyFNIRS_blk: [cell] % Block-level fNIRS structspf2_Intensity2OD.m- Convert raw intensity to optical density (log10)
| Function | Purpose |
|---|---|
pf2_lpf.m |
Low-pass Butterworth filter |
pf2_hpf.m |
High-pass Butterworth filter |
pf2_bpf_butter.m |
Band-pass Butterworth filter |
pf2_bpf_fir.m |
Band-pass FIR filter |
pf2_bpf_iir.m |
Butterworth IIR bandpass/lowpass/highpass filter with NaN handling |
pf2_bandstop.m |
Band-stop filter |
detrend_nan.m |
Detrending with NaN handling |
detrend_3rd_order.m |
Third-order polynomial detrending |
| Function | Purpose |
|---|---|
pf2_SMAR.m |
Sliding Motion Artifact Rejection |
pf2_SMAR2.m |
SMAR v2.0 (improved algorithm) |
pf2_SMAR2_mask.m |
SMAR2 with masking |
pf2_fnirs_MARA.m |
Movement Artifact Reduction Algorithm |
pf2_MotionCorrectTDDR.m |
Temporal Derivative Distribution Repair |
pf2_MotionCorrectSpline.m |
Spline interpolation motion correction |
pf2_MotionCorrectSplineSG.m |
Spline interpolation with Savitzky-Golay smoothing |
pf2_MotionCorrectWavelet.m |
Wavelet-based motion correction |
| Function | Purpose |
|---|---|
pf2_CAR.m |
Common Average Reference |
pf2_GSR.m |
Global signal removal via PCA spatial filter (tunable CAR generalization) |
pf2_subtractAmbient.m |
Subtract dark/ambient channel |
applyTimeChMask.m |
Apply channel mask across time |
pf2_ambient_ICA_clean.m |
ICA-based ambient channel removal |
icaClean.m |
Independent component analysis cleaning |
waveClean.m |
Wavelet-based cleaning |
| Function | Purpose |
|---|---|
pf2_thresholdValues.m |
Threshold outlier values |
pf2_thresholdValues_mask.m |
Threshold with masking |
pf2_TakizawaRejection.m |
Takizawa artifact criterion (on processed Hb data) |
pf2_SCIRejection.m |
SCI-based channel rejection (on raw intensity data) |
pf2_SSR.m |
Short separation regression processing function |
| Function | Purpose |
|---|---|
pf2_build_nanmean_ROI.m |
ROI from mean of channels |
pf2_build_pca_ROI.m |
ROI from PCA components |
fNIR_Devices_fNIR1000.cfg- fNIR 1000fNIR_Devices_fNIR1000_LD.cfg- fNIR 1000 (long-distance optode spacing)fNIR_Devices_fNIR1000_Linear.cfg- fNIR 1000 linear arrayfNIR_Devices_fNIR1000_Split_2x2ch.cfg- fNIR 1000 split configurationfNIR_Devices_fNIR1200_16ch.cfg- fNIR 1200 (16 channels)fNIR_Devices_fNIR2000.cfg- fNIR 2000fNIR_Devices_fNIR2000_18ch.cfg- fNIR 2000 (18 channels)fNIR_Devices_fNIR3000.cfg- fNIR 3000
Hitachi_ETG4000_3x5.cfg- 3x5 probe configurationHitachi_ETG4000_3x11.cfg- 3x11 probe configurationfNIR_Hitachi_3x5_merged.cfg- Merged Hitachi 3x5
NIRX_Sport_8x8_frontal.cfg- 8x8 frontal configurationNIRX_Sport_16x16_parietal.cfg- 16x16 parietal configurationNIRX_Sport_16x16_lw.cfg- 16x16 lightweight version
- No
.cfgfile: device geometry is read per-recording from the.oxy3header (sampling rate, lasers/wavelengths, detector and ADC counts). - Optode positions are not stored in the
.oxy3(OxySoft references an external optode template by ID).importOxy3generates a placeholder layout by default; pass'OptodeTemplate', 'optodetemplates.xml'to recover real 2D optode coordinates for the recording'sOptodeTemplateID. - Supports both newer (
<SampleRate>) and older (<SampleTime>-only) OxySoft schemas, dual-wavelength (≈760/850 nm) systems, and OxyMon/OctaMon-class montages where disconnected source–detector combinations are imported and then flagged by the saturation quality check.
Rogue_BrainSight.cfg- Rogue/BrainSight systemDrP_probe.cfg- Custom DrP probe
[Info]
CfgName = 'Device_Name'
Name = 'Display Name'
Manufacturer = 'Manufacturer'
DefaultSamplingRate = 10 % Hz
NumberChannels = 18
TimeIsSampleCount = 0
[Probe1]
ChannelNumbers = [...] % Channel indices
Wavelength = [...] % Wavelengths in nm
DetPosX, DetPosY, DetPosZ % Detector 2D positions
SrcPosX, SrcPosY, SrcPosZ % Source 2D positions
DetPos3DX, etc. % 3D detector positions (Talairach/MNI)
SrcPos3DX, etc. % 3D source positions
sI = [...] % Source indices per channel
dI = [...] % Detector indices per channel| Variable | Description |
|---|---|
PF2 |
Processing settings and loaded methods |
setF |
Device/file information |
outputData |
Processing stage control |
| Extension | Format | Import Function |
|---|---|---|
.nir |
fNIR Devices/Biopac | pf2.import.importNIR |
.hdr/.wl1/.wl2 |
NIRx | pf2.import.importNIRX |
.csv |
Hitachi ETG-4000 | pf2.import.importHitachiMES |
.snirf |
SNIRF standard | pf2.import.importSNIRF |