Metadata-Version: 2.4
Name: qmeasure
Version: 1.2.1
Summary: Measurement code for condensed matter groups at UW based on QCoDeS.
Author: Christian Rose
Author-email: Jiaqi Cai <jiaqic@mit.edu>, Jack Barlow <barlowmj@uw.edu>, Elliott Runburg <erunburg@uw.edu>, Joshua Wang <wangjo@mit.edu>
License-Expression: GPL-3.0-or-later
Project-URL: Repository, https://github.com/nanophys/MeasureIt
Project-URL: Documentation, https://measureituw.readthedocs.io/en/latest/?badge=latest
Project-URL: Bug Reports, https://github.com/nanophys/MeasureIt/issues
Project-URL: Contributing, https://github.com/nanophys/MeasureIt/blob/main/CONTRIBUTING.md
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20.0
Requires-Dist: scipy>=1.7.0
Requires-Dist: matplotlib>=3.5.0
Requires-Dist: ruamel.yaml>=0.17.0
Requires-Dist: pandas>=1.3.0
Requires-Dist: requests>=2.31.0
Requires-Dist: qcodes>=0.37.0
Requires-Dist: qcodes_contrib_drivers>=0.18.0
Requires-Dist: PyQt5>=5.15.0
Requires-Dist: pyqtgraph>=0.13.0
Requires-Dist: multipyvu>=1.2.0; platform_system == "Windows"
Requires-Dist: platformdirs>=3.0.0
Requires-Dist: ipykernel!=7.*,>=6.29.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pytest-qt>=4.2.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: pre-commit>=2.20.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=5.0.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=1.2.0; extra == "docs"
Requires-Dist: sphinx-autodoc-typehints>=1.19.0; extra == "docs"
Requires-Dist: myst-parser>=0.18.0; extra == "docs"
Provides-Extra: jupyter
Requires-Dist: jupyterlab>=3.4.0; extra == "jupyter"
Requires-Dist: notebook>=6.4.0; extra == "jupyter"
Requires-Dist: ipykernel!=7.*,>=6.29.0; extra == "jupyter"
Requires-Dist: ipython<10,>=8.0.0; extra == "jupyter"
Requires-Dist: jupyter_client>=7.3.0; extra == "jupyter"
Requires-Dist: jupyter_core>=4.11.0; extra == "jupyter"
Requires-Dist: traitlets>=5.3.0; extra == "jupyter"
Requires-Dist: ipython_genutils>=0.2.0; extra == "jupyter"
Provides-Extra: windows
Requires-Dist: pywin32>=304; platform_system == "Windows" and extra == "windows"
Provides-Extra: drivers
Requires-Dist: nidaqmx>=0.6.0; extra == "drivers"
Requires-Dist: zhinst>=21.8.0; extra == "drivers"
Provides-Extra: gui
Provides-Extra: all
Requires-Dist: pytest>=7.0.0; extra == "all"
Requires-Dist: pytest-cov>=4.0.0; extra == "all"
Requires-Dist: pytest-qt>=4.2.0; extra == "all"
Requires-Dist: mypy>=1.0.0; extra == "all"
Requires-Dist: ruff>=0.1.0; extra == "all"
Requires-Dist: pre-commit>=2.20.0; extra == "all"
Requires-Dist: sphinx>=5.0.0; extra == "all"
Requires-Dist: sphinx-rtd-theme>=1.2.0; extra == "all"
Requires-Dist: sphinx-autodoc-typehints>=1.19.0; extra == "all"
Requires-Dist: myst-parser>=0.18.0; extra == "all"
Requires-Dist: jupyterlab>=3.4.0; extra == "all"
Requires-Dist: notebook>=6.4.0; extra == "all"
Requires-Dist: ipykernel!=7.*,>=6.29.0; extra == "all"
Requires-Dist: ipython<10,>=8.0.0; extra == "all"
Requires-Dist: jupyter_client>=7.3.0; extra == "all"
Requires-Dist: jupyter_core>=4.11.0; extra == "all"
Requires-Dist: traitlets>=5.3.0; extra == "all"
Requires-Dist: ipython_genutils>=0.2.0; extra == "all"
Requires-Dist: pywin32>=304; platform_system == "Windows" and extra == "all"
Requires-Dist: nidaqmx>=0.6.0; extra == "all"
Requires-Dist: zhinst>=21.8.0; extra == "all"
Dynamic: license-file

﻿# MeasureIt [![Documentation Status](https://readthedocs.org/projects/measureituw/badge/?version=latest)](https://measureituw.readthedocs.io/en/latest/?badge=latest)

Measurement software based on [QCoDeS](https://qcodes.github.io/), developed in University of Washington physics.

## High-Level Design

MeasureIt is a measurement software package built on top of [QCoDeS](https://qcodes.github.io/) for physics experiments. The architecture follows these key patterns:

### Core Architecture
- **Sweep-based Measurement System**: The core abstraction is the `BaseSweep` class with specialized implementations (`Sweep0D`, `Sweep1D`, `Sweep2D`) for different dimensional measurements
- **Qt-based Threading**: Uses PyQt5 with separate threads for data acquisition (`RunnerThread`) and plotting (`PlotterThread`) 
- **Driver Layer**: Custom instrument drivers in the `Drivers/` module that interface with various lab equipment
- **Notebook Workflow**: Designed for Jupyter/CLI usage; PyQt5 powers background threading and signaling
- **Data Management**: Integration with QCoDeS for data storage and experiment management

See related projects:
- AI enhancement: [AI Integration](https://github.com/caidish/instrMCP)
- WebUI: [Qmeasure Jupyter](https://github.com/caidish/qmeasure-jupyter) (a small jupyterlab extension for generating sweeping code)

### Key Components
- **Base Classes**: `BaseSweep` provides the foundation with parameter following, measurement creation, and thread management
- **Measurement Types**: 
  - 0D (time-based measurements)
  - 1D (single parameter sweep) 
  - 2D (dual parameter sweep)
- **Queue System**: `SweepQueue` for batch experiment execution
- **Real-time Plotting**: Live data visualization during measurements
- **Station Management**: QCoDeS Station integration for instrument management

### Package Structure
```
src/measureit/
    sweep/             # Measurement implementations
    base_sweep.py      # Core sweep functionality
    tools/             # Data utilities and sweep helpers
    Drivers/           # Instrument drivers
    visualization/     # Plotting helpers
```

## Quick Start

### Prerequisites

- Python 3.11+
- NI DAQmx drivers: http://www.ni.com/en-us/support/downloads/drivers/download/unpackaged.ni-daqmx.291872.html
- NI VISA package: http://www.ni.com/download/ni-visa-18.5/7973/en/

## Installation

  ### Using pip (recommended)
  ```bash
  pip install qmeasure
  ```

  **Note:** The package is installed as `qmeasure`, but you import it as `measureit`:
  ```python
  import measureit  # Import name stays the same
  ```

  ### From source
  ```bash
  git clone https://github.com/nanophys/MeasureIt.git
  cd MeasureIt
  pip install -e .
  ```

## Data Directory Configuration

  MeasureIt (installed as `qmeasure`) stores databases, logs, and configuration files. You have three options:

  ### Option 1: Use defaults 
  Data is automatically stored in OS-appropriate locations:
  - **Linux**: `~/.local/share/measureit/`
  - **macOS**: `~/Library/Application Support/measureit/`
  - **Windows**: `C:\Users\<username>\AppData\Local\measureit\`

  ### Option 2: Set environment variable (recommended)
  ```bash
  export MEASUREIT_HOME="/path/to/your/data"  # Linux/macOS
  set MEASUREIT_HOME="C:\path\to\data"        # Windows
  ```

  ### Option 3: Programmatic configuration
  ```python
  import measureit
  measureit.set_data_dir('/custom/path')
  ```


### Updating MeasureIt (development version)

```bash
cd /path/to/MeasureIt
git pull
pip install -e . --upgrade
```

### Known Issues

- `ipykernel` 7.0.x has a dormant event-loop bug that prevents the Qt/pyqtgraph
  plotter from updating. Stick to `ipykernel>=6.29` (or the newer 7.1+ series).

## Installation & Updating

It is useful to first create a conda environment to manage all the required 
packages for this package to work. First, download some form of conda 
(Miniforge3 is strongly recommended since it comes with mamba):

* Download Miniforge: https://github.com/conda-forge/miniforge
* Download Anaconda: https://www.anaconda.com/download/
* Download Miniconda: https://docs.conda.io/projects/miniconda/en/latest/miniconda-install.html


## Basic Usage

### Programmatic Usage

```python
import measureit
from qcodes import Station

# Create a station and add instruments
station = Station()
# ... add your instruments ...

# Choose where databases should be stored (optional)
measureit.set_data_dir("/path/to/measureit-data")

# Create a 1D sweep
sweep = measureit.Sweep1D(
    set_param=dac.voltage,
    start=0,
    stop=1,
    step=0.01,
    inter_delay=0.1
)

# Follow parameters to measure
sweep.follow_param(dmm.voltage, lockin.x)

# Start the measurement
sweep.start()
```

### Sweep Logging

- All sweeps and the `SweepQueue` now log status messages to timestamped files in
  the MeasureIt data directory's ``logs/`` folder (see *Data Directory
  Configuration* above). Each run creates a file named
  ``sweeps_YYYYMMDD_HHMMSS.log`` that captures info/warning/error messages.
- To mirror those messages inside Jupyter notebooks, attach the notebook handler
  once per kernel:

  ```python
  from measureit import attach_notebook_logging

  attach_notebook_logging()
  ```

  The handler safely marshals log output from background Qt threads back into
  the notebook cell output, so database switches and sweep transitions are
  visible while the queue runs.

## Documentation

### Building Documentation

```bash
# Install documentation dependencies
uv pip install -e ".[docs]"  # or pip install -e ".[docs]"

# Build HTML documentation
cd docs/source
make html
```

The documentation is located in the `docs/source` directory. The built documentation will be in `docs/source/_build/html/`.

### Online Documentation

Visit our [online documentation](https://measureituw.readthedocs.io/en/latest/?badge=latest) for detailed guides and API reference.

## Testing

MeasureIt includes a comprehensive test suite to ensure reliability and correctness.

### Running Tests Locally

```bash
# Install development dependencies
pip install -e ".[dev,jupyter]"

# Run all tests
pytest

# Run with coverage report
pytest --cov=src/measureit --cov-report=html

# Run specific test categories
pytest tests/unit -v           # Unit tests only
pytest tests/integration -v    # Integration tests only
pytest -m "not slow"           # Skip slow tests

# Run tests with Qt debugging
export PYTEST_QT_API=pyqt5
export QT_LOGGING_RULES="*.debug=true"
pytest tests/integration -v -s
```

### Test Organization

- **`tests/unit/`**: Fast, isolated unit tests for individual components
- **`tests/integration/`**: Tests for component interactions (Qt threads, signals)
- **`tests/e2e/`**: End-to-end tests for complete workflows
- **`tests/stress/`**: Performance and stress tests

### Test Infrastructure

MeasureIt uses:
- **pytest** with **pytest-qt** for Qt event loop handling
- **pytest-cov** for coverage reporting
- Mock QCoDeS instruments for hardware-independent testing
- Temporary databases and isolated MEASUREIT_HOME per test
- The pytest-qt now creates so much trouble that we do not check it in CI on github workflows. But such a test can still be run locally to verify Qt-related functionality.

### Continuous Integration

All unit tests run automatically on:
- Multiple Python versions (3.11-3.13)
- Multiple operating systems (Linux, Windows, macOS)
- Every push and pull request
  
## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed information about:

- Setting up a development environment
- Code quality standards and tools
- Testing guidelines
- Documentation standards
- Submitting pull requests

For quick development setup:
```bash
# Clone and set up development environment
git clone https://github.com/nanophys/MeasureIt
cd MeasureIt
uv pip install -e ".[dev,docs,jupyter]"  # or pip install -e ".[dev,docs,jupyter]"

# Run tests to verify setup
pytest tests/unit -v
```

## External links and active known users

# Seattle
[David Cobden's lab](https://sites.google.com/uw.edu/nanodevice-physics)

[Xiaodong Xu's lab](https://sites.google.com/uw.edu/xulab)

# Cambridge
[Pablo Jarillo-Herrero's lab](https://jarillo-herrero.mit.edu)

[Long Ju's lab](https://physics.mit.edu/faculty/long-ju)
