A Python port of the R package sensR for Thurstonian models in sensory discrimination analysis.
sensPy provides a comprehensive Python implementation of sensR, the R package for sensory discrimination methods. This project ensures:
- Numerical parity with sensR (validated against R outputs)
- Modern Python practices (type hints, dataclasses, NumPy/SciPy integration)
- Full test coverage with 500+ tests
# Install with pip
pip install senspy
# Or install from source
git clone https://github.com/aigorahub/sensPy.git
cd sensPy
pip install -e .All standard protocols with single and double variants:
| Protocol | Single | Double |
|---|---|---|
| Triangle | ✅ | ✅ |
| Duo-Trio | ✅ | ✅ |
| 2-AFC | ✅ | ✅ |
| 3-AFC | ✅ | ✅ |
| Tetrad | ✅ | ✅ |
| Hexad | ✅ | - |
| 2-out-of-5 | ✅ | - |
discrim()- D-prime estimation with confidence intervals and p-valuesbetabin()- Beta-binomial model for overdispersed datatwoac()- 2-Alternative Certainty modelsamediff()- Same-different modeldod()- Degree-of-difference modelanota()- A-not-A signal detection model
discrim_power(),dprime_power()- Power analysisdiscrim_sample_size(),dprime_sample_size()- Sample size calculationsamediff_power()- Same-different power (simulation-based)twoac_power()- 2-AC exact powerdod_power()- DOD power analysis
dprime_test()- Test d-prime hypothesesdprime_compare()- Compare d-primes across groupsposthoc()- Post-hoc pairwise comparisons
roc()- ROC curve computationauc()- Area under the ROC curvesdt()- Signal detection theory transforms
discrim_sim()- Simulate discrimination experimentssamediff_sim()- Simulate same-different datadod_sim()- Simulate DOD data
plot_psychometric()- Psychometric functionsplot_roc()- ROC curvesplot_power_curve()- Power curvesplot_profile_likelihood()- Profile likelihood
from senspy import discrim, discrim_power
# Analyze a Triangle test result (80 correct out of 100)
result = discrim(correct=80, total=100, method="triangle")
print(f"d-prime: {result.d_prime:.3f}")
print(f"95% CI: [{result.ci_lower:.3f}, {result.ci_upper:.3f}]")
print(f"p-value: {result.p_value:.4g}")
# Calculate power for a future test
power = discrim_power(d_prime=1.5, sample_size=100, method="triangle")
print(f"Power: {power:.1%}")from senspy import samediff, dprime_compare
# Same-different analysis
sd = samediff(nsamesame=45, ndiffsame=5, nsamediff=20, ndiffdiff=30)
print(f"delta: {sd.delta:.3f}, tau: {sd.tau:.3f}")
# Compare d-primes across products
result = dprime_compare(
correct=[80, 65, 90],
total=[100, 100, 100],
method="triangle"
)
print(f"Chi-square: {result.statistic:.2f}, p={result.p_value:.4f}")Beta Release — sensPy is currently in beta. While we strive for numerical accuracy and validate results against the original sensR package, this software is provided "as is", without warranty of any kind. Aigora assumes no liability for any decisions, outcomes, or consequences arising from the use of this software. Users are responsible for independently verifying results before relying on them in production, regulatory, or research contexts.
This project is licensed under the GNU General Public License version 2.0 or later. See LICENSE for details.
If you use sensPy in your research, please cite:
@software{senspy,
title = {sensPy: Python port of sensR for Thurstonian models},
author = {Aigora},
year = {2025},
url = {https://github.com/aigorahub/sensPy}
}This package is a port of sensR by Per Bruun Brockhoff and Rune Haubo Bojesen Christensen.