Usage
Input format
All computation functions expect three parallel arrays of the same length, one row per trial:
| Argument | Values | Description |
|---|---|---|
stim |
0 or 1 | Stimulus category (0 = S1 / noise, 1 = S2 / signal) |
resp |
0 or 1 | Participant response (0 = "S1", 1 = "S2") |
conf |
1 … n_ratings | Confidence rating (1 = lowest, n_ratings = highest) |
n_ratings |
int | Total number of confidence categories |
Pure Python API (stdpy)
Compute all measures at once
import numpy as np
from metasignal import stdpy
rng = np.random.default_rng(42)
n, n_ratings = 200, 4
stim = rng.choice([0, 1], n)
resp = np.where(rng.random(n) < 0.78, stim, 1 - stim) # 78% accuracy
correct = stim == resp
conf = np.where(correct, rng.integers(2, n_ratings + 1, n),
rng.integers(1, n_ratings, n)) # higher conf when correct
results = stdpy.compute_all_measures(stim, resp, conf, n_ratings=n_ratings)
print(results)
The returned array has 26 elements: the first 20 are metacognitive/SDT measures, and the last 6 are meta-d' model-fit diagnostics (not measures themselves).
Pass return_type='dict' or return_type='dataframe' to get the same 26 values
labeled by measure name instead of by position (the default, 'array', is
unchanged and positional):
results = stdpy.compute_all_measures(stim, resp, conf, n_ratings=n_ratings, return_type="dict")
print(results["meta_d"], results["M_ratio"])
The canonical, ordered list of names is available as stdpy.MEASURE_NAMES.
Measures (indices 0-19):
| Index | Measure |
|---|---|
| 0 | meta-d' |
| 1 | AUC2 |
| 2 | gamma |
| 3 | phi |
| 4 | deltaConf |
| 5 | M-ratio |
| 6 | AUC2-ratio |
| 7 | gamma-ratio |
| 8 | phi-ratio |
| 9 | deltaConf-ratio |
| 10 | M-diff |
| 11 | AUC2-diff |
| 12 | gamma-diff |
| 13 | phi-diff |
| 14 | deltaConf-diff |
| 15 | metaNoise |
| 16 | metaUncertainty |
| 17 | d' |
| 18 | c |
| 19 | mean confidence |
Model-fit diagnostics (indices 20-25):
| Index | Diagnostic |
|---|---|
| 20 | logL (meta-d' MLE log-likelihood) |
| 21 | AIC |
| 22 | BIC |
| 23 | AICc |
| 24 | k (free parameters in the meta-d' fit) |
| 25 | n (trials used in the meta-d' fit) |
Compute individual measures
Basic SDT — d' and criterion c:
dprime, c, ln_beta = stdpy.compute_sdt_resp(stim, resp)
print(f"d' = {dprime:.3f}, c = {c:.3f}")
Convert trials to response counts:
nr_s1, nr_s2 = stdpy.trials_to_counts(stim, resp, conf, n_ratings=n_ratings)
Fit meta-d' via MLE:
nr_s1, nr_s2 = stdpy.trials_to_counts(stim, resp, conf, n_ratings=n_ratings)
result = stdpy.fit_meta_d_mle(nr_s1, nr_s2)
print(f"meta-d' = {result['meta_da']:.3f}")
print(f"M-ratio = {result['M_ratio']:.3f}")
Type-2 measures:
auc2 = stdpy.compute_type2_auc(nr_s1, nr_s2)
gamma = stdpy.compute_gamma(nr_s1, nr_s2)
phi = stdpy.compute_phi(nr_s1, nr_s2)
dc = stdpy.compute_delta_conf(nr_s1, nr_s2)
metaNoise and metaUncertainty:
noise = stdpy.compute_meta_noise(stim, resp, conf, n_ratings=n_ratings)
uncert = stdpy.compute_meta_uncertainty(stim, resp, conf, n_ratings=n_ratings)
Statistical inference (analysis)
The metasignal.analysis sub-package provides tools for running inference over the point estimates:
Bootstrap confidence intervals
import numpy as np
from metasignal.analysis import bootstrap_measure
rng = np.random.default_rng(42)
n, n_ratings = 200, 4
stim = rng.choice([0, 1], n)
resp = np.where(rng.random(n) < 0.78, stim, 1 - stim)
correct = stim == resp
conf = np.where(correct, rng.integers(2, n_ratings + 1, n),
rng.integers(1, n_ratings, n))
lo, hi = bootstrap_measure(
stim, resp, conf,
n_ratings=n_ratings,
measure_index=5, # M-ratio (index 5)
n_boot=2000,
ci=0.95,
)
print(f"M-ratio 95% CI: [{lo:.3f}, {hi:.3f}]")
Permutation test (two-condition comparison)
from metasignal.analysis import permutation_test
p_val, obs_diff = permutation_test(
stim_a, resp_a, conf_a,
stim_b, resp_b, conf_b,
n_ratings=2,
measure_index=5, # M-ratio
n_perm=5000,
)
print(f"p = {p_val:.4f}, observed difference = {obs_diff:.4f}")
Group-level summary
from metasignal.analysis import group_summary
# List of (stim, resp, conf) tuples — one per participant
participants = [(stim_p1, resp_p1, conf_p1), ...]
summary = group_summary(participants, n_ratings=2)
print(summary["mean"]) # (26,) array of group means
print(summary["sem"]) # (26,) array of standard errors
print(summary["labels"]) # list of 26 measure names
CLI
For quick exploratory use without writing Python:
metasignal compute \
--stim "0,1,0,1,1,0,1,0,0,1" \
--resp "0,1,1,1,1,0,0,0,0,1" \
--conf "2,3,1,4,4,3,2,1,3,4" \
--n-ratings 4
See CLI Reference for the full argument list.