Skill Tracer
Skills › Scientific Agent Skills › neurokit2 › eda.md

eda.md

200 lines · skills/neurokit2/references/eda.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Electrodermal activity
2
3Checked **2026-10-01** against NeuroKit2 0.2.13 stable runtime/source,
4the official EDA API/examples, and Society for Psychophysiological Research guidance.
5

Electrodermal activity

Checked 2026-10-01 against NeuroKit2 0.2.13 stable runtime/source, the official EDA API/examples, and Society for Psychophysiological Research guidance.

Raw lines 1 to 5
6## Measurement contract
7
8Record:
9
10- conductance versus resistance, physical unit, range, and calibration;
11- constant-voltage/current system and electrode material/area;
12- palmar/plantar or other site, laterality, placement, and skin preparation;
13- sampling rate, hardware filters, temperature, humidity, acclimation, and movement;
14- missing/detached/saturated intervals; and
15- participant/task factors and response definition.
17Do not infer microsiemens from `EDA` or compare arbitrary sensor units with published
18µS thresholds. Sensor site, hardware, environment, and population require validation.

Measurement contract

Record:

  • conductance versus resistance, physical unit, range, and calibration;
  • constant-voltage/current system and electrode material/area;
  • palmar/plantar or other site, laterality, placement, and skin preparation;
  • sampling rate, hardware filters, temperature, humidity, acclimation, and movement;
  • missing/detached/saturated intervals; and
  • participant/task factors and response definition.

Do not infer microsiemens from EDA or compare arbitrary sensor units with published µS thresholds. Sensor site, hardware, environment, and population require validation.

Raw lines 6 to 19
20## Default stable pipeline
22```python
23signals, info = nk.eda_process(
24 eda,
25 sampling_rate=100,
26 method="neurokit",
28```
30In stable 0.2.13 the NeuroKit pipeline performs cleaning, **high-pass**
31tonic/phasic decomposition, and NeuroKit SCR detection. It does not use cvxEDA by
32default.
34The pinned default schema observed:
36```text
37EDA_Raw, EDA_Clean, EDA_Tonic, EDA_Phasic,
38SCR_Onsets, SCR_Peaks, SCR_Height, SCR_Amplitude,
39SCR_RiseTime, SCR_Recovery, SCR_RecoveryTime
40```
42`info` was a flat dict containing SCR arrays plus `sampling_rate`. Treat this as a
43default 0.2.13 observation, not a universal schema.
45There is no public `eda_quality()` in stable 0.2.13. Quality must combine acquisition
46metadata, missing/flat/clipped/motion checks, raw/clean overlays, decomposition
47plausibility, and response review.

Default stable pipeline

signals, info = nk.eda_process(
    eda,
    sampling_rate=100,
    method="neurokit",
)

In stable 0.2.13 the NeuroKit pipeline performs cleaning, high-pass tonic/phasic decomposition, and NeuroKit SCR detection. It does not use cvxEDA by default.

The pinned default schema observed:

EDA_Raw, EDA_Clean, EDA_Tonic, EDA_Phasic,
SCR_Onsets, SCR_Peaks, SCR_Height, SCR_Amplitude,
SCR_RiseTime, SCR_Recovery, SCR_RecoveryTime

info was a flat dict containing SCR arrays plus sampling_rate. Treat this as a default 0.2.13 observation, not a universal schema.

There is no public eda_quality() in stable 0.2.13. Quality must combine acquisition metadata, missing/flat/clipped/motion checks, raw/clean overlays, decomposition plausibility, and response review.

Raw lines 20 to 48
49## Make decomposition explicit
51```python
52clean = nk.eda_clean(eda, sampling_rate=100, method="neurokit")
53components = nk.eda_phasic(
54 clean,
55 sampling_rate=100,
56 method="highpass",
58```
60`eda_clean()` options include `neurokit`, `biosppy`, and `none`. The NeuroKit path
61uses a 3 Hz low-pass, and skips it below 7 Hz.
63`eda_phasic()` returns a DataFrame with `EDA_Tonic` and `EDA_Phasic`. Methods include:
65- `highpass`: default stable method; phasic high-pass separation;
66- `smoothmedian`: median-smoothed tonic estimate;
67- `cvxeda`: convex optimization; needs optional `cvxopt`;
68- `sparseda`: sparse decomposition.
70These methods estimate different latent components and are not interchangeable.
71Report method, all kwargs, optional dependency versions, convergence/failure behavior,
72and sensitivity. Do not call one decomposition “physiologically true” without
73appropriate validation.

Make decomposition explicit

clean = nk.eda_clean(eda, sampling_rate=100, method="neurokit")
components = nk.eda_phasic(
    clean,
    sampling_rate=100,
    method="highpass",
)

eda_clean() options include neurokit, biosppy, and none. The NeuroKit path uses a 3 Hz low-pass, and skips it below 7 Hz.

eda_phasic() returns a DataFrame with EDA_Tonic and EDA_Phasic. Methods include:

  • highpass: default stable method; phasic high-pass separation;
  • smoothmedian: median-smoothed tonic estimate;
  • cvxeda: convex optimization; needs optional cvxopt;
  • sparseda: sparse decomposition.

These methods estimate different latent components and are not interchangeable. Report method, all kwargs, optional dependency versions, convergence/failure behavior, and sensitivity. Do not call one decomposition “physiologically true” without appropriate validation.

Raw lines 49 to 74
75## SCR detection
77```python
78markers, peak_info = nk.eda_peaks(
79 components["EDA_Phasic"],
80 sampling_rate=100,
81 method="neurokit",
82 amplitude_min=0.1,
84```
86Stable methods include `neurokit`, `gamboa2008`, `kim2004`, `vanhalem2020`, and
87`nabian2018`. For `neurokit` and `kim2004`, `amplitude_min` is a fraction relative to
88the largest detector-specific candidate in the analyzed signal—not an absolute µS
89threshold. In stable source, `neurokit` thresholds peak prominence, whereas `kim2004`
90thresholds phasic peak height. Neither is a common absolute onset-to-peak amplitude
91cutoff. Other supported methods ignore `amplitude_min`.
93`eda_peaks()` returns `(signals, info)`:
95- marker/feature DataFrame: `SCR_Onsets`, `SCR_Peaks`, `SCR_Height`,
96 `SCR_Amplitude`, `SCR_RiseTime`, `SCR_Recovery`, `SCR_RecoveryTime`;
97- info dict: event-indexed arrays and sampling rate.
99Marker columns are same-length arrays; feature values are placed at relevant marker
100locations and are otherwise **zero**, not missing, in stable 0.2.13. Invalid feature
101values at a detected response can still be NaN. Use `info` for event-level arrays. Do not average
102same-length feature columns as if every sample were an independent response.
104`eda_fixpeaks()` is documented as a placeholder that does not currently correct EDA
105peaks.

SCR detection

markers, peak_info = nk.eda_peaks(
    components["EDA_Phasic"],
    sampling_rate=100,
    method="neurokit",
    amplitude_min=0.1,
)

Stable methods include neurokit, gamboa2008, kim2004, vanhalem2020, and nabian2018. For neurokit and kim2004, amplitude_min is a fraction relative to the largest detector-specific candidate in the analyzed signal—not an absolute µS threshold. In stable source, neurokit thresholds peak prominence, whereas kim2004 thresholds phasic peak height. Neither is a common absolute onset-to-peak amplitude cutoff. Other supported methods ignore amplitude_min.

eda_peaks() returns (signals, info):

  • marker/feature DataFrame: SCR_Onsets, SCR_Peaks, SCR_Height, SCR_Amplitude, SCR_RiseTime, SCR_Recovery, SCR_RecoveryTime;
  • info dict: event-indexed arrays and sampling rate.

Marker columns are same-length arrays; feature values are placed at relevant marker locations and are otherwise zero, not missing, in stable 0.2.13. Invalid feature values at a detected response can still be NaN. Use info for event-level arrays. Do not average same-length feature columns as if every sample were an independent response.

eda_fixpeaks() is documented as a placeholder that does not currently correct EDA peaks.

Raw lines 75 to 106
107## Missingness and artifacts
109EDA motion/electrode artifacts can resemble fast responses, while detachment can look
110flat. Before decomposition:
1121. inspect raw units, range, clipping, steps, flatlines, and missing runs;
1132. segment long discontinuities;
1143. annotate motion, temperature changes, and contact problems;
1154. avoid broad interpolation across SCR morphology; and
1165. keep an artifact/validity mask through epoching.
118Filtering cannot restore a detached or saturated channel. A low response count can be
119physiological, methodological, or a sensor failure; it is not automatically a
120“non-responder.”

Missingness and artifacts

EDA motion/electrode artifacts can resemble fast responses, while detachment can look flat. Before decomposition:

  1. inspect raw units, range, clipping, steps, flatlines, and missing runs;
  2. segment long discontinuities;
  3. annotate motion, temperature changes, and contact problems;
  4. avoid broad interpolation across SCR morphology; and
  5. keep an artifact/validity mask through epoching.

Filtering cannot restore a detached or saturated channel. A low response count can be physiological, methodological, or a sensor failure; it is not automatically a “non-responder.”

Raw lines 107 to 121
122## Event-related EDA
124Create epochs only after event and signal clocks are aligned:
126```python
127epochs = nk.epochs_create(
128 signals,
129 events,
130 sampling_rate=100,
131 epochs_start=-1,
132 epochs_end=10,
133 baseline_correction=False,
135features = nk.eda_eventrelated(epochs)
136```
138Stable event-related output is conditional on available columns. Documented features
139include `EDA_SCR`, first-response amplitude/time/rise/recovery fields, tonic/phasic
140summaries, labels, conditions, and event onset. Inspect `features.columns`.
142Prespecify response latency/window, overlap handling, baseline approach, minimum
143amplitude definition, non-response coding, and trial artifact rules. Slow responses can
144overlap adjacent events; a peak in a window is not automatically elicited by that event.

Event-related EDA

Create epochs only after event and signal clocks are aligned:

epochs = nk.epochs_create(
    signals,
    events,
    sampling_rate=100,
    epochs_start=-1,
    epochs_end=10,
    baseline_correction=False,
)
features = nk.eda_eventrelated(epochs)

Stable event-related output is conditional on available columns. Documented features include EDA_SCR, first-response amplitude/time/rise/recovery fields, tonic/phasic summaries, labels, conditions, and event onset. Inspect features.columns.

Prespecify response latency/window, overlap handling, baseline approach, minimum amplitude definition, non-response coding, and trial artifact rules. Slow responses can overlap adjacent events; a peak in a window is not automatically elicited by that event.

Raw lines 122 to 145
146## Interval analysis and sympathetic index
148```python
149features = nk.eda_intervalrelated(signals, sampling_rate=100)
150```
152The pinned official example showed six columns, including SCR count/amplitude,
153`EDA_Tonic_SD`, `EDA_Sympathetic`, `EDA_SympatheticN`, and
154`EDA_Autocorrelation`; output depends on duration and available columns.
156`eda_sympathetic()` supports `posada` and `ghiasi`, with a default 0.045–0.25 Hz
157band. Stable `posada` returns NaN when duration is **64 seconds or less**, despite a
158warning referring to 60 seconds. `ghiasi` uses 60-second STFT windows with 59-second
159overlap. The helper conservatively requires more than 64 seconds for either method;
160this is a software guard, not a universal validity threshold. Report exact usable
161duration, frequency band, estimator, normalization, and
162units. Do not turn this index into a direct clinical sympathetic-state measure.

Interval analysis and sympathetic index

features = nk.eda_intervalrelated(signals, sampling_rate=100)

The pinned official example showed six columns, including SCR count/amplitude, EDA_Tonic_SD, EDA_Sympathetic, EDA_SympatheticN, and EDA_Autocorrelation; output depends on duration and available columns.

eda_sympathetic() supports posada and ghiasi, with a default 0.045–0.25 Hz band. Stable posada returns NaN when duration is 64 seconds or less, despite a warning referring to 60 seconds. ghiasi uses 60-second STFT windows with 59-second overlap. The helper conservatively requires more than 64 seconds for either method; this is a software guard, not a universal validity threshold. Report exact usable duration, frequency band, estimator, normalization, and units. Do not turn this index into a direct clinical sympathetic-state measure.

Raw lines 146 to 163
164## Bounded pipeline
166```bash
167python skills/neurokit2/scripts/eda_pipeline.py \
168 --input deidentified.csv --column EDA --root . --deidentified \
169 --sampling-rate 100 --unit uS \
170 --clean-method neurokit --phasic-method highpass \
171 --peak-method neurokit --amplitude-min 0.1
172```
174The helper rejects missing/non-finite samples, records the observed schema, and makes
175decomposition/threshold semantics explicit.
177Only `neurokit` and `kim2004` apply `--amplitude-min`; the report marks it inactive
178for other detectors. Synthetic generation passes both duration and integer sample
179count: supplying `length` alone does not update NeuroKit2's default 10-second time
180axis, drift, or SCR placement. Flat/no-response inputs can raise a detector error;
181do not reinterpret that failure as a validated physiological zero-response count.

Bounded pipeline

python skills/neurokit2/scripts/eda_pipeline.py \
  --input deidentified.csv --column EDA --root . --deidentified \
  --sampling-rate 100 --unit uS \
  --clean-method neurokit --phasic-method highpass \
  --peak-method neurokit --amplitude-min 0.1

The helper rejects missing/non-finite samples, records the observed schema, and makes decomposition/threshold semantics explicit.

Only neurokit and kim2004 apply --amplitude-min; the report marks it inactive for other detectors. Synthetic generation passes both duration and integer sample count: supplying length alone does not update NeuroKit2's default 10-second time axis, drift, or SCR placement. Flat/no-response inputs can raise a detector error; do not reinterpret that failure as a validated physiological zero-response count.

Raw lines 164 to 182
Runs code python skills/neurokit2/scripts/eda_pipeline.py :167
183## Interpretation boundary
185EDA indexes eccrine sweat-gland activity under the recording conditions. It does not
186uniquely identify stress, emotion, deception, pain, diagnosis, or intent. Compare
187within a theory-driven design with contextual measures and validated preprocessing.
188Do not use this workflow for clinical/driver/workplace monitoring or medical-device
189validation.

Interpretation boundary

EDA indexes eccrine sweat-gland activity under the recording conditions. It does not uniquely identify stress, emotion, deception, pain, diagnosis, or intent. Compare within a theory-driven design with contextual measures and validated preprocessing. Do not use this workflow for clinical/driver/workplace monitoring or medical-device validation.

Raw lines 183 to 190
191## Sources checked 2026-10-01
193- [Official EDA API](https://neuropsychology.github.io/NeuroKit/functions/eda.html)
194- [Official SCR example](https://neuropsychology.github.io/NeuroKit/examples/eda_peaks/eda_peaks.html)
195- [Stable v0.2.13 EDA source](https://github.com/neuropsychology/NeuroKit/tree/v0.2.13/neurokit2/eda)
196- [SPR Ad Hoc Committee (2012), publication recommendations](https://doi.org/10.1111/j.1469-8986.2012.01384.x)
197- [Greco et al. (2016), cvxEDA](https://doi.org/10.1109/TBME.2015.2474131)
198- [NeuroKit2 main paper](https://doi.org/10.3758/s13428-020-01516-y)
200- [Stable `eda_simulate.py` implementation](https://github.com/neuropsychology/NeuroKit/blob/v0.2.13/neurokit2/eda/eda_simulate.py)

Sources checked 2026-10-01

  • [Stable eda_simulate.py implementation](https://github.com/neuropsychology/NeuroKit/blob/v0.2.13/neurokit2/eda/eda_simulate.py)
Raw lines 191 to 200