photoelastimetry¶
Package for processing polarised images to measure stress in granular media
Installation¶
To install the package, run the following command in the terminal:
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.
Arguments:
json_filename: Path to the JSON5 parameter file containing configuration (required)--output: Path to save the output stress map image (optional)
Example:
The JSON5 parameter file should contain:
folderName: Path to folder containing raw photoelastic imagesC: Stress-optic coefficient in 1/Pathickness: Sample thickness in meterswavelengths: List of wavelengths in nanometersS_i_hat: Incoming normalized Stokes vector [S1_hat, S2_hat, S3_hat] representing polarization statecrop(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.
Arguments:
json_filename: Path to the JSON5 parameter file containing configuration (required)
Example:
The JSON5 parameter file should contain:
p_filename: Path to the photoelastimetry parameter filestress_filename: Path to the stress field data filet: Thickness of the photoelastic materiallambda_light: Wavelength of light used in the experimentC: Stress-optic coefficient of the materialscattering(optional): Gaussian filter sigma for scattering simulationoutput_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:
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
}