Skip to main content

HRfunc

HRfunc is a Python library for estimating hemodynamic response functions and neural activity from hemoglobin concentration in functional near infrared spectroscopy (fNIRS), through modeling hemodynamic response functions through the brain recorded from fNIRS signals and deconvolving neural activity. Toeplitz deconvolution with Tikhonov regularization is employed for HRF and neural activity estimation. For more guidance on using the HRfunc tool, visit www.hrfunc.org for in-depth guides and demo videos.


Table of Contents


Features

  • ✅ HRF and neural activity estimation for fNIRS
  • ✅ Estimation through Toeplitz deconvolution with Tikhonov Reg.
  • ✅ Community sourced HRF estimates stored in the HRtree
  • ✅ Easy-to-use API compatible with MNE
  • ✅ Fast computations with NumPy + SciPy
  • ✅ Supports group-level aggregation
  • ✅ Neural activity estimation for block task and resting state scans
  • ✅ Native desktop GUI for point-and-click workflows (v1.3.0+)

Installation

You can easily install hrfunc via pip, as long as you have Python version 3.8 or higher.

pip install hrfunc

If you need to install Python, check out this great guide for installing it on your operating system -> https://realpython.com/installing-python/

To install the optional desktop GUI alongside the library:

pip install hrfunc[gui]

Desktop GUI

v1.3.0 ships a NiceGUI-based desktop app for researchers who prefer point-and-click over Python. The same library powers the GUI under the hood, so analyses produced from the GUI are equivalent to those from the programmatic API.

Launch the GUI:

hrfunc                          # opens the welcome screen
hrfunc /path/to/study           # preloads a folder of scans
hrfunc subject_01.snirf         # preloads a single scan

On first launch HRfunc offers to add itself to your system menu (Spotlight on macOS, Start menu on Windows, Activities on Linux) so you can open it without the terminal afterward. You can also run the install manually at any time:

hrfunc install-shortcut         # add HRfunc to your system menu
hrfunc uninstall-shortcut       # remove it

The workspace exposes seven tabs that mirror the analysis pipeline:

  1. Inspect — preview channel list, 2D probe layout, and event annotations for the selected scan.
  2. Preprocess — run preprocess_fnirs with the canonical pipeline (OD → SCI → bad-channel interpolation → TDDR → Beer-Lambert → baseline correct → bandpass) plus optional diagnostic toggles.
  3. HRFs — estimate per-channel HRFs via toeplitz deconvolution, or render an SPM-style canonical reference.
  4. Activity — deconvolve neural-activity time series from the preprocessed scan using either your estimated HRFs or the bundled canonical library.
  5. Quality — per-scan SNR / skewness / kurtosis / SCI metrics plus a dataset-wide aggregate that walks the full manifest.
  6. HRtree (/library) — plotly 3D scatter of the bundled literature HRF database, with a context filter sidebar (task, doi, study, demographics, stimulus, conditions) and a per-HRF detail pane with trace preview.
  7. Export — saves preprocessed Raw, activity Raw, montage HRFs JSON, per-channel HRF PNGs, and quality metrics CSV.

A 3-pane workspace with a BIDS-aware dataset tree on the left, tabbed analysis surface in the middle, and a manifest summary on the right.

For the full walkthrough — including installation troubleshooting, caching behavior, scan-mismatch guards, and tab-by-tab usage — see docs/external/gui_guide.md.


Quickstart

You can estimate channel-wise hemodynamic response functions and neural activity directly within your subjects fNIRS data through the hrfunc library. The hrfunc.montage() object orchestrates these estimations through 5 steps:

  1. Prepare your fNIRS and event data
  2. Initialize an HRfunc montage
  3. Estimate subject-level HRFs
  4. Calculate a subject-pool wide HRF distribution
  5. Estimate neural activity in each subjects scans

Watch a tutorial video here!

1. Preparing Data for HRfunc

HRfunc leverages the MNE Python libraries standard fNIRS scan objects to estimate HRFs and neural activity. To prepare you're data, simply load each raw fNIRS scan through MNE and create an event impulse timeseries representing when events occured in the scan.

# - - - -  1. Prepare Your fNIRS Data - - - - #
# Load in your raw fNIRS data through the MNE library
# and append to a list of scans for easy access and iteration

# NOTE: This is just an example of how you can load your fNIRS
# data and events, in the end all you need is fNIRS data loaded
# through MNE and a list of 0's and 1's representing when events
# occured during your scan.

import mne

# - Create a List of All of Your Subject Filepaths

scan_paths = ['path/to/sub-1.snirf', 
    'path/to/another/sub_2.snirf',
    'path/to/yet/another/sub_3.snirf']

# (Optional hack) use glob to grab them all! 

from glob import glob
# Use *, **, or ? (wildcards) to define ambiguous file patterns
scan_paths = glob("path/**/sub*.snirf") # and grab all your files in one pass

#  - Load Raw fNIRS Data through MNE -

raw_scans = []
for path in scan_paths: # Load through you're datatypes mne.io read call
    raw_scans.append(mne.io.read_raw_snirf(path)) # All MNE fNIRS formats will work


# - - - -  Prepare Your Events - - - - #
# Load/create a list of 0's and 1's representing when events occur
# in your fNIRS data. This list must be at most the same length

with open("task_events.txt", "r") as file:
    events = [int(line.split('/n')[0] for line in file.readlines()]

HRfunc Usage Example

Once you're data is loaded, you can start to estimate HRFs and neural activity through HRfunc!

# - - - - 2. Initialize an HRfunc montage - - - - #
# Pass in one of your scans into the hrf.montage() to intialize
# an HRF estimation node for each of your montages optodes.

import hrfunc as hrf

montage = hrf.montage(scan)


# - - - - 3. Estimate Subject Level HRFs - - - - #
# Pass each of your scans and their corresponding events
# into the estimate_hrfs() function to estimate subject level 
# channel-wise estimates.

for scan in raw_scans:
    montage.estimate_hrfs(scan, events, duration = 30.0)


# - - - - 4. Generate a Subject-Pool HRF Distribution - - - - #
# Generate channel-wise HRF estimates across the subject pool

montage.generate_distribution()
montage.save("study_HRFs.json")


# - - - - 5. Estimate Neural Activity - - - - # 
# Use the subject-pool wide HRF estimates to estimate
# channel wise neural activity for each subject

for scan in scans:
    # Estimate neural activity and replace in-place of the MNE object
    montage.estimate_activity(scan)

    # Save the scan
    scan.save(f"neural_activity_{scan.filename}")

After estimating HRF's and publishing a paper detailing how your dataset was collecting you can submit you're estimated HRFs to be added to the HRtree for the wider neuroimaging community to use in their own work. For guides on uploading neural activity, visit HRfunc.org/hrf_upload

HRtree Usage Example

WARNING: The HRtree is currently very limited in the HRF's available and you may need to estimate your own HRF's or rely on a canonical HRF for estimating neural activity

HRfunc can only estimate HRFs from fNIRS data with events occuring during the scan. In these situations you could skip straight to estimating neural activity and rely on a canonical HRF.

Alternatively you could search the HRtree for experimentally related HRF's! HRfunc's hybrid tree-hash table data structure has a number of useful functions to search for useful HRF's

# - - - - Localize HRFs with your Context of Interest - - - - #
import hrfunc as hrf

# Localize any HRF's within range that contain task and age requested
montage = hrf.localize_hrfs(scan, max_distance = 0.001, task = 'flanker', age = [5, 6, 7])

# - - - - Filter Again for Another Experimental Context - - - - #
montage = montage.branch(demographic = ["black", "women"])

# - - - - Further Filter the Montage by Percent Similarity - - - - #
# Filter for specifically HRF's that meet a similarity threshold (95% in this case)
montage.filter(similarity_threshold = 0.95)

# - - - - Estimate Neural Activity using Found HRFs - - - - #
# NOTE: Relies on canonical HRF for a given optode if no 
# HRF was found for the given optode/experimental context
for scan in raw_scans:
    montage.estimate_acivity(scan)

Documentation

For more comprehensive documentation on the tool, visit www.hrfunc.org.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

Distributed under the BSD-3 License. See LICENSE for details.

Citation

If you use hrfunc in your research, please cite:

Metadata

Release files for hrfunc 1.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hrfunc 1.3.1
File Size Uploaded
hrfunc-1.3.1.tar.gz 3.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for hrfunc 1.3.1
File Interpreter ABI Platform
hrfunc-1.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 6.7 MB

Release files / hrfunc-1.3.1.tar.gz

Download URL hrfunc-1.3.1.tar.gz
Size 3.4 MB
Tags Source
SHA-256 checksum
How to use checksums
d8198f1786a83d6f9ede791b945f0687c0086c4234d56c9cf7ffd0da6946090b
BLAKE2b-256 checksum
How to use checksums
6310032d8f5b69b02e27a9f3d6350ecf79b2c43a4ab81ac9bb589735fe080f22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / hrfunc-1.3.1-py3-none-any.whl

Download URL hrfunc-1.3.1-py3-none-any.whl
Size 3.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
88853c7d29c139ebad1c6524ec91250663b69a0b985d94426e0d6d2e27e8059e
BLAKE2b-256 checksum
How to use checksums
c1d1663efc848536d6edc32f4046ae35a2de1baad311277ed013fb98876872f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

1.3.1 This release

2 release files

1.3.0

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page