adaptivetesting 1.1.5__tar.gz → 1.2__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.2/PKG-INFO +100 -0
- adaptivetesting-1.2/README.md +79 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/__init__.py +16 -3
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/data/__csv_context.py +23 -10
- adaptivetesting-1.2/adaptivetesting/data/__read_prev_items_exp_cont.py +56 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/implementations/__pre_test.py +10 -3
- adaptivetesting-1.2/adaptivetesting/implementations/__test_assembler.py +427 -0
- adaptivetesting-1.2/adaptivetesting/math/__gen_response_pattern.py +141 -0
- adaptivetesting-1.2/adaptivetesting/math/content_balancing/__constraint.py +23 -0
- adaptivetesting-1.2/adaptivetesting/math/content_balancing/__content_balancing.py +35 -0
- adaptivetesting-1.2/adaptivetesting/math/content_balancing/__functions.py +266 -0
- adaptivetesting-1.2/adaptivetesting/math/content_balancing/__init__.py +1 -0
- adaptivetesting-1.2/adaptivetesting/math/content_balancing/__maximum_priority_index.py +82 -0
- adaptivetesting-1.2/adaptivetesting/math/content_balancing/__weighted_penalty_model.py +337 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__bayes_modal_estimation.py +124 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__expect_a_posteriori.py +166 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/math/estimators/__functions/__bayes.py +35 -17
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/math/estimators/__functions/__estimators.py +34 -19
- adaptivetesting-1.2/adaptivetesting/math/estimators/__functions/__poly/__gpcm.py +70 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__functions/__poly/__grm.py +77 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__functions/__poly/__init__.py +4 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__functions/__poly/__poly_math.py +193 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/math/estimators/__init__.py +1 -1
- adaptivetesting-1.2/adaptivetesting/math/estimators/__ml_estimation.py +113 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__prior.py +183 -0
- adaptivetesting-1.2/adaptivetesting/math/estimators/__test_information.py +217 -0
- adaptivetesting-1.2/adaptivetesting/math/exposure_control/__exposure_control.py +32 -0
- adaptivetesting-1.2/adaptivetesting/math/exposure_control/__init__.py +2 -0
- adaptivetesting-1.2/adaptivetesting/math/exposure_control/__mpi_exposure_control.py +81 -0
- adaptivetesting-1.2/adaptivetesting/math/exposure_control/__randomesque.py +114 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/math/item_selection/__maximum_information_criterion.py +8 -13
- adaptivetesting-1.2/adaptivetesting/math/item_selection/__urrys_rule.py +38 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__adaptive_test.py +2 -33
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__item_pool.py +87 -69
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__item_selection_exception.py +1 -0
- adaptivetesting-1.2/adaptivetesting/models/__test_item.py +81 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/services/__estimator_interface.py +17 -10
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/services/__item_selection_protocol.py +0 -2
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/services/__test_results_interface.py +0 -2
- adaptivetesting-1.2/adaptivetesting/simulation/__init__.py +5 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/simulation/__simulation.py +39 -28
- adaptivetesting-1.2/adaptivetesting/tests/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_adaptive_test.py +0 -4
- adaptivetesting-1.2/adaptivetesting/tests/test_bayes_modal.py +194 -0
- adaptivetesting-1.2/adaptivetesting/tests/test_content_balacing.py +131 -0
- adaptivetesting-1.2/adaptivetesting/tests/test_eap.py +159 -0
- adaptivetesting-1.2/adaptivetesting/tests/test_exposure_control_mpi.py +87 -0
- adaptivetesting-1.2/adaptivetesting/tests/test_full_tests.py +224 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_generate_response_pattern.py +33 -2
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_item_selection.py +12 -2
- adaptivetesting-1.2/adaptivetesting/tests/test_load_test_items.py +325 -0
- adaptivetesting-1.2/adaptivetesting/tests/test_poly_models.py +103 -0
- adaptivetesting-1.2/adaptivetesting/tests/test_priors.py +56 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_simulation.py +63 -1
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_test_assembler.py +8 -8
- adaptivetesting-1.2/adaptivetesting/tests/test_weighted_penalty_model.py +530 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/utils/__funcs.py +1 -1
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/utils/__plots.py +34 -26
- adaptivetesting-1.2/adaptivetesting.egg-info/PKG-INFO +100 -0
- adaptivetesting-1.2/adaptivetesting.egg-info/SOURCES.txt +87 -0
- adaptivetesting-1.2/adaptivetesting.egg-info/dependency_links.txt +1 -0
- adaptivetesting-1.2/adaptivetesting.egg-info/requires.txt +6 -0
- adaptivetesting-1.2/adaptivetesting.egg-info/top_level.txt +1 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/pyproject.toml +22 -12
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/setup.cfg +7 -2
- adaptivetesting-1.2/setup.py +21 -0
- adaptivetesting-1.1.5/.github/CONTRIBUTING.md +0 -11
- adaptivetesting-1.1.5/.github/workflows/publish.yml +0 -39
- adaptivetesting-1.1.5/.github/workflows/python-test.yml +0 -60
- adaptivetesting-1.1.5/.gitignore +0 -170
- adaptivetesting-1.1.5/.gitlab-ci.yml +0 -13
- adaptivetesting-1.1.5/.python-version +0 -1
- adaptivetesting-1.1.5/.readthedocs.yml +0 -22
- adaptivetesting-1.1.5/.vscode/extensions.json +0 -8
- adaptivetesting-1.1.5/.vscode/settings.json +0 -14
- adaptivetesting-1.1.5/CHANGELOG.md +0 -13
- adaptivetesting-1.1.5/PKG-INFO +0 -375
- adaptivetesting-1.1.5/README.md +0 -356
- adaptivetesting-1.1.5/adaptivetesting/implementations/__test_assembler.py +0 -231
- adaptivetesting-1.1.5/adaptivetesting/math/__gen_response_pattern.py +0 -50
- adaptivetesting-1.1.5/adaptivetesting/math/estimators/__bayes_modal_estimation.py +0 -121
- adaptivetesting-1.1.5/adaptivetesting/math/estimators/__expect_a_posteriori.py +0 -90
- adaptivetesting-1.1.5/adaptivetesting/math/estimators/__ml_estimation.py +0 -65
- adaptivetesting-1.1.5/adaptivetesting/math/estimators/__prior.py +0 -94
- adaptivetesting-1.1.5/adaptivetesting/math/estimators/__test_information.py +0 -91
- adaptivetesting-1.1.5/adaptivetesting/math/item_selection/__urrys_rule.py +0 -33
- adaptivetesting-1.1.5/adaptivetesting/models/__test_item.py +0 -33
- adaptivetesting-1.1.5/adaptivetesting/simulation/__init__.py +0 -1
- adaptivetesting-1.1.5/adaptivetesting/tests/test_bayes_modal.py +0 -89
- adaptivetesting-1.1.5/adaptivetesting/tests/test_eap.py +0 -27
- adaptivetesting-1.1.5/adaptivetesting/tests/test_load_test_items.py +0 -176
- adaptivetesting-1.1.5/docs/Makefile +0 -20
- adaptivetesting-1.1.5/docs/data.md +0 -69
- adaptivetesting-1.1.5/docs/implementations.md +0 -117
- adaptivetesting-1.1.5/docs/index.md +0 -32
- adaptivetesting-1.1.5/docs/make.bat +0 -35
- adaptivetesting-1.1.5/docs/math.md +0 -254
- adaptivetesting-1.1.5/docs/models.md +0 -248
- adaptivetesting-1.1.5/docs/readme.md +0 -32
- adaptivetesting-1.1.5/docs/requirements.txt +0 -0
- adaptivetesting-1.1.5/docs/services.md +0 -42
- adaptivetesting-1.1.5/docs/simulation.md +0 -53
- adaptivetesting-1.1.5/docs/source/_static/SPEC-0.svg +0 -1
- adaptivetesting-1.1.5/docs/source/_static/logo.svg +0 -67
- adaptivetesting-1.1.5/docs/source/_static/main.css +0 -24
- adaptivetesting-1.1.5/docs/source/conf.py +0 -49
- adaptivetesting-1.1.5/docs/source/data.rst +0 -9
- adaptivetesting-1.1.5/docs/source/implementations.rst +0 -8
- adaptivetesting-1.1.5/docs/source/index.rst +0 -37
- adaptivetesting-1.1.5/docs/source/math.rst +0 -21
- adaptivetesting-1.1.5/docs/source/models.rst +0 -9
- adaptivetesting-1.1.5/docs/source/services.rst +0 -8
- adaptivetesting-1.1.5/docs/source/simulation.rst +0 -9
- adaptivetesting-1.1.5/docs/source/tests.rst +0 -5
- adaptivetesting-1.1.5/docs/tests.md +0 -4
- adaptivetesting-1.1.5/examples/.gitignore +0 -3
- adaptivetesting-1.1.5/examples/simulation.py +0 -134
- adaptivetesting-1.1.5/examples/testing.py +0 -108
- adaptivetesting-1.1.5/images/default.svg +0 -208
- adaptivetesting-1.1.5/images/semi-adaptive.svg +0 -254
- adaptivetesting-1.1.5/mypy.ini +0 -8
- adaptivetesting-1.1.5/requirements.txt +0 -0
- adaptivetesting-1.1.5/uv.lock +0 -4274
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/LICENSE +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/data/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/data/__pickle_context.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/implementations/__default_implementation.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/implementations/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/implementations/__semi_implementation.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/math/__init__.py +0 -0
- {adaptivetesting-1.1.5/adaptivetesting/tests → adaptivetesting-1.2/adaptivetesting/math/estimators/__functions}/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/math/item_selection/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__algorithm_exception.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__misc.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/models/__test_result.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/services/__init__.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_descriptives.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_information_test.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_mle.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_plots.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_pretest.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/tests/test_standard_error.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/utils/__descriptives.py +0 -0
- {adaptivetesting-1.1.5 → adaptivetesting-1.2}/adaptivetesting/utils/__init__.py +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adaptivetesting
|
|
3
|
+
Version: 1.2
|
|
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
|
+
Author-email: Jonas Engicht <dev@condecon.de>
|
|
6
|
+
Project-URL: Homepage, https://github.com/condecon/adaptivetesting
|
|
7
|
+
Project-URL: Documentation, https://github.com/condecon/adaptivetesting/wiki
|
|
8
|
+
Project-URL: Repository, https://github.com/condecon/adaptivetesting.git
|
|
9
|
+
Project-URL: Issues, https://github.com/condecon/adaptivetesting/issues
|
|
10
|
+
Keywords: statistics,psychology,item-response-theory,computerized-adaptive-testing
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy>=2.1.0
|
|
15
|
+
Requires-Dist: pandas>=2.3.0
|
|
16
|
+
Requires-Dist: scipy>=1.15.0
|
|
17
|
+
Requires-Dist: tqdm>=4.66.0
|
|
18
|
+
Requires-Dist: matplotlib>=3.10.0
|
|
19
|
+
Requires-Dist: numdifftools>=0.9.42
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# adaptivetesting
|
|
23
|
+
|
|
24
|
+
<img src="/docs/_static/logo.svg" style="width: 100%">
|
|
25
|
+
</img>
|
|
26
|
+
|
|
27
|
+
**An open-source Python package for simplified, customizable Computerized Adaptive Testing (CAT) using Bayesian methods.**
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Key Features
|
|
31
|
+
|
|
32
|
+
- **Bayesian Methods**: Built-in support for Bayesian ability estimation with customizable priors
|
|
33
|
+
- **Flexible Architecture**: Object-oriented design with abstract classes for easy extension
|
|
34
|
+
- **Item Response Theory**: Full support for 1PL, 2PL, 3PL, and 4PL models, GRM, GPCM
|
|
35
|
+
- **Multiple Estimators**:
|
|
36
|
+
- Maximum Likelihood Estimation (MLE)
|
|
37
|
+
- Bayesian Modal Estimation (BM)
|
|
38
|
+
- Expected A Posteriori (EAP)
|
|
39
|
+
- **Item Selection Strategies**: Maximum information criterion
|
|
40
|
+
- **Content Balancing**: Maximum Priority Index, Weighted Penalty Model
|
|
41
|
+
- **Exposure Control**: Randomesque Item Selection, Maximum Priority Index
|
|
42
|
+
- **Simulation Framework**: Comprehensive tools for CAT simulation and evaluation
|
|
43
|
+
- **Real-world Application**: Direct transition from simulation to production testing
|
|
44
|
+
- **Stopping Criteria**: Support for standard error and test length criteria
|
|
45
|
+
- **Data Management**: Built-in support for CSV and pickle data formats
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
Install from PyPI using pip:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install adaptivetesting
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For the latest development version:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install git+https://github.com/condecon/adaptivetesting
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Contributing
|
|
62
|
+
|
|
63
|
+
We welcome contributions! Please see our [GitHub repository](https://github.com/condecon/adaptivetesting) for:
|
|
64
|
+
|
|
65
|
+
- Issue tracking
|
|
66
|
+
- Feature requests
|
|
67
|
+
- Pull request guidelines
|
|
68
|
+
- Development setup
|
|
69
|
+
|
|
70
|
+
## Research and Applications
|
|
71
|
+
|
|
72
|
+
This package is designed for researchers and practitioners in:
|
|
73
|
+
|
|
74
|
+
- Educational assessment
|
|
75
|
+
- Psychological testing
|
|
76
|
+
- Cognitive ability measurement
|
|
77
|
+
- Adaptive learning systems
|
|
78
|
+
- Psychometric research
|
|
79
|
+
|
|
80
|
+
The package facilitates the transition from research simulation to real-world testing applications without requiring major code modifications.
|
|
81
|
+
|
|
82
|
+
## Citation
|
|
83
|
+
If you use this package for your academic work, please provide the following reference:
|
|
84
|
+
Engicht, J., Bee, R. M., & Koch, T. (2025). Customizable Bayesian Adaptive Testing with Python – The adaptivetesting Package. Open Science Framework. https://doi.org/10.31219/osf.io/d2xge_v1
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
@online{engichtCustomizableBayesianAdaptive2025,
|
|
88
|
+
title = {Customizable {{Bayesian Adaptive Testing}} with {{Python}} – {{The}} Adaptivetesting {{Package}}},
|
|
89
|
+
author = {Engicht, Jonas and Bee, R. Maximilian and Koch, Tobias},
|
|
90
|
+
date = {2025-08-06},
|
|
91
|
+
eprinttype = {Open Science Framework},
|
|
92
|
+
doi = {10.31219/osf.io/d2xge_v1},
|
|
93
|
+
url = {https://osf.io/d2xge_v1},
|
|
94
|
+
pubstate = {prepublished}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
This project is licensed under the terms specified in the [LICENSE](LICENSE) file.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# adaptivetesting
|
|
2
|
+
|
|
3
|
+
<img src="/docs/_static/logo.svg" style="width: 100%">
|
|
4
|
+
</img>
|
|
5
|
+
|
|
6
|
+
**An open-source Python package for simplified, customizable Computerized Adaptive Testing (CAT) using Bayesian methods.**
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Bayesian Methods**: Built-in support for Bayesian ability estimation with customizable priors
|
|
12
|
+
- **Flexible Architecture**: Object-oriented design with abstract classes for easy extension
|
|
13
|
+
- **Item Response Theory**: Full support for 1PL, 2PL, 3PL, and 4PL models, GRM, GPCM
|
|
14
|
+
- **Multiple Estimators**:
|
|
15
|
+
- Maximum Likelihood Estimation (MLE)
|
|
16
|
+
- Bayesian Modal Estimation (BM)
|
|
17
|
+
- Expected A Posteriori (EAP)
|
|
18
|
+
- **Item Selection Strategies**: Maximum information criterion
|
|
19
|
+
- **Content Balancing**: Maximum Priority Index, Weighted Penalty Model
|
|
20
|
+
- **Exposure Control**: Randomesque Item Selection, Maximum Priority Index
|
|
21
|
+
- **Simulation Framework**: Comprehensive tools for CAT simulation and evaluation
|
|
22
|
+
- **Real-world Application**: Direct transition from simulation to production testing
|
|
23
|
+
- **Stopping Criteria**: Support for standard error and test length criteria
|
|
24
|
+
- **Data Management**: Built-in support for CSV and pickle data formats
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Install from PyPI using pip:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install adaptivetesting
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
For the latest development version:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install git+https://github.com/condecon/adaptivetesting
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Contributing
|
|
41
|
+
|
|
42
|
+
We welcome contributions! Please see our [GitHub repository](https://github.com/condecon/adaptivetesting) for:
|
|
43
|
+
|
|
44
|
+
- Issue tracking
|
|
45
|
+
- Feature requests
|
|
46
|
+
- Pull request guidelines
|
|
47
|
+
- Development setup
|
|
48
|
+
|
|
49
|
+
## Research and Applications
|
|
50
|
+
|
|
51
|
+
This package is designed for researchers and practitioners in:
|
|
52
|
+
|
|
53
|
+
- Educational assessment
|
|
54
|
+
- Psychological testing
|
|
55
|
+
- Cognitive ability measurement
|
|
56
|
+
- Adaptive learning systems
|
|
57
|
+
- Psychometric research
|
|
58
|
+
|
|
59
|
+
The package facilitates the transition from research simulation to real-world testing applications without requiring major code modifications.
|
|
60
|
+
|
|
61
|
+
## Citation
|
|
62
|
+
If you use this package for your academic work, please provide the following reference:
|
|
63
|
+
Engicht, J., Bee, R. M., & Koch, T. (2025). Customizable Bayesian Adaptive Testing with Python – The adaptivetesting Package. Open Science Framework. https://doi.org/10.31219/osf.io/d2xge_v1
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
@online{engichtCustomizableBayesianAdaptive2025,
|
|
67
|
+
title = {Customizable {{Bayesian Adaptive Testing}} with {{Python}} – {{The}} Adaptivetesting {{Package}}},
|
|
68
|
+
author = {Engicht, Jonas and Bee, R. Maximilian and Koch, Tobias},
|
|
69
|
+
date = {2025-08-06},
|
|
70
|
+
eprinttype = {Open Science Framework},
|
|
71
|
+
doi = {10.31219/osf.io/d2xge_v1},
|
|
72
|
+
url = {https://osf.io/d2xge_v1},
|
|
73
|
+
pubstate = {prepublished}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
This project is licensed under the terms specified in the [LICENSE](LICENSE) file.
|
|
@@ -12,18 +12,21 @@ from .data.__pickle_context import PickleContext
|
|
|
12
12
|
from .implementations.__default_implementation import DefaultImplementation
|
|
13
13
|
from .implementations.__pre_test import PreTest
|
|
14
14
|
from .implementations.__semi_implementation import SemiAdaptiveImplementation
|
|
15
|
-
from .implementations.__test_assembler import TestAssembler
|
|
15
|
+
from .implementations.__test_assembler import TestAssembler, ContentBalancingArgs, ExposureControlArgs
|
|
16
16
|
|
|
17
17
|
from .math.__gen_response_pattern import generate_response_pattern
|
|
18
18
|
from .math.estimators.__ml_estimation import MLEstimator
|
|
19
19
|
from .math.estimators.__bayes_modal_estimation import BayesModal
|
|
20
20
|
from .math.estimators.__expect_a_posteriori import ExpectedAPosteriori
|
|
21
|
-
from .math.estimators.__prior import Prior, NormalPrior, CustomPrior, CustomPriorException
|
|
21
|
+
from .math.estimators.__prior import Prior, NormalPrior, CustomPrior, CustomPriorException, SkewNormalPrior, EmpiricalPrior
|
|
22
22
|
from .math.estimators.__functions.__estimators import probability_y0, probability_y1, maximize_likelihood_function, likelihood
|
|
23
23
|
from .math.estimators.__functions.__bayes import maximize_posterior
|
|
24
24
|
from .math.estimators.__test_information import test_information_function, item_information_function, prior_information_function
|
|
25
25
|
from .math.item_selection.__maximum_information_criterion import maximum_information_criterion
|
|
26
26
|
from .math.item_selection.__urrys_rule import urrys_rule
|
|
27
|
+
from .math.content_balancing.__weighted_penalty_model import WeightedPenaltyModel
|
|
28
|
+
from .math.content_balancing.__constraint import *
|
|
29
|
+
from .math.content_balancing.__functions import *
|
|
27
30
|
|
|
28
31
|
from .models.__adaptive_test import AdaptiveTest
|
|
29
32
|
from .models.__algorithm_exception import AlgorithmException
|
|
@@ -39,4 +42,14 @@ from .services.__item_selection_protocol import ItemSelectionStrategy
|
|
|
39
42
|
|
|
40
43
|
from .simulation.__simulation import Simulation, SimulationPool, setup_simulation_and_start
|
|
41
44
|
|
|
42
|
-
from .utils.__descriptives import bias, average_absolute_deviation, rmse
|
|
45
|
+
from .utils.__descriptives import bias, average_absolute_deviation, rmse
|
|
46
|
+
from .utils.__funcs import load_final_test_results, load_test_results_single_participant
|
|
47
|
+
from .utils.__plots import (
|
|
48
|
+
plot_exposure_rate,
|
|
49
|
+
plot_final_ability_estimates,
|
|
50
|
+
plot_icc,
|
|
51
|
+
plot_iif,
|
|
52
|
+
plot_exposure_rate,
|
|
53
|
+
plot_test_information,
|
|
54
|
+
plot_theta_estimation_trace
|
|
55
|
+
)
|
|
@@ -3,7 +3,8 @@ import csv
|
|
|
3
3
|
import pathlib
|
|
4
4
|
from ..models.__test_result import TestResult
|
|
5
5
|
from ..services.__test_results_interface import ITestResults
|
|
6
|
-
|
|
6
|
+
import json
|
|
7
|
+
import ast
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class CSVContext(ITestResults):
|
|
@@ -47,22 +48,34 @@ class CSVContext(ITestResults):
|
|
|
47
48
|
file.close()
|
|
48
49
|
|
|
49
50
|
def load(self) -> List[TestResult]:
|
|
50
|
-
"""Loads
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
"""Loads results from the database.
|
|
52
|
+
The implementation of this method is required
|
|
53
|
+
by the interface. However, it does not have
|
|
54
|
+
any implemented functionality and will throw an error
|
|
55
|
+
if used.
|
|
56
|
+
|
|
57
|
+
Returns: List[TestResult]
|
|
57
58
|
"""
|
|
58
59
|
foldername = f"data/{self.simulation_id}"
|
|
59
60
|
|
|
60
|
-
fieldnames = list(fields(TestResult))
|
|
61
61
|
test_results: list[TestResult] = []
|
|
62
62
|
with open(f"{foldername}/{self.participant_id}.csv", "r", encoding="utf-8") as file:
|
|
63
|
-
reader = csv.DictReader(file
|
|
63
|
+
reader = csv.DictReader(file)
|
|
64
|
+
next(reader, None) # skip header row
|
|
64
65
|
for row in reader:
|
|
65
66
|
test_result = TestResult.from_dict(row)
|
|
67
|
+
# showed_item is read as a string representation of a Python
|
|
68
|
+
# literal (e.g. a dict). Use ast.literal_eval to safely parse
|
|
69
|
+
# it back into a dict. Fallback to a JSON-style conversion
|
|
70
|
+
# if literal_eval fails.
|
|
71
|
+
try:
|
|
72
|
+
test_result.showed_item = ast.literal_eval(str(test_result.showed_item))
|
|
73
|
+
except Exception:
|
|
74
|
+
json_string = str(test_result.showed_item).replace("'", '"').replace("None", "null")
|
|
75
|
+
try:
|
|
76
|
+
test_result.showed_item = json.loads(json_string)
|
|
77
|
+
except Exception:
|
|
78
|
+
test_result.showed_item = {}
|
|
66
79
|
test_results.append(test_result)
|
|
67
80
|
file.close()
|
|
68
81
|
return test_results
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
from warnings import deprecated
|
|
3
|
+
from ..models.__test_item import TestItem
|
|
4
|
+
from ..models.__test_result import TestResult
|
|
5
|
+
from .__csv_context import CSVContext
|
|
6
|
+
from .__pickle_context import PickleContext
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def read_prev_items(format: Literal["CSV", "PICKLE"],
|
|
10
|
+
test_id: str,
|
|
11
|
+
participant_ids: list[str]) -> list[TestItem]:
|
|
12
|
+
"""Read previously administered items.
|
|
13
|
+
This function is internally used to perform exposure control.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
format (Literal["CSV", "PICKLE"]): The format of the results: CSV or PICKLE.
|
|
17
|
+
test_id (str): The test ID / simulation ID.
|
|
18
|
+
participant_ids (list[str]): The participant IDs.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
list[TestItem]: A list of TestItem objects.
|
|
22
|
+
"""
|
|
23
|
+
all_shown_test_items = []
|
|
24
|
+
|
|
25
|
+
for part_id in participant_ids:
|
|
26
|
+
test_results = read_single_participant(test_id, part_id, format)
|
|
27
|
+
items = [TestItem.from_dict(res.showed_item) for res in test_results]
|
|
28
|
+
|
|
29
|
+
all_shown_test_items += items
|
|
30
|
+
|
|
31
|
+
return all_shown_test_items
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@deprecated("This function will be removed in future releases.")
|
|
35
|
+
def read_single_participant(test_id: str, participant_id: str, format: Literal["CSV", "PICKLE"]) -> list[TestResult]:
|
|
36
|
+
"""
|
|
37
|
+
Reads the test results of a particular participant.
|
|
38
|
+
Args:
|
|
39
|
+
test_id (str): The test ID / simulation ID.
|
|
40
|
+
participant_id (str): The participant ID.
|
|
41
|
+
format (Literal["CSV", "PICKLE"]): The format of the results: CSV or PICKLE.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
list[TestResult]: A list of TestResult objects.
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
ValueError: If the format is not supported.
|
|
48
|
+
"""
|
|
49
|
+
context: CSVContext | PickleContext
|
|
50
|
+
if format == "CSV":
|
|
51
|
+
context = CSVContext(test_id, participant_id)
|
|
52
|
+
return context.load()
|
|
53
|
+
if format == "PICKLE":
|
|
54
|
+
context = PickleContext(test_id, participant_id)
|
|
55
|
+
return context.load()
|
|
56
|
+
raise ValueError(f"Unknown format: {format}")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import List
|
|
1
|
+
from typing import List, cast
|
|
2
2
|
import numpy as np
|
|
3
3
|
from ..models.__test_item import TestItem
|
|
4
4
|
import random
|
|
@@ -10,6 +10,7 @@ class PreTest:
|
|
|
10
10
|
The pretest class can be used to draw items randomly from
|
|
11
11
|
difficulty quantiles
|
|
12
12
|
of the item pool.
|
|
13
|
+
This pretest can only be used with dichotomous IRT models and items.
|
|
13
14
|
|
|
14
15
|
Args:
|
|
15
16
|
items: Item pool
|
|
@@ -18,15 +19,21 @@ class PreTest:
|
|
|
18
19
|
If not, the item selection will be drawn randomly, and you will not be able
|
|
19
20
|
to reproduce the results.
|
|
20
21
|
|
|
22
|
+
Raises:
|
|
23
|
+
ValueError: Raised if the items are specified for polytomous IRT models.
|
|
24
|
+
|
|
21
25
|
"""
|
|
22
26
|
self.items = items
|
|
23
27
|
self.seed = seed
|
|
24
28
|
|
|
29
|
+
if any([isinstance(item.b, list) for item in items]):
|
|
30
|
+
raise ValueError("The pretest can only be used with dichotomous IRT models and items.")
|
|
31
|
+
|
|
25
32
|
def calculate_quantiles(self) -> np.ndarray:
|
|
26
33
|
"""Calculates quantiles 0.25, 0.5, 0.75
|
|
27
34
|
"""
|
|
28
35
|
# get difficulties
|
|
29
|
-
difficulties: List[float] = [item.b for item in self.items]
|
|
36
|
+
difficulties: List[float] = [cast(float, item.b) for item in self.items]
|
|
30
37
|
|
|
31
38
|
quantiles = np.array([])
|
|
32
39
|
# calculate quantiles
|
|
@@ -50,7 +57,7 @@ class PreTest:
|
|
|
50
57
|
"""
|
|
51
58
|
# select only items with difficulty in interval
|
|
52
59
|
items_in_interval: List[TestItem] = [item for item in list(self.items)
|
|
53
|
-
if lower < item.b <= upper]
|
|
60
|
+
if lower < cast(float, item.b) <= upper]
|
|
54
61
|
# draw one item randomly
|
|
55
62
|
if self.seed is not None:
|
|
56
63
|
random.seed(self.seed)
|