Metadata-Version: 2.4
Name: dyntex
Version: 1.0
Summary: MotionCloud and dynamic texture stimulus generation tools
Author: Jonathan Vacher
License-Expression: MIT
Project-URL: Homepage, https://gitlab.com/dynamic-textures/dyntex-python
Project-URL: Documentation, https://dynamic-textures.gitlab.io/dyntex-python/
Project-URL: Repository, https://gitlab.com/dynamic-textures/dyntex-python
Project-URL: Issues, https://gitlab.com/dynamic-textures/dyntex-python/-/issues
Keywords: dynamic textures,motion clouds,neuroscience,psychophysics,visual stimuli
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: imageio[ffmpeg]
Requires-Dist: numpy
Requires-Dist: torch
Provides-Extra: psychopy
Requires-Dist: psychopy; extra == "psychopy"
Provides-Extra: opengl
Requires-Dist: glfw>=2.7; extra == "opengl"
Requires-Dist: moderngl>=5.10; extra == "opengl"
Provides-Extra: docs
Requires-Dist: nbsphinx; extra == "docs"
Requires-Dist: sphinx; extra == "docs"
Requires-Dist: sphinx-rtd-theme; extra == "docs"
Dynamic: license-file

# DynTex

DynTex generates MotionCloud and dynamic texture stimuli with PyTorch. It includes
programmatic generation, PsychoPy demos, a no-code batch GUI, and an optional
ModernGL viewer.

## Repository Structure

```
.
├── demo
│   ├── simple_gui.py        # Basic MotionCloud GUI demo
│   ├── compound_gui.py      # Composite MotionCloud GUI (blend two clouds)
│   ├── batch_generate_gui.py # Batch GUI launcher
│   ├── moderngl_viewer.py   # ModernGL example launcher
│   └── runtime_check.ipynb  # Notebook for checking package runtime and environment
├── dyntex
│   ├── DynTex.py            # Core classes and entry points
│   ├── MotionCloud.py       # MotionCloud stimulus implementation
│   ├── DriftingGrating.py   # DriftingGrating stimulus utility
│   ├── batch.py             # Batch generation backend
│   ├── batch_gui.py         # Installed Tkinter batch GUI
│   ├── movie_demo.py        # Installed MP4 movie-generation smoke test
│   ├── opengl_demo.py       # Installed ModernGL example
│   └── utils.py             # Helper functions and utilities
├── pyproject.toml           # Build configuration and package metadata
└── README.md                # This installation & usage guide
```

---

## Prerequisites

- **Python 3.10 or newer**
- **Git** (optional, to clone the repository)
- Optional: **CUDA-capable GPU** with matching CUDA drivers for PyTorch GPU acceleration

---

## 1. Optional: Get the Source Files

```bash
# Clone using SSH when you want the full source tree
git clone git@gitlab.com:dynamic-textures/dyntex-python.git
cd dyntex-python
```

Installing from PyPI does not require a source checkout. Alternatively, download
the [full archive from GitLab](https://gitlab.com/dynamic-textures/dyntex-python/-/archive/main/dyntex-python-main.zip).

---

## 2. Create & Activate a Python Environment

You can choose **Conda** or the built-in **venv** module.

### 2.1 Using Conda

```bash
conda create -n dyntex-env python=3.10 -y
conda activate dyntex-env
conda install pip -y
```

### 2.2 Using `venv` (macOS/Linux -- python3.10 required)

```bash
python3 -m venv dyntex-env
source dyntex-env/bin/activate
pip install --upgrade pip
```

### 2.3 Using `venv` (Windows PowerShell -- python3.10 required)

```powershell
python -m venv dyntex-env
.\dyntex-env\Scripts\Activate.ps1
pip install --upgrade pip
```

---

## 3. Install DynTex


1. **Optional: install a CUDA-specific PyTorch build**:

   Visit the [official PyTorch installation page](https://pytorch.org/get-started/locally/) and select the command matching your CUDA version. For example, with CUDA 11.7:

   ```bash
   pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
   ```

2. **Install the package**:

   From PyPI:

   ```bash
   pip install dyntex
   ```

3. **Generate a test movie**:

   The default installation can generate a short MP4 without PsychoPy or
   OpenGL:

   ```bash
   dyntex-movie-demo
   ```

   This writes `dyntex_demo.mp4` in the current directory. Run
   `dyntex-movie-demo --help` to select an output path, duration, size, or
   device.

4. **Optional: install PsychoPy demo dependencies**:

   ```bash
   pip install "dyntex[psychopy]"
   ```

---

## 4. Run the Demo GUIs

The Simple and Compound PsychoPy examples are standalone scripts. Install the
extra dependency, download the script you need, and run it from its download
directory; cloning the repository is not required:

- **Basic GUI**

  Download [simple_gui.py](https://gitlab.com/dynamic-textures/dyntex-python/-/raw/main/demo/simple_gui.py).

  ```bash
  pip install "dyntex[psychopy]"
  python simple_gui.py
  ```

  It previews one MotionCloud with live controls for spatial frequency,
  orientation, speed, and bandwidth.

- **Composite GUI (blend two MotionClouds)**

  Download [compound_gui.py](https://gitlab.com/dynamic-textures/dyntex-python/-/raw/main/demo/compound_gui.py).

  ```bash
  python compound_gui.py
  ```

  It independently controls two MotionClouds and their blend ratio.

- **Batch generator GUI**

  ```bash
  dyntex-batch-gui
  ```

  Enter comma-separated kernel settings to generate full stimulus grids. The
  default output is MP4, the default device is auto, and duration/burn-in fields
  are entered in milliseconds. The GUI records every generated file in
  `manifest.csv`; the natural kernel exposes `alpha` for the power-law exponent.
  The batch GUI uses Python's Tkinter module; some Linux distributions provide
  it separately as `python3-tk`.

Press **Esc** in the PsychoPy preview windows to exit those demos.

## 5. Run the ModernGL Example

Install the lightweight ModernGL and GLFW dependencies, then launch the viewer:

```bash
pip install "dyntex[opengl]"
dyntex-opengl-demo
```

The OpenGL shader displays the generated grayscale frame without changing its
contrast or color. `modulation_level(elapsed_time)` in `dyntex/opengl_demo.py`
instead controls the MotionCloud bandpass kernel: orientation moves from 15 to
75 degrees while orientation bandwidth moves from 5 to 15 degrees. MotionCloud
generation runs at its declared 60 FPS independently of the monitor refresh
rate. The example uses one temporal simulation step per displayed frame. The
renderer uses an integer-scaled nearest-neighbor viewport
so display resampling cannot attenuate oriented spatial frequencies. Replace the
normalized placeholder with an amplitude envelope, frequency-band energy, beat
strength, or another music-derived feature.

---

## 6. Advanced MotionCloud Options

By default, `MotionCloud` applies the main spatial filter after PDE recursion:

```python
MC = MotionCloud(spatial_filter_mode="post")
```

To reproduce the commuted formulation, apply the spatial filter before
the PDE recursion:

```python
MC = MotionCloud(spatial_filter_mode="pre")  # "legacy" is also accepted
```

The default pole-matched temporal scheme maps the continuous PDE poles with an
exponential and remains stable without a minimum oversampling factor:

```python
MC = MotionCloud(temporal_scheme="pole_matched")
```

The previous explicit finite-difference scheme remains available for
reproducibility:

```python
MC = MotionCloud(temporal_scheme="explicit")  # "legacy" is also accepted
```

---

## 7. Troubleshooting

- **Import errors**: ensure `dyntex` is installed in the active Python environment with `pip install dyntex`.
- **CUDA issues**: verify your GPU drivers and matching CUDA toolkit for the installed PyTorch
- **Psychopy window does not appear**: check display driver compatibility (OpenGL support)

---

## 8. Contributing

Feel free to open issues or pull requests to improve the GUI, add features, or fix bugs. Please follow the repository’s coding style and include descriptive commit messages.

---

DynTex is distributed under the MIT License. See `LICENSE` for details.
