adaptivetesting 1.0.1__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.github/workflows/python-test.yml +0 -3
- adaptivetesting-1.1.0/BREAKING_CHANGES.md +65 -0
- adaptivetesting-1.1.0/PKG-INFO +348 -0
- adaptivetesting-1.1.0/README.md +330 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/__init__.py +1 -1
- adaptivetesting-1.1.0/adaptivetesting/data/__csv_context.py +57 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/data/__init__.py +1 -1
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/data/__pickle_context.py +4 -4
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/implementations/__default_implementation.py +17 -6
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/implementations/__init__.py +1 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/implementations/__pre_test.py +1 -1
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/implementations/__semi_implementation.py +32 -14
- adaptivetesting-1.1.0/adaptivetesting/implementations/__test_assembler.py +231 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/math/__gen_response_pattern.py +7 -6
- adaptivetesting-1.1.0/adaptivetesting/math/__init__.py +1 -0
- adaptivetesting-1.1.0/adaptivetesting/math/estimators/__bayes_modal_estimation.py +121 -0
- adaptivetesting-1.1.0/adaptivetesting/math/estimators/__expect_a_posteriori.py +90 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/math/estimators/__functions/__bayes.py +1 -1
- adaptivetesting-1.1.0/adaptivetesting/math/estimators/__functions/__estimators.py +139 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/math/estimators/__init__.py +3 -1
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/math/estimators/__ml_estimation.py +28 -2
- adaptivetesting-1.1.0/adaptivetesting/math/estimators/__prior.py +94 -0
- adaptivetesting-1.1.0/adaptivetesting/math/estimators/__test_information.py +101 -0
- adaptivetesting-1.1.0/adaptivetesting/math/item_selection/__init__.py +2 -0
- adaptivetesting-1.1.0/adaptivetesting/math/item_selection/__maximum_information_criterion.py +55 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__adaptive_test.py +56 -31
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__init__.py +1 -1
- adaptivetesting-1.1.0/adaptivetesting/models/__misc.py +17 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__test_result.py +1 -1
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/services/__estimator_interface.py +13 -1
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/services/__init__.py +1 -0
- adaptivetesting-1.1.0/adaptivetesting/services/__item_selection_protocol.py +25 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/services/__test_results_interface.py +3 -3
- adaptivetesting-1.1.0/adaptivetesting/simulation/__init__.py +1 -0
- adaptivetesting-1.1.0/adaptivetesting/simulation/__simulation.py +152 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/tests/test_adaptive_test.py +14 -7
- adaptivetesting-1.1.0/adaptivetesting/tests/test_bayes_modal.py +89 -0
- adaptivetesting-1.0.1/adaptivetesting/tests/test_bayes_modal.py → adaptivetesting-1.1.0/adaptivetesting/tests/test_eap.py +6 -9
- adaptivetesting-1.1.0/adaptivetesting/tests/test_information_test.py +55 -0
- adaptivetesting-1.1.0/adaptivetesting/tests/test_item_selection.py +60 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/tests/test_pretest.py +1 -1
- adaptivetesting-1.1.0/adaptivetesting/tests/test_simulation.py +99 -0
- adaptivetesting-1.1.0/adaptivetesting/tests/test_standard_error.py +160 -0
- adaptivetesting-1.1.0/adaptivetesting/tests/test_test_assembler.py +204 -0
- adaptivetesting-1.1.0/docs/readme.md +32 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/source/conf.py +5 -4
- adaptivetesting-1.1.0/docs/source/data.rst +9 -0
- adaptivetesting-1.1.0/docs/source/implementations.rst +8 -0
- adaptivetesting-1.1.0/docs/source/math.rst +21 -0
- adaptivetesting-1.1.0/docs/source/models.rst +9 -0
- adaptivetesting-1.1.0/docs/source/services.rst +8 -0
- adaptivetesting-1.1.0/docs/source/simulation.rst +9 -0
- adaptivetesting-1.1.0/examples/basic.py +39 -0
- adaptivetesting-1.1.0/examples/real_world.py +102 -0
- adaptivetesting-1.1.0/profiler/profile_bm_beta_simu.py +49 -0
- adaptivetesting-1.1.0/profiler/profile_bm_normal_simu.py +48 -0
- adaptivetesting-1.1.0/profiler/profile_ml_simu.py +45 -0
- adaptivetesting-1.1.0/profiler/profile_sim_pool.py +42 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/pyproject.toml +17 -5
- adaptivetesting-1.1.0/requirements.txt +612 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/setup.cfg +1 -1
- adaptivetesting-1.1.0/uv.lock +1075 -0
- adaptivetesting-1.0.1/PKG-INFO +0 -90
- adaptivetesting-1.0.1/README.md +0 -76
- adaptivetesting-1.0.1/adaptivetesting/data/__sqlite_context.py +0 -73
- adaptivetesting-1.0.1/adaptivetesting/math/__init__.py +0 -3
- adaptivetesting-1.0.1/adaptivetesting/math/__standard_error.py +0 -60
- adaptivetesting-1.0.1/adaptivetesting/math/__test_information.py +0 -37
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__bayes_modal_estimation.py +0 -45
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__functions/__estimators.py +0 -133
- adaptivetesting-1.0.1/adaptivetesting/math/estimators/__prior.py +0 -47
- adaptivetesting-1.0.1/adaptivetesting/math/item_selection/__init__.py +0 -1
- adaptivetesting-1.0.1/adaptivetesting/simulation/__init__.py +0 -1
- adaptivetesting-1.0.1/adaptivetesting/simulation/__simulation.py +0 -75
- adaptivetesting-1.0.1/adaptivetesting/tests/test_code_examples.py +0 -22
- adaptivetesting-1.0.1/adaptivetesting/tests/test_information_test.py +0 -39
- adaptivetesting-1.0.1/adaptivetesting/tests/test_standard_error.py +0 -58
- adaptivetesting-1.0.1/adaptivetesting/tests/test_urrys_rule.py +0 -28
- adaptivetesting-1.0.1/code_examples/example_default.py +0 -76
- adaptivetesting-1.0.1/code_examples/example_psychopy.py +0 -116
- adaptivetesting-1.0.1/code_examples/example_semi.py +0 -77
- adaptivetesting-1.0.1/data/default/0.pickle +0 -0
- adaptivetesting-1.0.1/data/semi/0.pickle +0 -0
- adaptivetesting-1.0.1/docs_generation/source/data.rst +0 -19
- adaptivetesting-1.0.1/docs_generation/source/implementations.rst +0 -31
- adaptivetesting-1.0.1/docs_generation/source/math.rst +0 -77
- adaptivetesting-1.0.1/docs_generation/source/models.rst +0 -46
- adaptivetesting-1.0.1/docs_generation/source/services.rst +0 -18
- adaptivetesting-1.0.1/docs_generation/source/simulation.rst +0 -29
- adaptivetesting-1.0.1/requirements.txt +0 -552
- adaptivetesting-1.0.1/uv.lock +0 -1016
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.github/workflows/publish.yml +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.gitignore +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.gitlab-ci.yml +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.python-version +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.vscode/extensions.json +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/.vscode/settings.json +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/LICENSE +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/math/item_selection/__urrys_rule.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__algorithm_exception.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__item_pool.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__item_selection_exception.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/models/__test_item.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/tests/__init__.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/tests/test_generate_response_pattern.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/tests/test_load_test_items.py +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/adaptivetesting/tests/test_mle.py +0 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/Makefile +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/data.md +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/implementations.md +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/index.md +0 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/make.bat +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/math.md +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/models.md +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/services.md +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/simulation.md +0 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/source/_static/logo.svg +0 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/source/_static/main.css +0 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/source/index.rst +0 -0
- {adaptivetesting-1.0.1/docs_generation → adaptivetesting-1.1.0/docs}/source/tests.rst +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/docs/tests.md +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/images/default.svg +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/images/semi-adaptive.svg +0 -0
- {adaptivetesting-1.0.1 → adaptivetesting-1.1.0}/mypy.ini +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Breaking Changes in `adaptivetesting`
|
|
2
|
+
|
|
3
|
+
This document highlights breaking changes and updates in the `adaptivetesting` package, considering its structure, features, and potential impacts on users transitioning between versions.
|
|
4
|
+
|
|
5
|
+
## 1. Python Version Requirement
|
|
6
|
+
- **Updated Requirement**: Python version `>= 3.11` is now required. Users on Python 3.10 or earlier may experience compatibility issues.
|
|
7
|
+
|
|
8
|
+
## 2. Package Structure
|
|
9
|
+
- The package is organized into several key modules:
|
|
10
|
+
- **`adaptivetesting.models`**: Core classes including `AdaptiveTest`, `ItemPool`, and `TestItem`.
|
|
11
|
+
- **`adaptivetesting.implementations`**: Ready-to-use test implementations like `TestAssembler`.
|
|
12
|
+
- **`adaptivetesting.math`**: Mathematical functions for IRT, ability estimation, and item selection.
|
|
13
|
+
- **`adaptivetesting.simulation`**: Simulation framework and result management.
|
|
14
|
+
- **`adaptivetesting.data`**: Data management utilities for CSV and pickle formats.
|
|
15
|
+
- **`adaptivetesting.services`**: Abstract interfaces and protocols.
|
|
16
|
+
|
|
17
|
+
## 3. Key Features
|
|
18
|
+
- **Bayesian Methods**: Built-in support for Bayesian ability estimation with customizable priors.
|
|
19
|
+
- **Flexible Architecture**: Object-oriented design with abstract classes for easy extension.
|
|
20
|
+
- **Item Response Theory**: Full support for 1PL, 2PL, 3PL, and 4PL models.
|
|
21
|
+
- **Multiple Estimators**:
|
|
22
|
+
- Maximum Likelihood Estimation (MLE)
|
|
23
|
+
- Bayesian Modal Estimation (BM)
|
|
24
|
+
- Expected A Posteriori (EAP)
|
|
25
|
+
- **Item Selection Strategies**: Maximum information criterion and Urry's rule.
|
|
26
|
+
- **Simulation Framework**: Comprehensive tools for CAT simulation and evaluation.
|
|
27
|
+
- **Real-world Application**: Direct transition from simulation to production testing.
|
|
28
|
+
- **Stopping Criteria**: Support for standard error and test length criteria.
|
|
29
|
+
- **Data Management**: Built-in support for CSV and pickle data formats.
|
|
30
|
+
|
|
31
|
+
## 4. Installation Instructions
|
|
32
|
+
- Install from PyPI using pip:
|
|
33
|
+
```bash
|
|
34
|
+
pip install adaptivetesting
|
|
35
|
+
```
|
|
36
|
+
- For the latest development version:
|
|
37
|
+
```bash
|
|
38
|
+
pip install git+https://github.com/condecon/adaptivetesting
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 5. Requirements
|
|
42
|
+
- The following dependencies are required:
|
|
43
|
+
- Python >= 3.11
|
|
44
|
+
- NumPy >= 2.0.0
|
|
45
|
+
- Pandas >= 2.2.0
|
|
46
|
+
- SciPy >= 1.15.0
|
|
47
|
+
- tqdm >= 4.67.1
|
|
48
|
+
|
|
49
|
+
## 6. Documentation Updates
|
|
50
|
+
- Full documentation is available in the `docs/` directory:
|
|
51
|
+
- [API Reference](docs/readme.md)
|
|
52
|
+
- [Models Module](docs/adaptivetesting.models.md)
|
|
53
|
+
- [Math Module](docs/adaptivetesting.math.md)
|
|
54
|
+
- [Implementation Examples](docs/adaptivetesting.implementations.md)
|
|
55
|
+
- [Simulation Guide](docs/adaptivetesting.simulation.md)
|
|
56
|
+
|
|
57
|
+
## 7. Testing
|
|
58
|
+
- Comprehensive tests are included. Run them using:
|
|
59
|
+
```bash
|
|
60
|
+
python -m pytest adaptivetesting/tests/
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
**Action Required**: Users should review these changes and update their environments and workflows accordingly.
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adaptivetesting
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: adaptivetesting is a Python package that can be used to simulate and evaluate custom CAT scenarios as well as implement them in real-world testing scenarios from a single codebase
|
|
5
|
+
Project-URL: Homepage, https://github.com/condecon/adaptivetesting
|
|
6
|
+
Project-URL: Documentation, https://github.com/condecon/adaptivetesting/tree/main/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/condecon/adaptivetesting.git
|
|
8
|
+
Project-URL: Issues, https://github.com/condecon/adaptivetesting/issues
|
|
9
|
+
Author-email: Jonas Engicht <dev@condecon.de>
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: computerized-adaptive-testing,item-response-theory,psychology,statistics
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Requires-Dist: numpy>=2.0.0
|
|
14
|
+
Requires-Dist: pandas>=2.2.0
|
|
15
|
+
Requires-Dist: scipy>=1.15.0
|
|
16
|
+
Requires-Dist: tqdm>=4.67.1
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# adaptivetesting
|
|
20
|
+
|
|
21
|
+
<img src="/docs/source/_static/logo.svg" style="width: 100%">
|
|
22
|
+
</img>
|
|
23
|
+
|
|
24
|
+
**An open-source Python package for simplified, customizable Computerized Adaptive Testing (CAT) using Bayesian methods.**
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Key Features
|
|
28
|
+
|
|
29
|
+
- **Bayesian Methods**: Built-in support for Bayesian ability estimation with customizable priors
|
|
30
|
+
- **Flexible Architecture**: Object-oriented design with abstract classes for easy extension
|
|
31
|
+
- **Item Response Theory**: Full support for 1PL, 2PL, 3PL, and 4PL models
|
|
32
|
+
- **Multiple Estimators**:
|
|
33
|
+
- Maximum Likelihood Estimation (MLE)
|
|
34
|
+
- Bayesian Modal Estimation (BM)
|
|
35
|
+
- Expected A Posteriori (EAP)
|
|
36
|
+
- **Item Selection Strategies**: Kaximum information criterion and Urry's rule
|
|
37
|
+
- **Simulation Framework**: Comprehensive tools for CAT simulation and evaluation
|
|
38
|
+
- **Real-world Application**: Direct transition from simulation to production testing
|
|
39
|
+
- **Stopping Criteria**: Support for standard error and test length criteria
|
|
40
|
+
- **Data Management**: Built-in support for CSV and pickle data formats
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
Install from PyPI using pip:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install adaptivetesting
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For the latest development version:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install git+https://github.com/condecon/adaptivetesting
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- Python >= 3.10
|
|
59
|
+
- NumPy >= 2.0.0
|
|
60
|
+
- Pandas >= 2.2.0
|
|
61
|
+
- SciPy >= 1.15.0
|
|
62
|
+
- tqdm >= 4.67.1
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
### Basic Example: Setting Up an Adaptive Test
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from adaptivetesting.models import ItemPool, TestItem
|
|
70
|
+
from adaptivetesting.implementations import TestAssembler
|
|
71
|
+
from adaptivetesting.math.estimators import BayesModal, NormalPrior
|
|
72
|
+
from adaptivetesting.simulation import Simulation, StoppingCriterion, ResultOutputFormat
|
|
73
|
+
import pandas as pd
|
|
74
|
+
|
|
75
|
+
# Create item pool from DataFrame
|
|
76
|
+
items_data = pd.DataFrame({
|
|
77
|
+
"a": [1.32, 1.07, 0.84, 1.19, 0.95], # discrimination
|
|
78
|
+
"b": [-0.63, 0.18, -0.84, 0.41, -0.25], # difficulty
|
|
79
|
+
"c": [0.17, 0.10, 0.19, 0.15, 0.12], # guessing
|
|
80
|
+
"d": [0.87, 0.93, 1.0, 0.89, 0.94] # upper asymptote
|
|
81
|
+
})
|
|
82
|
+
item_pool = ItemPool.load_from_dataframe(items_data)
|
|
83
|
+
|
|
84
|
+
# Set up adaptive test
|
|
85
|
+
adaptive_test = TestAssembler(
|
|
86
|
+
item_pool=item_pool,
|
|
87
|
+
simulation_id="sim_001",
|
|
88
|
+
participant_id="participant_001",
|
|
89
|
+
ability_estimator=BayesModal,
|
|
90
|
+
estimator_args={"prior": NormalPrior(mean=0, sd=1)},
|
|
91
|
+
true_ability_level=0.5, # For simulation
|
|
92
|
+
simulation=True
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Run simulation
|
|
96
|
+
simulation = Simulation(
|
|
97
|
+
test=adaptive_test,
|
|
98
|
+
test_result_output=ResultOutputFormat.CSV
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
simulation.simulate(
|
|
102
|
+
criterion=StoppingCriterion.SE,
|
|
103
|
+
value=0.3 # Stop when standard error <= 0.3
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Save results
|
|
107
|
+
simulation.save_test_results()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Custom Prior Example
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from adaptivetesting.math.estimators import CustomPrior
|
|
114
|
+
from scipy.stats import t
|
|
115
|
+
|
|
116
|
+
# Create custom t prior
|
|
117
|
+
custom_prior = CustomPrior(t, 100)
|
|
118
|
+
|
|
119
|
+
# Use in estimator
|
|
120
|
+
adaptive_test = TestAssembler(
|
|
121
|
+
item_pool=item_pool,
|
|
122
|
+
simulation_id="custom_prior_sim",
|
|
123
|
+
participant_id="participant_002",
|
|
124
|
+
ability_estimator=BayesModal,
|
|
125
|
+
estimator_args={"prior": custom_prior},
|
|
126
|
+
true_ability_level=0.0,
|
|
127
|
+
simulation=True
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Real-world Testing (Non-simulation) with PsychoPy
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from psychopy import visual, event
|
|
135
|
+
from psychopy.hardware import keyboard
|
|
136
|
+
from adaptivetesting.implementations import TestAssembler
|
|
137
|
+
from adaptivetesting.models import AdaptiveTest, ItemPool, TestItem
|
|
138
|
+
from adaptivetesting.data import CSVContext
|
|
139
|
+
from adaptivetesting.math.estimators import BayesModal, CustomPrior
|
|
140
|
+
from adaptivetesting.math.item_selection import maximum_information_criterion
|
|
141
|
+
from scipy.stats import t
|
|
142
|
+
import pandas as pd
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# Create item pool from DataFrame
|
|
146
|
+
items_data = pd.DataFrame({
|
|
147
|
+
"a": [1.32, 1.07, 0.84, 1.19, 0.95], # discrimination
|
|
148
|
+
"b": [-0.63, 0.18, -0.84, 0.41, -0.25], # difficulty
|
|
149
|
+
"c": [0.17, 0.10, 0.19, 0.15, 0.12], # guessing
|
|
150
|
+
"d": [0.87, 0.93, 1.0, 0.89, 0.94] # upper asymptote
|
|
151
|
+
})
|
|
152
|
+
item_pool = ItemPool.load_from_dataframe(items_data)
|
|
153
|
+
|
|
154
|
+
# Create adaptive test
|
|
155
|
+
adaptive_test: AdaptiveTest = TestAssembler(
|
|
156
|
+
item_pool=item_pool,
|
|
157
|
+
simulation_id="example",
|
|
158
|
+
participant_id="dummy",
|
|
159
|
+
ability_estimator=BayesModal,
|
|
160
|
+
estimator_args={
|
|
161
|
+
"prior": CustomPrior(t, 100),
|
|
162
|
+
"optimization_interval":(-10, 10)
|
|
163
|
+
},
|
|
164
|
+
item_selector=maximum_information_criterion,
|
|
165
|
+
simulation=False,
|
|
166
|
+
debug=False
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# ====================
|
|
170
|
+
# Setup PsychoPy
|
|
171
|
+
# ====================
|
|
172
|
+
|
|
173
|
+
# general setup
|
|
174
|
+
win = visual.Window([800, 600],
|
|
175
|
+
monitor="testMonitor",
|
|
176
|
+
units="deg",
|
|
177
|
+
fullscr=False)
|
|
178
|
+
|
|
179
|
+
# init keyboard
|
|
180
|
+
keyboard.Keyboard()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
# define function to get user input
|
|
184
|
+
def get_response(item: TestItem) -> int:
|
|
185
|
+
# get index
|
|
186
|
+
item_difficulty: float = item.b
|
|
187
|
+
stimuli: str = [item for item in item_pool.test_items if item["Difficulty"] == item_difficulty][0]["word"]
|
|
188
|
+
|
|
189
|
+
# create text box and display stimulus
|
|
190
|
+
text_box = visual.TextBox2(win=win,
|
|
191
|
+
text=stimuli,
|
|
192
|
+
alignment="center",
|
|
193
|
+
size=24)
|
|
194
|
+
# draw text
|
|
195
|
+
text_box.draw()
|
|
196
|
+
# update window
|
|
197
|
+
win.flip()
|
|
198
|
+
|
|
199
|
+
# wait for pressed keys
|
|
200
|
+
while True:
|
|
201
|
+
keys = event.getKeys()
|
|
202
|
+
# if keys are not None
|
|
203
|
+
if keys:
|
|
204
|
+
# if the right arrow keys is pressed
|
|
205
|
+
# return 1
|
|
206
|
+
if keys[0] == "right":
|
|
207
|
+
return 1
|
|
208
|
+
# if the left arrow keys is pressed
|
|
209
|
+
# return 0
|
|
210
|
+
if keys[0] == "left":
|
|
211
|
+
return 0
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# override adaptive test default function
|
|
215
|
+
adaptive_test.get_response = get_response
|
|
216
|
+
|
|
217
|
+
# start adaptive test
|
|
218
|
+
while True:
|
|
219
|
+
adaptive_test.run_test_once()
|
|
220
|
+
|
|
221
|
+
# check stopping criterion
|
|
222
|
+
if adaptive_test.standard_error <= 0.4:
|
|
223
|
+
break
|
|
224
|
+
|
|
225
|
+
# end test if all items have been shown
|
|
226
|
+
if len(adaptive_test.item_pool.test_items) == 0:
|
|
227
|
+
break
|
|
228
|
+
|
|
229
|
+
# save test results
|
|
230
|
+
data_context = CSVContext(
|
|
231
|
+
adaptive_test.simulation_id,
|
|
232
|
+
adaptive_test.participant_id
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
data_context.save(adaptive_test.test_results)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Package Structure
|
|
239
|
+
|
|
240
|
+
The package is organized into several key modules:
|
|
241
|
+
|
|
242
|
+
- **`adaptivetesting.models`**: Core classes including `AdaptiveTest`, `ItemPool`, and `TestItem`
|
|
243
|
+
- **`adaptivetesting.implementations`**: Ready-to-use test implementations like `TestAssembler`
|
|
244
|
+
- **`adaptivetesting.math`**: Mathematical functions for IRT, ability estimation, and item selection
|
|
245
|
+
- **`adaptivetesting.simulation`**: Simulation framework and result management
|
|
246
|
+
- **`adaptivetesting.data`**: Data management utilities for CSV and pickle formats
|
|
247
|
+
- **`adaptivetesting.services`**: Abstract interfaces and protocols
|
|
248
|
+
|
|
249
|
+
## Advanced Features
|
|
250
|
+
|
|
251
|
+
### Multiple Stopping Criteria
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
simulation.simulate(
|
|
255
|
+
criterion=[StoppingCriterion.SE, StoppingCriterion.LENGTH],
|
|
256
|
+
value=[0.3, 20] # Stop at SE ≤ 0.3 OR length ≥ 20 items
|
|
257
|
+
)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Pretest Phase
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
adaptive_test = TestAssembler(
|
|
264
|
+
item_pool=item_pool,
|
|
265
|
+
simulation_id="pretest_sim",
|
|
266
|
+
participant_id="participant_003",
|
|
267
|
+
ability_estimator=BayesModal,
|
|
268
|
+
estimator_args={"prior": NormalPrior(0, 1)},
|
|
269
|
+
pretest=True,
|
|
270
|
+
pretest_seed=42,
|
|
271
|
+
simulation=True
|
|
272
|
+
)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Custom Item Selection
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from adaptivetesting.math.item_selection import maximum_information_criterion
|
|
279
|
+
|
|
280
|
+
adaptive_test = TestAssembler(
|
|
281
|
+
item_pool=item_pool,
|
|
282
|
+
simulation_id="custom_selection",
|
|
283
|
+
participant_id="participant_004",
|
|
284
|
+
ability_estimator=BayesModal,
|
|
285
|
+
estimator_args={"prior": NormalPrior(0, 1)},
|
|
286
|
+
item_selector=maximum_information_criterion,
|
|
287
|
+
item_selector_args={"additional_param": "value"},
|
|
288
|
+
simulation=True
|
|
289
|
+
)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Custom Optimization Interval
|
|
293
|
+
```python
|
|
294
|
+
adaptive_test = TestAssembler(
|
|
295
|
+
item_pool=item_pool,
|
|
296
|
+
simulation_id="pretest_sim",
|
|
297
|
+
participant_id="participant_003",
|
|
298
|
+
ability_estimator=BayesModal,
|
|
299
|
+
estimator_args={
|
|
300
|
+
"prior": NormalPrior(0, 1),
|
|
301
|
+
"optimization_interval": (-5, 5)},
|
|
302
|
+
pretest_seed=42,
|
|
303
|
+
simulation=True
|
|
304
|
+
)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Documentation
|
|
308
|
+
|
|
309
|
+
Full documentation is available in the `docs/` directory:
|
|
310
|
+
|
|
311
|
+
- [API Reference](docs/readme.md)
|
|
312
|
+
- [Models Module](docs/adaptivetesting.models.md)
|
|
313
|
+
- [Math Module](docs/adaptivetesting.math.md)
|
|
314
|
+
- [Implementation Examples](docs/adaptivetesting.implementations.md)
|
|
315
|
+
- [Simulation Guide](docs/adaptivetesting.simulation.md)
|
|
316
|
+
|
|
317
|
+
## Testing
|
|
318
|
+
|
|
319
|
+
The package includes comprehensive tests. Run them using:
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
python -m pytest adaptivetesting/tests/
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Contributing
|
|
326
|
+
|
|
327
|
+
We welcome contributions! Please see our [GitHub repository](https://github.com/condecon/adaptivetesting) for:
|
|
328
|
+
|
|
329
|
+
- Issue tracking
|
|
330
|
+
- Feature requests
|
|
331
|
+
- Pull request guidelines
|
|
332
|
+
- Development setup
|
|
333
|
+
|
|
334
|
+
## Research and Applications
|
|
335
|
+
|
|
336
|
+
This package is designed for researchers and practitioners in:
|
|
337
|
+
|
|
338
|
+
- Educational assessment
|
|
339
|
+
- Psychological testing
|
|
340
|
+
- Cognitive ability measurement
|
|
341
|
+
- Adaptive learning systems
|
|
342
|
+
- Psychometric research
|
|
343
|
+
|
|
344
|
+
The package facilitates the transition from research simulation to real-world testing applications without requiring major code modifications.
|
|
345
|
+
|
|
346
|
+
## License
|
|
347
|
+
|
|
348
|
+
This project is licensed under the terms specified in the [LICENSE](LICENSE) file.
|