# Contributing to Moku Examples

Thank you for your interest in contributing to the Moku Examples repository! This guide will help you set up your development environment and understand our contribution workflow.

# Table of Contents

# Getting Started

# Prerequisites

  • Python 3.9 or higher
  • Git
  • A Moku device for testing
  • Basic familiarity with the Moku API

# Fork and Clone

  1. Fork the repository on GitHub

  2. Clone your fork locally:

    git clone https://github.com/YOUR-USERNAME/moku-examples.git
    cd moku-examples
    
    1
    2
  3. Add the upstream repository:

    git remote add upstream https://github.com/liquidinstruments/moku-examples.git
    
    1

# Development Environment Setup

We use uv for fast, reliable Python package management and uvx to run linting and type-checking tools in the pre-commit hooks. This ensures consistent tool versions without polluting your global Python environment.

# What is uv?

uv (opens new window) is a fast Python package installer and resolver written in Rust. uvx is its command runner that can execute tools in isolated environments.

# Install uv

Choose your platform:

macOS and Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh
1

Windows (PowerShell):

powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
1

Using pip (cross-platform):

pip install uv
1

Using Homebrew (macOS):

brew install uv
1

# Verify Installation

# Check that uv is installed
uv --version

# Check that uvx is available
uvx --version
1
2
3
4
5

Both commands should show version information (e.g., uv 0.5.0).

# 2. Install Python Dependencies

Install the project dependencies using uv sync:

# Sync all dependencies including dev dependencies
uv sync --all-extras

# Or sync with specific extras only
uv sync --extra dev  # Just dev dependencies
uv sync --extra neuralnetwork  # For neural network examples
1
2
3
4
5
6

What does uv sync do?

  • Creates a virtual environment (.venv) if one doesn't exist
  • Installs all project dependencies from pyproject.toml
  • Creates/updates uv.lock for reproducible builds
  • Much faster than traditional pip workflows

Activating the virtual environment: After running uv sync, activate the virtual environment:

# macOS/Linux
source .venv/bin/activate

# Windows
.venv\Scripts\activate
1
2
3
4
5

Or use uv run to run commands directly in the virtual environment without activating:

uv run python python-api/oscilloscope_basic.py
uv run pre-commit run --all-files
1
2

Note: If you prefer using pip:

# Install the Moku API
pip install moku

# Install optional dependencies for specific examples
pip install 'moku[neuralnetwork]'  # For neural network examples

# Install development dependencies (type stubs, etc.)
pip install -e ".[dev]"
1
2
3
4
5
6
7
8

# Why use uv?

  • Speed: Much faster than traditional pip-based workflows (10-100x faster)
  • Reliability: Better dependency resolution and reproducible installs
  • Isolation: Tools run in isolated environments without conflicting with your project dependencies
  • Consistency: Everyone uses the same tool versions
  • Convenience: Automatic virtual environment management

# 3. Install Pre-commit Hooks

We use pre-commit hooks to maintain code quality. This step is required for all contributors.

# Install pre-commit

Using uv (recommended):

uv tool install pre-commit
1

Or using pip:

pip install pre-commit
1

# Set up the hooks

# Install the pre-commit hooks into your git repository
pre-commit install
1
2

This will automatically run code quality checks before each commit using uvx to execute the tools.

# Manual Hook Execution

You can manually run the hooks on all files at any time:

# Run on all files
pre-commit run --all-files

# Run on specific files only
pre-commit run --files python-api/oscilloscope_basic.py
1
2
3
4
5

# 4. Install Additional Tools (Optional)

# For Linting and Type Checking

The pre-commit hooks use ruff and mypy, which are installed automatically via uvx when the hooks run. However, you can install them locally for IDE integration:

Using uv (recommended):

# Install ruff for linting and formatting
uv tool install ruff

# Install mypy for type checking (already included in dev dependencies)
# Type stubs are included in the dev extras via uv sync
1
2
3
4
5

Or using pip:

# Install ruff for linting and formatting
pip install ruff

# Install mypy for type checking
pip install mypy

# Install type stubs for OpenCV (if working with neural network examples)
pip install opencv-stubs
1
2
3
4
5
6
7
8

# For Jupyter Notebooks

If you're working with notebook examples:

Using uv:

uv tool install jupyter
uv pip install notebook ipykernel
1
2

Or using pip:

pip install jupyter notebook ipykernel
1

# 5. Verify Your Setup

Test that everything is working:

# Run the pre-commit hooks (using uv run if you haven't activated the venv)
uv run pre-commit run --all-files

# Or if you've activated the virtual environment:
pre-commit run --all-files

# Should see output like:
# ruff-check...............................................................Passed
# ruff-format..............................................................Passed
# mypy.....................................................................Passed
1
2
3
4
5
6
7
8
9
10

# Code Quality Standards

We enforce code quality using automated tools. All contributions must pass these checks.

# Pre-commit Hooks

The repository uses three pre-commit hooks:

  1. ruff-check: Linting (checks for code issues)

    • Checks: pycodestyle errors (E), warnings (W), pyflakes (F), import sorting (I)
    • Auto-fixes: Import sorting, some code issues
  2. ruff-format: Code formatting

    • Enforces consistent code style
    • Auto-formats: Line length (110 chars), quotes, spacing
  3. mypy: Type checking

    • Checks: Type annotations and type consistency
    • Python version: 3.9+

# Configuration

Code quality settings are defined in pyproject.toml. Key settings:

[tool.ruff]
line-length = 110
target-version = "py38"

[tool.mypy]
python_version = "3.9"
ignore_missing_imports = true  # Lenient for examples
1
2
3
4
5
6
7

# Common Issues and Fixes

# Ambiguous variable names

# ❌ Bad - single letter that looks like zero/one
O = np.pi / np.array([o for o in range(8, 64)])

# ✅ Good - descriptive name
omega = np.pi / np.array([o for o in range(8, 64)])
1
2
3
4
5

# Bare except clauses

# ❌ Bad - catches everything
try:
    data = device.get_data()
except:
    data = None

# ✅ Good - specific exception types
try:
    data = device.get_data()
except (KeyError, IndexError):
    data = None
1
2
3
4
5
6
7
8
9
10
11

# Boolean comparisons

# ❌ Bad - explicit comparison to False
while status == False:
    do_something()

# ✅ Good - pythonic boolean check
while not status:
    do_something()
1
2
3
4
5
6
7

# Type hints for matplotlib

# ❌ Bad - list instead of tuple
ax.set_xlim([0, 10])

# ✅ Good - tuple for axis limits
ax.set_xlim((0, 10))
1
2
3
4
5

# Contribution Workflow

# 1. Create a Branch

# Update your local main branch
git checkout main
git pull upstream main

# Create a feature branch
git checkout -b feature/your-feature-name
1
2
3
4
5
6

Use descriptive branch names:

  • feature/add-oscilloscope-fft-example
  • fix/phasemeter-streaming-bug
  • docs/improve-neural-network-readme

# 2. Make Your Changes

  • Write clear, well-commented code
  • Follow existing code style in the repository
  • Test your code with actual Moku hardware if possible
  • Update documentation as needed

# 3. Commit Your Changes

The pre-commit hooks will run automatically:

git add .
git commit -m "Add oscilloscope FFT example"
1
2

If the hooks fail:

  1. Review the error messages
  2. Fix the issues (some are auto-fixed)
  3. Stage the changes again: git add .
  4. Commit again

# 4. Push and Create a Pull Request

git push origin feature/your-feature-name
1

Then create a Pull Request on GitHub with:

  • Clear title describing the change
  • Description of what the PR does
  • Any testing performed
  • Screenshots/plots if applicable

# Example Guidelines

# File Naming

Use descriptive, lowercase names with underscores:

  • oscilloscope_fft_analysis.py
  • waveformgenerator_swept_sine.py
  • neural_network_pid_control.ipynb

# Code Structure

# Python Scripts (.py)

# Brief description of what the example does
#
# (c) 2024 Liquid Instruments Pty. Ltd.

from moku.instruments import Oscilloscope

# Configuration constants
MOKU_IP = '192.168.1.100'  # Update with your device IP
SAMPLE_RATE = '1MSa/s'

try:
    # Connect to device
    osc = Oscilloscope(MOKU_IP, force_connect=True)

    # Configure instrument
    osc.set_timebase(0, 1e-3)

    # Your example code here

finally:
    # Always close the connection
    osc.relinquish_ownership()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Jupyter Notebooks (.ipynb)

  • Start with a markdown cell explaining the purpose
  • Use markdown headers to organize sections
  • Include visualization outputs
  • Add explanatory text between code cells
  • Clear all outputs before committing (optional, but keeps diffs clean)

# Documentation in Examples

Each example should include:

  1. Header comment: Brief description and date
  2. Inline comments: Explain non-obvious code
  3. Configuration section: Clearly marked parameters users need to change
  4. Error handling: Use try/finally for cleanup
  5. Output: Print relevant information or generate plots

# IP Address Handling

Never commit your actual device IP. Use placeholder or example IPs:

# ✅ Good
MOKU_IP = '192.168.1.100'  # Update with your device IP

# ✅ Also good
MOKU_IP = '192.168.###.###'  # Replace with your device IP

# ❌ Bad (reveals your network)
MOKU_IP = '192.168.50.247'
1
2
3
4
5
6
7
8

# Testing Your Changes

# Manual Testing

  1. Test with actual hardware if possible
  2. Verify the example runs without errors
  3. Check outputs (plots, data files, console output)
  4. Test error conditions (e.g., wrong IP, disconnected device)

# Pre-commit Testing

Always run before pushing:

# Test all files
pre-commit run --all-files

# Test specific files you changed
pre-commit run --files python-api/your_new_example.py
1
2
3
4
5

# Notebook Testing

For Jupyter notebooks:

# Run the notebook and check for errors
jupyter nbconvert --to notebook --execute your_notebook.ipynb
1
2

# Questions?

# Code of Conduct

  • Be respectful and constructive
  • Help others learn
  • Focus on what is best for the community
  • Show empathy towards other contributors

Thank you for contributing to Moku Examples! Your contributions help others learn and build with Moku devices.