Metadata-Version: 2.4
Name: psychopy-pest
Version: 2.1.0
Summary: PEST adaptive staircase (Taylor & Creelman, 1967) as a PsychoPy plugin
Author: Zhenxian Li
License: Non-Commercial License for PEST MATLAB Implementation
        -------------------------------------------------------
        
        Copyright (c) 2025 Zhenxian Li
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to use 
        the Software solely for non-commercial research and educational purposes,
        subject to the following conditions:
        
        1. The above copyright notice and this permission notice shall be included
           in all copies or substantial portions of the Software.
           
        2. The Software may not be used, reproduced, modified, distributed, or 
           sublicensed for any commercial purpose without the prior written consent
           of the copyright holder.
        
        3. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
           OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
           FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
           THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
           LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
           OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
           SOFTWARE.
        
        For any inquiries regarding commercial use, please open an issue on GitHub:
        https://github.com/ZhenxianLi/PEST_Toolbox/issues
        
Project-URL: Homepage, https://github.com/ZhenxianLi/PEST_Toolbox
Project-URL: Issues, https://github.com/ZhenxianLi/PEST_Toolbox/issues
Keywords: psychopy,psychophysics,staircase,PEST,threshold
Classifier: Programming Language :: Python :: 3
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: License :: Free for non-commercial use
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Dynamic: license-file

# psychopy-pest

A [PsychoPy](https://www.psychopy.org) plugin that adds **PEST** (Parameter
Estimation by Sequential Testing; Taylor & Creelman, 1967) as
`psychopy.data.PestHandler`, alongside PsychoPy's own `StairHandler` and
`QuestHandler`.

> Taylor, M. M., & Creelman, C. D. (1967). PEST: Efficient estimates on
> probability functions. *The Journal of the Acoustical Society of America*,
> 41(4A), 782–787. https://doi.org/10.1121/1.1910407

It implements the same procedure as the MATLAB toolbox in this repository
and gives identical results: the Wald sequential test (or an optional
N-down/M-up rule), the five step-size rules, and termination when a reversal
would halve the step below the minimum. See the
[main README](https://github.com/ZhenxianLi/PEST_Toolbox#the-pest-procedure)
for the rules.

## Installation

In the Python environment that runs PsychoPy:

```bash
pip install "psychopy-pest @ git+https://github.com/ZhenxianLi/PEST_Toolbox#subdirectory=python"
```

In the PsychoPy app, open **Tools → Plugins/packages manager → Packages**
and install the same address, or run the command above in the app's
terminal.

## Usage with PsychoPy

```python
from psychopy import plugins
plugins.scanPlugins()             # find newly installed plugins
plugins.loadPlugin('psychopy-pest')
from psychopy import data

staircase = data.PestHandler(
    startVal=-20,         # intensity of the first trial
    startStepSize=8,
    minStepSize=1,        # run ends when a reversal halves the step below this
    maxStepSize=16,
    pThreshold=0.75,      # Wald test target
    waldLimit=1)

for intensity in staircase:          # stops when the PEST run ends
    isCorrect = runTrial(intensity)  # your trial code
    staircase.addResponse(isCorrect)

print(staircase.threshold)
staircase.saveAsExcel('pest_run.xlsx')
```

`PestHandler` is a subclass of `StairHandler`, so `addOtherData`, the
`saveAs*` methods and `ExperimentHandler.addLoop` work as usual. A correct
response steps the intensity **down**, and steps are linear: express the
intensity in the unit PEST should step in (for example, dB).

In Builder, enable the plugin in the plugin manager and create the handler in
a Code component.

## Usage without PsychoPy

The algorithm itself has no dependencies:

```python
from psychopy_pest import PEST

pest = PEST(initial_level=-20, initial_step_size=8, min_step_size=1)
while not pest.finished:
    pest.update(run_trial(pest.level))
print(pest.threshold, pest.history)
```

## Development

```bash
pip install -e ".[test]"
pytest
```

The handler tests run when PsychoPy is installed and are skipped otherwise.
[`examples/simulated_observer.py`](https://github.com/ZhenxianLi/PEST_Toolbox/blob/main/python/examples/simulated_observer.py) runs both classes against a simulated
observer.

## License

Non-commercial research and educational use only; see [LICENSE](https://github.com/ZhenxianLi/PEST_Toolbox/blob/main/LICENSE).
