Skip to content

photoelastimetry

Tests codecov Code style: black Python 3.9+ License: GPL v3

Package for processing polarised images to measure stress in granular media

Installation

To install the package, run the following command in the terminal:

pip install photoelastimetry

Documentation

Full documentation is available here.

Usage

After installation, two command line scripts are available:

image-to-stress

Converts photoelastic images to stress maps using the stress-optic law and polarisation analysis.

image-to-stress <json_filename> [--output OUTPUT]

Arguments:

  • json_filename: Path to the JSON5 parameter file containing configuration (required)
  • --output: Path to save the output stress map image (optional)

Example:

image-to-stress params.json5 --output stress_map.png

The JSON5 parameter file should contain:

  • folderName: Path to folder containing raw photoelastic images
  • C: Stress-optic coefficient in 1/Pa
  • thickness: Sample thickness in meters
  • wavelengths: List of wavelengths in nanometers
  • S_i_hat: Incoming normalized Stokes vector [S1_hat, S2_hat, S3_hat] representing polarization state
  • crop (optional): Crop region as [y1, y2, x1, x2]
  • debug (optional): If true, display all channels for debugging

stress-to-image

Converts stress field data to photoelastic fringe pattern images.

stress-to-image <json_filename>

Arguments:

  • json_filename: Path to the JSON5 parameter file containing configuration (required)

Example:

stress-to-image params.json5

The JSON5 parameter file should contain:

  • p_filename: Path to the photoelastimetry parameter file
  • stress_filename: Path to the stress field data file
  • t: Thickness of the photoelastic material
  • lambda_light: Wavelength of light used in the experiment
  • C: Stress-optic coefficient of the material
  • scattering (optional): Gaussian filter sigma for scattering simulation
  • output_filename (optional): Path for the output image (default: "output.png")

demosaic-raw

De-mosaics a raw polarimetric image from a camera with a 4x4 superpixel pattern into separate colour and polarisation channels.

demosaic-raw <input_file> [--width WIDTH] [--height HEIGHT] [--dtype DTYPE] [--output-prefix PREFIX] [--format FORMAT] [--all]

Arguments:

  • input_file: Path to the raw image file, or directory when using --all (required)
  • --width: Image width in pixels (default: 4096)
  • --height: Image height in pixels (default: 3000)
  • --dtype: Data type, either 'uint8' or 'uint16' (auto-detected if not specified)
  • --output-prefix: Prefix for output files (default: input filename without extension)
  • --format: Output format, either 'tiff' or 'png' (default: 'tiff')
  • --all: Recursively process all .raw files in the input directory and subdirectories

Examples:

# Save as a single TIFF stack
demosaic-raw image.raw --width 2448 --height 2048 --dtype uint16 --format tiff

# Save as four separate PNG files (one per polarisation angle)
demosaic-raw image.raw --width 2448 --height 2048 --format png --output-prefix output

# Process all raw files in a directory recursively
demosaic-raw images/ --format png --all

Output formats:

  • tiff: Creates a single TIFF file with shape [H/4, W/4, 4, 4] containing all colour channels (R, G1, G2, B) and polarisation angles (0°, 45°, 90°, 135°)
  • png: Creates 4 PNG files (one per polarisation angle), each containing all colour channels as a composite image

Development

To set up the development environment, clone the repository and install the package in editable mode with development dependencies:

git clone https://github.com/benjym/photoelastimetry.git
cd photoelastimetry
pip install -e ".[dev]"
# Set up pre-commit hooks
pre-commit install

Running Tests

The project uses pytest for testing with comprehensive coverage analysis:

# Run all tests
pytest

# Run tests with coverage report
pytest --cov=photoelastimetry --cov-report=html

# Run specific test file
pytest tests/test_stokes_solver_pytest.py -v

# Run tests in parallel (faster)
pytest -n auto

Code Coverage

View the coverage report by opening htmlcov/index.html in your browser after running tests with coverage enabled.

Current test coverage includes: - Stokes solver: photoelastic stress recovery using normalised Stokes parameters - Intensity solver: raw intensity-based stress recovery with noise modelling - Equilibrium solver: global stress field recovery enforcing mechanical equilibrium - Disk simulations: synthetic photoelastic data generation - Image processing: retardance, principal angle, and Mueller matrix calculations

Code Quality

The project uses black for code formatting and flake8 for linting:

# Format code
black photoelastimetry tests

# Check code style
flake8 photoelastimetry

Continuous Integration

GitHub Actions automatically runs tests on: - Python 3.9, 3.10, 3.11, and 3.12 - Multiple operating systems (Ubuntu) - Every push and pull request

Test coverage is automatically uploaded to Codecov for tracking.

Authors

Usage

The code is run by calling python photoelastimetry/local.py <json5 file>. The parameters for the experiment are stored in the json5 file. The default parameters, contained in json/params.json5 are as follows:

{
    // Incoming normalized Stokes vector [S1_hat, S2_hat, S3_hat]
    // For linear polarizer at 0°: [1.0, 0.0, 0.0]
    // For linear polarizer at 45°: [0.0, 1.0, 0.0]
    // For circular polarizer: [0.0, 0.0, 1.0]
    S_i_hat : [1.0, 0.0, 0.0], // Incoming polarization state
    wavelengths : [650, 550, 450], // R, G, B wavelengths (nm)
    C : [2e-12,2e-12,2e-12], // stress-optic coefficient for each wavelength (1/Pa)
    thickness : 0.01, // thickness of sample in m
    polarisation_efficiency : 0.95,
    folderName : "images/2025_05_06/2025_05_06_11_51_53_010/02002060_diskSaving1",
    debug: false
}