Skip to content

Testing, and some streamlining, of LUT calibration (& CLI)#36

Open
JorisVincent wants to merge 15 commits into
masterfrom
dev/lut_calibration
Open

Testing, and some streamlining, of LUT calibration (& CLI)#36
JorisVincent wants to merge 15 commits into
masterfrom
dev/lut_calibration

Conversation

@JorisVincent

@JorisVincent JorisVincent commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Provides tests for the measurement routines, and with that the full calibration pipeline.

Mock functionality

To test measurement, provides a MockPhotometer object: corresponds to the full Photometer-class interface, but simulates measurements. It has a current_intensity attribute which should be set to the (gamma-corrected) intensity that would be on the screen. Then, MockPhotometer also holds an LUT, and readLuminance looks up the luminance corresponding to current_intensity. Optionally, it can also simulate 'measurement noise', with a seedable random generator, to provide more realistic measurements.

To set the current_intensity, a mock stimulus drawing function is also used in the tests of the measurement functions.

Tests

This mock setup is used to test the measure_lut function directly (test_measure.py), the whole calibration pipeline end-to-end (test_integration.py), and the hrl-util lut measure and lut verify commands (test_cli.py).
Additionally, the MockPhotometer itself is unit-test (test_mockphotometer.py)

Additional changes

  • round-trip calibration pipeline testing now uses hrl.luts.create_LUT to create synthetic LUTs; and so does generate_test_data.py. This basically ensures there's one place where synthetic LUTs get defined.
    • Also updated how this function works. Primarily a fix that luminance is linear with intensity_in, and intensity_out is gamma'd from there. Also that the linear relationship is done with np.linspace, which ensure better float compatibilty with the MockPhotometer. This also required a corresponding fix in the tests for gamma_correct.
  • measure_lut handles filewriting itself. Previously, this was done through the hrl.rfl attribute and hrl.writeResultsLine function -- but that needlessly couples filewriting to the HRL object.
    • measure_lut also only checks if escape was pressed if there is an inputs device; so not in testing.
  • measure_lut no longer calls .flip() -- this should be done by whatever function draws the calibration stimulus (admittedly, this is primarily to make the mock drawing function more straightforward)

Linear input -> luminance relationship.
Use linspace to define luminances, to be consistent with linearization routines.
Using parametric LUTs from `create_LUT`; `MockPhotometer`
No longer rely on the HRL filewriting, which needlessly coupled responsibilities.
Create LUTs more directly using `create_LUT`, where possible.
Use more realistic scenarios
Uses a mock photometer and mock HRL, to test in the absence of real hardware.
essentially updating the tests in line with cadae73
@JorisVincent
JorisVincent marked this pull request as ready for review July 7, 2026 15:56

@guillermoaguilar guillermoaguilar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written below, I like we include this, to be able to test the pipeline. But I'd do it with gamma values, not with LUT as input.
Then the tests can probe different gammas, noise levels (as you already do), and resolutions. I would find such a design cleaner.

What do you think @JorisVincent ? Is there a reason why to have lut as input?

Comment thread hrl/photometer/mock.py

Parameters
----------
lut : array-like or callable

@guillermoaguilar guillermoaguilar Jul 14, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that we can introduce a mock photometer, so be able to test the whole pipeline. But I am not sure about this design decision, to have a LUT as input.

I think it is cleaner to have a gamma value as input (or 3 gamma values in the case of color), and a default range of luminances. Then the mock photometer calculates luminance using a standard gamma function.

I say this because conceptually, an LUT file is the result of the calibration pipeline, not the input. So it can be confusing what is the Photometer actually mocking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants