Metadata-Version: 2.4
Name: tachywooting
Version: 0.2.1
Summary: Python interface for Wooting analog keyboards
Author: Mathias Salvas-Hébert
License-Expression: BSD-3-Clause
Keywords: wooting,analog-keyboard,keyboard,cffi,hdf5
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cffi>=1.15.0
Requires-Dist: h5py>=3.8.0
Requires-Dist: matplotlib>=3.6.0
Requires-Dist: numpy>=1.23.0
Requires-Dist: pandas>=1.5.0
Requires-Dist: rich>=10.0.0
Requires-Dist: setuptools>=77.0
Requires-Dist: tqdm>=4.60.0
Provides-Extra: docs
Requires-Dist: furo>=2024.8.6; extra == "docs"
Requires-Dist: sphinx>=7.0.0; extra == "docs"
Provides-Extra: dev
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: build>=1.0.0; extra == "dev"
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: roman>=4.0; extra == "dev"
Requires-Dist: ruff>=0.4.0; extra == "dev"
Requires-Dist: sphinx>=7.0.0; extra == "dev"
Requires-Dist: furo>=2024.8.6; extra == "dev"
Requires-Dist: twine>=5.0.0; extra == "dev"
Provides-Extra: all
Requires-Dist: tachywooting[dev]; extra == "all"
Dynamic: license-file

# TachyWooting

[![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](LICENSE)
[![Python versions](https://img.shields.io/pypi/pyversions/tachywooting)](https://pypi.org/project/tachywooting/)
[![Tests](https://github.com/Charestlab/tachywooting/actions/workflows/test-install.yml/badge.svg)](https://github.com/Charestlab/tachywooting/actions/workflows/test-install.yml)

Python bindings and acquisition utilities for Wooting analog keyboards.

For deeper implementation details, see [documentation.md](documentation.md).
Read the Docs/Sphinx sources live in [docs/](docs/) and use NumPy-style docstrings.
Console scripts are documented in [docs/scripts.md](docs/scripts.md).

## Project Documentation

- [README.md](README.md): project overview and quick start
- [documentation.md](documentation.md): technical details and architecture notes
- [development.md](development.md): maintainer workflow and SDK update process
- [PLUGIN_MANAGEMENT.md](PLUGIN_MANAGEMENT.md): plugin installation and troubleshooting
- [raw_sdk.md](raw_sdk.md): direct `lib`/`ffi` SDK reference for advanced use

- **Analog Key Acquisition**: Read key positions (0.0–1.0) with microsecond-level timing
- **Threshold-Based Triggering**: Automatically capture key press trajectories around actuation threshold
- **HDF5 Logging**: Hierarchical per-trial logging with automatic shard merging
- **Multi-Key Support**: Efficiently read multiple keys simultaneously using full-buffer API
- **Cross-Platform**: Linux, macOS, and Windows support
- **Automatic Setup**: Self-contained installation with system configuration
- **CLI Tools**: Command-line utilities for plugin management and testing

- Read analog key pressure as floats in the `0.0` to `1.0` range.
- Convert analog pressure to integer values in the `0` to `255` range.
- Acquire one or more keys around a threshold crossing.
- Log trials to hierarchical HDF5 files.
- Build against the bundled Wooting Analog SDK headers and native libraries.
- Inspect HDF5 logs with a small visualization CLI.

## Requirements

- Python 3.10 or newer.
- A supported Wooting analog keyboard.
- A local compiler toolchain for the CFFI interface build.
- Platform-specific permissions for USB/native library access.

### Quick Start

```bash
pip install .
```

### What setup is needed

`pip install` does **not** run system setup — pip installs from wheels, which have
no reliable post-install hook. Setup is split into two parts:

1. **CFFI compilation** happens **automatically the first time** you create a
   `WOOTING_ACQUISITION` (or run `wooting-demo`). It needs only a C compiler —
   no admin rights.
2. **SDK plugins + input permissions** require a **one-time privileged step**:

   ```bash
   wooting-build-interface   # installs SDK plugins + permissions (needs sudo/admin)
   ```

If the keyboard is not detected, the error message tells you exactly to run this
command — you do not have to remember it. To undo it later: `wooting-delete-interface`.

### Development Installation

```bash
python -m pip install -e ".[dev]"
wooting-build-interface
```

## Quick Start

```python
from tachywooting import WOOTING_ACQUISITION

acq = WOOTING_ACQUISITION(threshold=0.8)
acq.initialize_keyboard(verbose=True)

try:
    acq.setup_logging(name="tracking", path="logs", int_analog=2)
    trial = acq.acquire_analog_values(target_keys=["A"])
finally:
    acq.uninitialize_keyboard()
```

## CLI Demo

```bash
wooting-demo --key A --threshold 50
```

## Visual feedback (TachyPy)

On-screen pressure feedback — the interactive fixation cross and
`wait_light_press_visual()` — lives in **TachyPy**, not in this hardware package.
Install it with `pip install 'tachypy[wooting]'`, then:

```python
from tachypy import WOOTING_ACQUISITION  # keyboard + visual feedback
```

## HDF5 Logging

`setup_logging()` writes one temporary shard per trial and merges shards when `uninitialize_keyboard()` is called.

Final files use this layout:

```text
/trials/0001/keys/0004/values
```

Each `values` dataset stores columns in this order:

```text
position, time_from_onset, time_abs
```

## Visualize Logs

```bash
python -m tachywooting.visualize logs/tracking.hdf5 --list
python -m tachywooting.visualize logs/tracking.hdf5 --trial 1 --key 4
```

## Public API

- `WOOTING_ACQUISITION`: acquisition, threshold detection, readiness checks, and logging.
- `convert_char_to_keycode`: convert between key labels and HID keycodes.
- `load_trial`: load a single trial from an HDF5 log file.
- `load_session`: load all trials from an HDF5 log file.
- `trial_to_dataframe`: convert a trial dict to a pandas DataFrame.
- `build_interface`: rebuild the CFFI interface.
- `delete_interface`: remove generated CFFI artifacts.
- `lib` and `ffi`: raw CFFI handles for advanced SDK access.

## Troubleshooting

If importing works but acquisition fails with a missing native interface error, run:

```bash
wooting-build-interface
```

If no devices are detected, confirm the keyboard is connected, Wootility recognizes it, and platform permissions have been applied.

## Hardware Requirements

This package was developed and tested with the **Wooting UwU** keypad ([wooting.io/uwu](https://wooting.io/uwu)), and its use is strongly recommended for optimal results.

![Wooting UwU keypad](repo_visuals/UwU_keyboard.png)

The UwU is a 3-key Hall effect keypad using [**Lekker L45 V2 linear switches**](https://wooting.io/product/lekker-switch-l45-v2) — contactless magnetic sensors with a smooth linear force curve (30–45 cN, no tactile bump). Keys can be configured to actuate at any depth from 0.1mm to 4.0mm.
