thermophysio
A Python library for extracting, analysing, and cross-correlating skin temperature time-series from FLIR thermal infrared camera recordings of human participants during psychophysiology experiments.
Overview
The pipeline extracts temperature signals from anatomically defined regions of interest (ROIs) on the face, scalp, and neck, then asks: does the difference in a thermal feature between two regions correlate with task activation?
Three camera configurations are supported:
| Camera | Landmark detector | Regions |
|---|---|---|
| Frontal (face-forward) | MediaPipe FaceLandmarker (468 landmarks) | 13 facial/neck ROIs |
| Back-of-head | YOLOv8 pose (ear keypoints) | 11 cranial/neck ROIs |
| Dual side-profile | YOLOv8 pose (eye, ear, nose) | 24 bilateral ROIs |
Installation
pip install thermophysio
MediaPipe and Ultralytics (YOLOv8) are installed as dependencies. YOLOv8 weights (yolov8n-pose.pt) are downloaded automatically on first use.
For development / editable install from source:
git clone https://github.com/RauwP/thermophysio
cd thermophysio
pip install -e .
Experiment Types
| Type | Experiments | Camera | Regions |
|---|---|---|---|
| Faces | Exp01–05, Exp08 | Back | 11 |
| GoNoGo | Exp06, Exp09, Exp11 | Frontal | 13 |
| Words | Exp07, Exp10, Exp12, Exp21 | Frontal | 13 |
| CORSI | Exp13–20 | Frontal | 13 |
| LogicalVsIllogical | Exp22–24 | Dual | 24 |
Workflow
Step 1 — Extraction (interactive, per session)
from thermophysio import extract_back, extract_frontal, extract_profile
# Back-of-head camera (Faces experiment)
extract_back(
img_dir="Experiments/Exp01-Faces",
out_dir="Calc_Experiments/Exp01-Faces",
model="yolov8n-pose.pt"
)
# Frontal camera (GoNoGo, Words, CORSI)
extract_frontal(
img_dir="Experiments/Exp06-GoNoGo",
out_dir="Calc_Experiments/Exp06-GoNoGo"
)
# Dual side-profile (LogicalVsIllogical)
extract_profile(
dir_a="Experiments/Exp22-LogicalVsIllogical/CamA",
dir_b="Experiments/Exp22-LogicalVsIllogical/CamB",
out_dir="Calc_Experiments/Exp22-LogicalVsIllogical",
model="yolov8n-pose.pt"
)
Each call opens a GUI for entering block timings, then processes all frames automatically. Outputs land in:
Calc_Experiments/Exp01-Faces/
raw/ session_meta.json + overlays/ + pixels/
stats.csv 10 features × all ROIs × all timepoints
stats_resampled.csv uniformly resampled at dt=5 s
analysis/
ccf_table.csv all (feature × pair) CCF results, ranked
top10_leaderboard.png top-10 bar chart with Bartlett CI
top10_ccf_grid.png 5×2 grid of top-10 full CCF curves
plots/ individual CCF plots + per-feature grids
If extraction was done separately into Processed_Experiments/, run only the analysis pipeline:
from thermophysio._pipeline import run_pipeline
run_pipeline(
raw_dir="Processed_Experiments/Exp01-Faces",
out_dir="Calc_Experiments/Exp01-Faces"
)
Step 2 — Meta-Analysis (post-hoc, across runs of same type)
python -m thermophysio.FLIR_Meta_Analysis \
Calc_Experiments/Exp01-Faces/analysis/ccf_table.csv \
Calc_Experiments/Exp02-Faces/analysis/ccf_table.csv \
Calc_Experiments/Exp03-Faces/analysis/ccf_table.csv \
Calc_Experiments/Exp04-Faces/analysis/ccf_table.csv \
Calc_Experiments/Exp05-Faces/analysis/ccf_table.csv \
Calc_Experiments/Exp08-Faces/analysis/ccf_table.csv \
--out Calc_Experiments/Meta_Faces \
--label "Faces" \
--min-runs 2
Outputs: leaderboard PNG, table PNG, full AI-readable markdown report.
Repository Structure
thermophysio/ Installable package
__init__.py Public API: extract_frontal / extract_back / extract_profile
_pipeline.py Orchestrator: build_csv → resample → analyse → summarise
Back_FLIR_Extractor.py YOLOv8 back-of-head pipeline
Frontal_FLIR_Extractor.py MediaPipe frontal pipeline
Dual_FLIR_Extractor.py YOLOv8 dual side-profile pipeline
FLIR_Stats_to_CSV.py NPZ → 10-feature stats CSV
FLIR_TimeSeries.py Irregular → uniform time resampling
FLIR_CrossROI_Analysis.py Bartlett-corrected CCF analysis + plots
FLIR_Top_Correlations.py Top-N leaderboard and CCF grid (per session)
FLIR_Meta_Analysis.py Fisher z meta-analysis across runs
FLIR_Delta_Analysis.py Pairwise Pearson delta analysis (alternative)
shared_utils.py Feature computation + CCF math
mesh_defs.json ROI polygon definitions (all 3 camera types)
mesh_loader.py JSON loader with GitHub download + local cache
editors/
back_mesh_editor.py GUI editor for back-of-head ROI mesh
frontal_mesh_editor.py GUI editor for frontal ROI mesh
profile_mesh_editor.py GUI editor for dual-profile ROI mesh (J = export)
docs/
assets/ Representative overlays + meta-analysis figures
REPORT.md Full technical report with math and results
Features Extracted per ROI
| Feature | Definition |
|---|---|
| mean | Mean pixel temperature (°C) |
| median | Median pixel temperature |
| max | Maximum pixel temperature |
| min | Minimum pixel temperature |
| variance | Sample variance (ddof=1) |
| energy | Mean squared temperature |
| entropy | Shannon entropy of 32-bin histogram (bits) |
| kurtosis | Excess kurtosis (Fisher definition) |
| skewness | Distribution skewness |
npixels (ROI size) is computed but excluded from correlation analysis.
Analysis Parameters
| Parameter | Default | Description |
|---|---|---|
dt |
5.0 s | Resampling grid spacing |
alpha |
0.05 | Bartlett CI and Fisher CI significance level |
max_lag |
n // 3 | Maximum CCF lag tested |
top_k |
9 | Pairs per feature in per-feature grid plots |
top_n |
10 | Pairs in global summary leaderboard |
min_runs |
1 | Minimum runs for meta-analysis inclusion |
Dependencies
- numpy, scipy, matplotlib
- opencv-python, Pillow
- mediapipe (frontal extraction)
- ultralytics (YOLOv8, back/dual extraction)
- flyr (FLIR radiometric JPEG parsing)
Data Availability
Raw recordings, extracted pixel data, and analysis outputs are archived on Zenodo:
The deposit contains three archives:
Experiments.zip— raw FLIR radiometric JPEGs, one folder per sessionProcessed_Experiments.zip— extracted pixel arrays (.npz), session metadata, and ROI overlay imagesCalc_Experiments.zip— per-session statistics CSVs, resampled time-series, CCF tables, and plots
See Also
docs/REPORT.md — full technical report covering coordinate geometry, feature math, statistical methods, and per-experiment results with figures.
Metadata
Release files for thermophysio 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| thermophysio-0.1.1.tar.gz | 107.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| thermophysio-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 221.9 kB
Release files / thermophysio-0.1.1.tar.gz
| Download URL | thermophysio-0.1.1.tar.gz |
|---|---|
| Size | 107.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
40cdd9741c1a6bc53d097643893be7a0b204ca6de071f585316e2e1a724140b3
|
|
BLAKE2b-256 checksum How to use checksums |
683b23403c9cae0b4b07f68db4d3dbf6fb68798c40adc2cef55d9ce675a4ce0d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.
Transparency logRelease files / thermophysio-0.1.1-py3-none-any.whl
| Download URL | thermophysio-0.1.1-py3-none-any.whl |
|---|---|
| Size | 114.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6be327e4d0b7ef48423c6bc409f0559c27f1eba11e91c357090e2de082ad0632
|
|
BLAKE2b-256 checksum How to use checksums |
f9e75f8709b3b6550d072ed5ab14ff48b9b9116e54b0a59902f3c5ae628f623c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.
Transparency log