Metadata-Version: 2.5
Name: personality_questionnaire
Version: 2.1.0
Summary: Administer, score and record validated personality and affect questionnaires.
Project-URL: Documentation, https://fodorad.github.io/personality_questionnaire/
Project-URL: Issues, https://github.com/fodorad/personality_questionnaire/issues
Project-URL: Source, https://github.com/fodorad/personality_questionnaire
Author-email: fodorad <fodorad201@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: bfi-2,big five,personality,psychometrics,questionnaire,vas-f
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.12
Requires-Dist: numpy
Provides-Extra: analysis
Requires-Dist: matplotlib; extra == 'analysis'
Requires-Dist: scipy>=1.18.1; extra == 'analysis'
Provides-Extra: dev
Requires-Dist: coverage; extra == 'dev'
Requires-Dist: pre-commit; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Requires-Dist: ty; extra == 'dev'
Provides-Extra: docs
Requires-Dist: furo; extra == 'docs'
Requires-Dist: myst-parser; extra == 'docs'
Requires-Dist: sphinx-autoapi; extra == 'docs'
Requires-Dist: sphinx-autobuild; extra == 'docs'
Requires-Dist: sphinx>=9.1.0; extra == 'docs'
Provides-Extra: mysql
Requires-Dist: pymysql>=1.1; extra == 'mysql'
Provides-Extra: ui
Requires-Dist: nicegui>=2.0; extra == 'ui'
Requires-Dist: sqlalchemy>=2.0.52; extra == 'ui'
Description-Content-Type: text/markdown

<div align="center">

<!-- PNG, not the SVG: PyPI strips SVG from project descriptions, so an SVG
     logo silently vanishes there while rendering fine on GitHub. The SVG is
     the source of truth and is used by the docs site and the application. -->
<img src="https://raw.githubusercontent.com/fodorad/personality_questionnaire/main/docs/assets/logo.png" alt="personality_questionnaire" width="112"/>

**Administer, score and record validated personality and affect questionnaires.**

[![GitHub Release](https://img.shields.io/github/v/release/fodorad/personality_questionnaire?color=purple)](https://github.com/fodorad/personality_questionnaire/releases)
[![PyPI](https://img.shields.io/pypi/v/personality_questionnaire?color=purple)](https://pypi.org/project/personality_questionnaire/)
[![CI](https://github.com/fodorad/personality_questionnaire/workflows/CI/badge.svg)](https://github.com/fodorad/personality_questionnaire/actions)
[![Coverage](https://codecov.io/gh/fodorad/personality_questionnaire/branch/main/graph/badge.svg)](https://codecov.io/gh/fodorad/personality_questionnaire)
[![Docs](https://img.shields.io/badge/docs-online-blue?logo=githubpages)](https://fodorad.github.io/personality_questionnaire/)
<br/>
[![Python](https://img.shields.io/badge/python-3.12%7C3.13%7C3.14-3776AB?logo=python&logoColor=white)](https://www.python.org)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000)](https://github.com/astral-sh/ruff)
[![License](https://img.shields.io/badge/license-MIT-yellow)](LICENSE)

</div>

---

# What this is

Collecting validated self-reports is the unglamorous half of an affective-computing
pipeline. This package administers published psychometric instruments, scores them
correctly, and records every response with the provenance needed to reproduce the
score months later.

It is built around one idea: **an instrument is data, not code.** Items, response
ranges, subscale membership and reverse keys are declared as values; a single
vectorised scorer turns responses into scores without knowing which questionnaire it
is holding. Adding an instrument adds no arithmetic.

# Instruments

| Key | Instrument | Items | Scale | Scores |
| --- | --- | --- | --- | --- |
| `bfi2` | Big Five Inventory-2 | 60 | 1–5 | 5 domains, 15 facets |
| `bfi2-xs` | BFI-2 Extra-Short Form | 15 | 1–5 | 5 domains |
| `bfi10` | Big Five Inventory-10 | 10 | 1–5 | 5 domains |
| `vasf` | Visual Analogue Scale to Evaluate Fatigue Severity | 18 | 0–10 | Fatigue, Energy, composite |

<sub>BFI-2 and BFI-2-XS: Soto & John (2017). BFI-10: Rammstedt & John (2007). VAS-F:
Lee, Hicks & Nino-Murcia (1991). See [docs/instruments.md](docs/instruments.md) for
full citations and licence notes.</sub>

# Quickstart

Score responses you already have:

```bash
pip install personality_questionnaire
```

```python
import personality_questionnaire as pq

result = pq.score(pq.get("bfi2"), answers)  # answers: (n_participants, 60)
result.by_level("domain")  # {"openness": array([...]), ...}
result.as_dict()  # one participant, every subscale
```

Administer one at the terminal:

```bash
pq list                                  # what is available
pq info bfi2                             # items, subscales, citation
pq run bfi2 --participant P01            # ask the questions, score the answers
pq score bfi2 --input answers.csv        # score a file
```

# How it works

```mermaid
flowchart LR
    I["instruments/<br/><i>pure data</i>"] --> R[registry]
    R --> S["scoring<br/><i>one vectorised scorer</i>"]
    S --> C[cli]
    S --> D[db]
    S --> U[ui]
```

| Module | Responsibility |
| --- | --- |
| `registry.py` | `Item`, `Subscale`, `Questionnaire` — what an instrument *is*, plus validation |
| `instruments/` | One module per questionnaire. Data only, no arithmetic |
| `scoring.py` | The single scorer: reverse-keying, subscale means, normalisation, pre/post deltas |
| `io.py` | Reading and writing responses and scores |
| `provenance.py` | Package version, git SHA, instrument hash for each record |
| `cli/` | `pq list \| info \| run \| score` |

# Design decisions

**Instruments are Python literals, not data files.** A literal is checked by the type
checker, validated at import, and present in the wheel by construction. A shipped CSV
is checked by nothing until a participant has already answered every item — and the
two scale files this repo used to carry were never read by any code path *and*
misspelled `neuroticism`, which is exactly how unread data drifts.

**Reverse-keying belongs to the subscale, not the item.** The VAS-F scores its five
energy items forward in `Energy` and reversed in `Fatigue (composite)`, so a per-item
mask cannot express both. The reflection is folded into a signed weight matrix, which
also means every subscale at every level is computed by one matrix multiplication.

**Both hierarchy levels are declared flat.** The BFI-2's five domains and fifteen
facets are siblings, each listing its own item numbers, rather than domains being
composed from facets. The arithmetic is identical and the flat form scores both
levels in a single pass.

**Polarity is recorded as data.** Every subscale carries a `higher_is` string, so no
consumer has to infer direction from a name — the inference that produced the bug
below.

# Development

```bash
make dev          # install everything
make fix          # format and autofix
make check        # lint, type-check, test, docs -- mirrors CI
make check-ci     # the same, in a throwaway venv built like CI's
```

Tests are `unittest` under `coverage`, mirroring the package layout in `tests/`.

# Related work

[PersonalityLinMulT](https://github.com/fodorad/PersonalityLinMulT) predicts perceived
Big Five traits from video. This package sits on the other side of that problem: it
collects *self-reported* ground truth, on the same `[0, 1]` scale and in the same
`openness, conscientiousness, extraversion, agreeableness, neuroticism` column order,
so an exported BFI-2 record drops into a self-report-versus-perception comparison.
The two are deliberately uncoupled in code — this package has no ML dependencies.

# Citation

```bibtex
@software{fodor_personality_questionnaire,
  author = {Fodor, Ádám},
  title  = {personality_questionnaire: administering and scoring validated psychometric instruments},
  url    = {https://github.com/fodorad/personality_questionnaire},
}
```

# Contact

* Ádám Fodor (fodorad201@gmail.com) — [adamfodor.com](https://adamfodor.com)
