Case 951

The meter made the snow grey

the_meter_made_the_snow_grey.eml - A photographer on a ski slope points a calibrated light meter at the snow, sets the camera to exactly what it reads, and gets a frame of grey snow; the same meter pointed at a coal heap gives grey coal. What the meter assumes about the thing it is pointed at is computed below.

ok: true — round-trip fixpoint reached (python1 == python2)updated 2026-09-21

EML

eml
# Self-authored for the EML case corpus (no external origin). A photographer on
# a ski slope points a calibrated light meter at the snow, sets the camera to
# exactly what it reads, and gets a frame of grey snow; the same meter pointed
# at a coal heap gives grey coal. What the meter assumes about the thing it is
# pointed at is computed below.
#
# The reasoning is careful. The meter is calibrated; it measured the light
# actually coming off the snow; the camera was set to the reading exactly; and
# the intent was exactly 'expose this scene correctly'.
#
# A reflected-light meter cannot know how bright a subject is, only how much
# light comes back, so it assumes every scene reflects the eighteen percent of
# an average one and sets the exposure that would render that as mid grey - snow
# reflects ninety, so the meter cuts the exposure five times and renders it
# grey, and coal reflects four, so the meter opens it four and a half times and
# renders that grey too.

18 => reflectance_the_meter_assumes_percent
90 => snow_reflectance_percent
4 => coal_reflectance_percent
4 => two_stops_as_a_light_factor
8 => three_stops_as_a_light_factor

int(snow_reflectance_percent * 10 / reflectance_the_meter_assumes_percent) => snow_exposure_cut_by_the_meter_tenths
int(reflectance_the_meter_assumes_percent * 10 / coal_reflectance_percent) => coal_exposure_opened_by_the_meter_tenths
reflectance_the_meter_assumes_percent => tone_the_snow_is_rendered_at_percent
reflectance_the_meter_assumes_percent => tone_the_coal_is_rendered_at_percent
snow_reflectance_percent - tone_the_snow_is_rendered_at_percent => brightness_the_snow_lost_percent
tone_the_coal_is_rendered_at_percent - coal_reflectance_percent => brightness_the_coal_gained_percent
snow_exposure_cut_by_the_meter_tenths - two_stops_as_a_light_factor * 10 => snow_correction_beyond_two_stops_tenths
three_stops_as_a_light_factor * 10 - snow_exposure_cut_by_the_meter_tenths => snow_correction_short_of_three_stops_tenths
snow_reflectance_percent - coal_reflectance_percent => real_difference_between_snow_and_coal_percent
tone_the_snow_is_rendered_at_percent - tone_the_coal_is_rendered_at_percent => difference_between_them_in_the_frames_percent

"the meter assumes               : a scene reflecting " + str(reflectance_the_meter_assumes_percent) + " percent, mid grey" ^0
"snow reflects                   : " + str(snow_reflectance_percent) + " percent" ^0
"coal reflects                   : " + str(coal_reflectance_percent) + " percent" ^0
"" ^0
"snow, the meter cuts exposure by : a factor of " + str(snow_exposure_cut_by_the_meter_tenths) + " tenths, snow rendered at " + str(tone_the_snow_is_rendered_at_percent) + " percent" ^0
"snow lost                       : " + str(brightness_the_snow_lost_percent) + " points of brightness, white to grey" ^0
"correction the snow needs       : open up by that factor, past two stops (" + str(two_stops_as_a_light_factor) + ") by " + str(snow_correction_beyond_two_stops_tenths) + " tenths, short of three (" + str(three_stops_as_a_light_factor) + ") by " + str(snow_correction_short_of_three_stops_tenths) ^0
"coal, the meter opens exposure by : a factor of " + str(coal_exposure_opened_by_the_meter_tenths) + " tenths, coal rendered at " + str(tone_the_coal_is_rendered_at_percent) + " percent" ^0
"coal gained                     : " + str(brightness_the_coal_gained_percent) + " points of brightness, black to grey" ^0
"snow and coal, in the world     : " + str(real_difference_between_snow_and_coal_percent) + " points apart" ^0
"snow and coal, in the frames    : " + str(difference_between_them_in_the_frames_percent) + " points apart, the same grey" ^0
"" ^0

# ---- what the photographer verified ----

"the trust-the-meter reasoning" ^0
"  meter : calibrated" ^0
"  measurement : the light actually coming off the snow" ^0
"  camera : set to the reading exactly" ^0
"  intent : expose this scene correctly" ^0
"  facts wrong : 0" ^0
"  verdict : THE METER IS RIGHT SO THE EXPOSURE IS RIGHT" ^0
"" ^0
"  measuring the light off the snow with a calibrated meter is" ^0
"  the part done right here, and it is why the reading is an" ^0
"  exact fact about how much light came back" ^0
"" ^0

# ---- what the meter assumes ----

"an instrument with an opinion" ^0
"  what it measures : light coming back from the subject" ^0
"  what it cannot know : whether that is a lot of light off a" ^0
"    dark thing or a little off a bright one" ^0
"  what it does instead : assumes the subject reflects " + str(reflectance_the_meter_assumes_percent) ^0
"    percent, and sets the exposure that renders " + str(reflectance_the_meter_assumes_percent) + " percent as grey" ^0
"  snow : " + str(snow_reflectance_percent) + " percent, so it sends back five times the assumed" ^0
"    light, and the meter cuts five times, to grey" ^0
"  coal : " + str(coal_reflectance_percent) + " percent, so it sends back less than a quarter, and" ^0
"    the meter opens four and a half times, to grey" ^0
"  what the reading is right about : the light; what it is" ^0
"    silent about : the subject" ^0
"" ^0

# ---- what the photographer got ----

"the frames" ^0
"  believed : white snow, black coal, correctly exposed" ^0
"  actual : two greys, " + str(difference_between_them_in_the_frames_percent) + " points apart where the world had " + str(real_difference_between_snow_and_coal_percent) ^0
"  is the meter miscalibrated : no; it measured the light exactly" ^0
"  is the reading the exposure : no; the reading is the light" ^0
"    plus an assumption about the subject, and the assumption" ^0
"    was wrong in both directions" ^0
"" ^0

# ---- null control ----

# The same slope metered for the light falling on it instead of the light
# coming off it.
18 => nc_snow_tone_from_the_reflected_reading_percent
90 => nc_snow_tone_from_the_incident_reading_percent
72 => nc_brightness_the_incident_reading_restores_percent

"null control - meter the light falling on the scene" ^0
"  snow tone, reflected reading : " + str(nc_snow_tone_from_the_reflected_reading_percent) + " percent" ^0
"  snow tone, incident reading : " + str(nc_snow_tone_from_the_incident_reading_percent) + " percent" ^0
"  brightness the incident reading restores : " + str(nc_brightness_the_incident_reading_restores_percent) + " points" ^0
"  no meter was recalibrated; the light was measured before it" ^0
"  met the subject, so no assumption about the subject was needed" ^0
"" ^0

# ---- the rule ----

"what a calibrated reflected-light reading guarantees" ^0
"  the light coming back was this much : exactly" ^0
"  the exposure that renders the subject as it is : not" ^0
"    addressed; the reading carries an assumption of " + str(reflectance_the_meter_assumes_percent) + " percent" ^0
"    reflectance, so snow at " + str(snow_reflectance_percent) + " is cut to grey and coal at " + str(coal_reflectance_percent) + " is" ^0
"    lifted to grey, " + str(brightness_the_snow_lost_percent) + " and " + str(brightness_the_coal_gained_percent) + " points wrong in opposite directions" ^0
"" ^0

"every instrument that cannot see the whole question fills the gap with an" ^0
"assumption, and an assumption is invisible in the reading; the meter was" ^0
"honest about the light and had an opinion about the snow" ^0
"" ^0

"The meter is calibrated and the light it measured is exact. But it assumes" ^0
"the subject reflects " + str(reflectance_the_meter_assumes_percent) + " percent, so " + str(snow_reflectance_percent) + "-percent snow is cut by " + str(snow_exposure_cut_by_the_meter_tenths) + " tenths to grey and" ^0
"" + str(coal_reflectance_percent) + "-percent coal is opened by " + str(coal_exposure_opened_by_the_meter_tenths) + " tenths to the same grey, " + str(difference_between_them_in_the_frames_percent) + " points apart in the frames" ^0
"where the world had " + str(real_difference_between_snow_and_coal_percent) + ", until the assumption in the reading is read along with the light." ^0

Python (deterministic transpilation)

python
reflectance_the_meter_assumes_percent = 18
snow_reflectance_percent = 90
coal_reflectance_percent = 4
two_stops_as_a_light_factor = 4
three_stops_as_a_light_factor = 8
snow_exposure_cut_by_the_meter_tenths = int(snow_reflectance_percent * 10 / reflectance_the_meter_assumes_percent)
coal_exposure_opened_by_the_meter_tenths = int(reflectance_the_meter_assumes_percent * 10 / coal_reflectance_percent)
tone_the_snow_is_rendered_at_percent = reflectance_the_meter_assumes_percent
tone_the_coal_is_rendered_at_percent = reflectance_the_meter_assumes_percent
brightness_the_snow_lost_percent = snow_reflectance_percent - tone_the_snow_is_rendered_at_percent
brightness_the_coal_gained_percent = tone_the_coal_is_rendered_at_percent - coal_reflectance_percent
snow_correction_beyond_two_stops_tenths = snow_exposure_cut_by_the_meter_tenths - two_stops_as_a_light_factor * 10
snow_correction_short_of_three_stops_tenths = three_stops_as_a_light_factor * 10 - snow_exposure_cut_by_the_meter_tenths
real_difference_between_snow_and_coal_percent = snow_reflectance_percent - coal_reflectance_percent
difference_between_them_in_the_frames_percent = tone_the_snow_is_rendered_at_percent - tone_the_coal_is_rendered_at_percent
print("the meter assumes               : a scene reflecting " + str(reflectance_the_meter_assumes_percent) + " percent, mid grey")
print("snow reflects                   : " + str(snow_reflectance_percent) + " percent")
print("coal reflects                   : " + str(coal_reflectance_percent) + " percent")
print("")
print("snow, the meter cuts exposure by : a factor of " + str(snow_exposure_cut_by_the_meter_tenths) + " tenths, snow rendered at " + str(tone_the_snow_is_rendered_at_percent) + " percent")
print("snow lost                       : " + str(brightness_the_snow_lost_percent) + " points of brightness, white to grey")
print("correction the snow needs       : open up by that factor, past two stops (" + str(two_stops_as_a_light_factor) + ") by " + str(snow_correction_beyond_two_stops_tenths) + " tenths, short of three (" + str(three_stops_as_a_light_factor) + ") by " + str(snow_correction_short_of_three_stops_tenths))
print("coal, the meter opens exposure by : a factor of " + str(coal_exposure_opened_by_the_meter_tenths) + " tenths, coal rendered at " + str(tone_the_coal_is_rendered_at_percent) + " percent")
print("coal gained                     : " + str(brightness_the_coal_gained_percent) + " points of brightness, black to grey")
print("snow and coal, in the world     : " + str(real_difference_between_snow_and_coal_percent) + " points apart")
print("snow and coal, in the frames    : " + str(difference_between_them_in_the_frames_percent) + " points apart, the same grey")
print("")
print("the trust-the-meter reasoning")
print("  meter : calibrated")
print("  measurement : the light actually coming off the snow")
print("  camera : set to the reading exactly")
print("  intent : expose this scene correctly")
print("  facts wrong : 0")
print("  verdict : THE METER IS RIGHT SO THE EXPOSURE IS RIGHT")
print("")
print("  measuring the light off the snow with a calibrated meter is")
print("  the part done right here, and it is why the reading is an")
print("  exact fact about how much light came back")
print("")
print("an instrument with an opinion")
print("  what it measures : light coming back from the subject")
print("  what it cannot know : whether that is a lot of light off a")
print("    dark thing or a little off a bright one")
print("  what it does instead : assumes the subject reflects " + str(reflectance_the_meter_assumes_percent))
print("    percent, and sets the exposure that renders " + str(reflectance_the_meter_assumes_percent) + " percent as grey")
print("  snow : " + str(snow_reflectance_percent) + " percent, so it sends back five times the assumed")
print("    light, and the meter cuts five times, to grey")
print("  coal : " + str(coal_reflectance_percent) + " percent, so it sends back less than a quarter, and")
print("    the meter opens four and a half times, to grey")
print("  what the reading is right about : the light; what it is")
print("    silent about : the subject")
print("")
print("the frames")
print("  believed : white snow, black coal, correctly exposed")
print("  actual : two greys, " + str(difference_between_them_in_the_frames_percent) + " points apart where the world had " + str(real_difference_between_snow_and_coal_percent))
print("  is the meter miscalibrated : no; it measured the light exactly")
print("  is the reading the exposure : no; the reading is the light")
print("    plus an assumption about the subject, and the assumption")
print("    was wrong in both directions")
print("")
nc_snow_tone_from_the_reflected_reading_percent = 18
nc_snow_tone_from_the_incident_reading_percent = 90
nc_brightness_the_incident_reading_restores_percent = 72
print("null control - meter the light falling on the scene")
print("  snow tone, reflected reading : " + str(nc_snow_tone_from_the_reflected_reading_percent) + " percent")
print("  snow tone, incident reading : " + str(nc_snow_tone_from_the_incident_reading_percent) + " percent")
print("  brightness the incident reading restores : " + str(nc_brightness_the_incident_reading_restores_percent) + " points")
print("  no meter was recalibrated; the light was measured before it")
print("  met the subject, so no assumption about the subject was needed")
print("")
print("what a calibrated reflected-light reading guarantees")
print("  the light coming back was this much : exactly")
print("  the exposure that renders the subject as it is : not")
print("    addressed; the reading carries an assumption of " + str(reflectance_the_meter_assumes_percent) + " percent")
print("    reflectance, so snow at " + str(snow_reflectance_percent) + " is cut to grey and coal at " + str(coal_reflectance_percent) + " is")
print("    lifted to grey, " + str(brightness_the_snow_lost_percent) + " and " + str(brightness_the_coal_gained_percent) + " points wrong in opposite directions")
print("")
print("every instrument that cannot see the whole question fills the gap with an")
print("assumption, and an assumption is invisible in the reading; the meter was")
print("honest about the light and had an opinion about the snow")
print("")
print("The meter is calibrated and the light it measured is exact. But it assumes")
print("the subject reflects " + str(reflectance_the_meter_assumes_percent) + " percent, so " + str(snow_reflectance_percent) + "-percent snow is cut by " + str(snow_exposure_cut_by_the_meter_tenths) + " tenths to grey and")
print("" + str(coal_reflectance_percent) + "-percent coal is opened by " + str(coal_exposure_opened_by_the_meter_tenths) + " tenths to the same grey, " + str(difference_between_them_in_the_frames_percent) + " points apart in the frames")
print("where the world had " + str(real_difference_between_snow_and_coal_percent) + ", until the assumption in the reading is read along with the light.")

stdout (executed)

text
the meter assumes               : a scene reflecting 18 percent, mid grey
snow reflects                   : 90 percent
coal reflects                   : 4 percent

snow, the meter cuts exposure by : a factor of 50 tenths, snow rendered at 18 percent
snow lost                       : 72 points of brightness, white to grey
correction the snow needs       : open up by that factor, past two stops (4) by 10 tenths, short of three (8) by 30
coal, the meter opens exposure by : a factor of 45 tenths, coal rendered at 18 percent
coal gained                     : 14 points of brightness, black to grey
snow and coal, in the world     : 86 points apart
snow and coal, in the frames    : 0 points apart, the same grey

the trust-the-meter reasoning
  meter : calibrated
  measurement : the light actually coming off the snow
  camera : set to the reading exactly
  intent : expose this scene correctly
  facts wrong : 0
  verdict : THE METER IS RIGHT SO THE EXPOSURE IS RIGHT

  measuring the light off the snow with a calibrated meter is
  the part done right here, and it is why the reading is an
  exact fact about how much light came back

an instrument with an opinion
  what it measures : light coming back from the subject
  what it cannot know : whether that is a lot of light off a
    dark thing or a little off a bright one
  what it does instead : assumes the subject reflects 18
    percent, and sets the exposure that renders 18 percent as grey
  snow : 90 percent, so it sends back five times the assumed
    light, and the meter cuts five times, to grey
  coal : 4 percent, so it sends back less than a quarter, and
    the meter opens four and a half times, to grey
  what the reading is right about : the light; what it is
    silent about : the subject

the frames
  believed : white snow, black coal, correctly exposed
  actual : two greys, 0 points apart where the world had 86
  is the meter miscalibrated : no; it measured the light exactly
  is the reading the exposure : no; the reading is the light
    plus an assumption about the subject, and the assumption
    was wrong in both directions

null control - meter the light falling on the scene
  snow tone, reflected reading : 18 percent
  snow tone, incident reading : 90 percent
  brightness the incident reading restores : 72 points
  no meter was recalibrated; the light was measured before it
  met the subject, so no assumption about the subject was needed

what a calibrated reflected-light reading guarantees
  the light coming back was this much : exactly
  the exposure that renders the subject as it is : not
    addressed; the reading carries an assumption of 18 percent
    reflectance, so snow at 90 is cut to grey and coal at 4 is
    lifted to grey, 72 and 14 points wrong in opposite directions

every instrument that cannot see the whole question fills the gap with an
assumption, and an assumption is invisible in the reading; the meter was
honest about the light and had an opinion about the snow

The meter is calibrated and the light it measured is exact. But it assumes
the subject reflects 18 percent, so 90-percent snow is cut by 50 tenths to grey and
4-percent coal is opened by 45 tenths to the same grey, 0 points apart in the frames
where the world had 86, until the assumption in the reading is read along with the light.

Trace event types

eml:run:starteml:assigneml:outputeml:run:done