<!-- canonical: efficientnewlanguage.org/ai/examples/889-the-hues-were-averaged-across-the-wrap | ai_layer_version: 0.1.0 | updated: 2026-09-17 -->

# Example 889 — The hues were averaged across the wrap

`the_hues_were_averaged_across_the_wrap.eml` - A palette tool picks an image's representative colour by averaging the hue of every pixel, and the average is exact over every pixel. What the mean of two hues near the seam of the colour wheel is, is computed below.

## EML

```eml
# Self-authored for the EML case corpus (no external origin). A palette tool
# picks an image's representative colour by averaging the hue of every pixel,
# and the average is exact over every pixel. What the mean of two hues near the
# seam of the colour wheel is, is computed below.
#
# The pick is careful. It reads the real hue of every pixel, not a sample; it
# uses the engine's own arithmetic mean; it weights every pixel equally; and the
# intent is exactly 'the hue that represents the image'.
#
# Hue is an angle on a circle that wraps at 360, and two reds - 350 and 10 -
# average arithmetically to 180, which is cyan, the one hue farthest from both.

350 => hue_a_degrees
10 => hue_b_degrees
0 => circular_mean_degrees

hue_a_degrees + hue_b_degrees => hue_sum
int(hue_sum / 2) => arithmetic_mean_degrees
arithmetic_mean_degrees - circular_mean_degrees => degrees_from_the_true_mean
int(degrees_from_the_true_mean * 10000 / 180) => share_of_the_farthest_possible_error_per_myriad

"hue A                           : " + str(hue_a_degrees) + " degrees, a red" ^0
"hue B                           : " + str(hue_b_degrees) + " degrees, a red" ^0
"arithmetic mean                 : " + str(arithmetic_mean_degrees) + " degrees, cyan" ^0
"circular mean                   : " + str(circular_mean_degrees) + " degrees, red" ^0
"error of the arithmetic mean    : " + str(degrees_from_the_true_mean) + " degrees" ^0
"of the farthest possible error  : " + str(share_of_the_farthest_possible_error_per_myriad) + " per ten thousand" ^0
"" ^0

# ---- what the pick verified ----

"the representative-hue pick" ^0
"  reads : the real hue of every pixel" ^0
"  mean : the engine's own arithmetic mean" ^0
"  weighting : every pixel equal" ^0
"  intent : the hue that represents the image" ^0
"  pixels omitted : 0" ^0
"  verdict : MEAN HUE IS 180" ^0
"" ^0
"  taking the exact arithmetic mean of every pixel's real hue" ^0
"  is the part done right here, and it is why 180 is" ^0
"  precisely the mean of the numbers" ^0
"" ^0

# ---- what hue is ----

"hue as a number" ^0
"  what hue is : an angle around a wheel, 0 and 360 the same" ^0
"    colour" ^0
"  where 350 and 10 sit : 20 degrees apart, across the seam" ^0
"  what the arithmetic mean does : treats 350 and 10 as 340" ^0
"    apart and lands halfway, at 180" ^0
"  what 180 is : the hue opposite both inputs" ^0
"  so the representative hue of a red image : cyan" ^0
"" ^0

# ---- what the caller got ----

"the palette" ^0
"  image : reds, 350 and 10" ^0
"  representative hue chosen : " + str(arithmetic_mean_degrees) + ", cyan" ^0
"  is the mean miscomputed : no; it is exact" ^0
"  is a mean of angles the same as a mean of numbers : no;" ^0
"    across the seam it is the opposite" ^0
"" ^0

# ---- null control ----

# The same hues averaged as directions (mean of the unit vectors, then the angle
# of the result), which has no seam.
180 => nc_mean_as_numbers
0 => nc_mean_as_directions
180 => nc_degrees_the_circular_mean_corrects

"null control - average the directions, not the numbers" ^0
"  mean as numbers : " + str(nc_mean_as_numbers) + " degrees" ^0
"  mean as directions : " + str(nc_mean_as_directions) + " degrees" ^0
"  degrees the circular mean corrects : " + str(nc_degrees_the_circular_mean_corrects) ^0
"  no pixel and no hue changed; the mean stopped crossing" ^0
"  the seam" ^0
"" ^0

# ---- the rule ----

"what an arithmetic mean of hues guarantees" ^0
"  the result is the mean of the hue numbers : exactly, every" ^0
"    pixel, the engine's own mean" ^0
"  the result is a hue between the inputs : not addressed;" ^0
"    hue wraps at 360, and two reds at " + str(hue_a_degrees) + " and " + str(hue_b_degrees) + " average to " + str(arithmetic_mean_degrees) + "," ^0
"    the hue opposite both - " + str(share_of_the_farthest_possible_error_per_myriad) + " per ten thousand of the worst" ^0
"    possible error" ^0
"" ^0

"a circle has no smallest number, and a mean that assumes one puts the middle" ^0
"of two neighbours on the far side of the wheel; the same seam that broke" ^0
"longitude at 180 breaks hue at 360, for the same reason" ^0
"" ^0

"It takes the exact arithmetic mean of every pixel's real hue - 180 is the mean" ^0
"of the numbers. But hue is an angle, and " + str(hue_a_degrees) + " and " + str(hue_b_degrees) + " are two reds 20 degrees" ^0
"apart across the seam; their arithmetic mean is " + str(arithmetic_mean_degrees) + ", cyan, " + str(degrees_from_the_true_mean) + " degrees off, until" ^0
"the hues are averaged as directions." ^0
```

## Python (deterministic transpilation)

```python
hue_a_degrees = 350
hue_b_degrees = 10
circular_mean_degrees = 0
hue_sum = hue_a_degrees + hue_b_degrees
arithmetic_mean_degrees = int(hue_sum / 2)
degrees_from_the_true_mean = arithmetic_mean_degrees - circular_mean_degrees
share_of_the_farthest_possible_error_per_myriad = int(degrees_from_the_true_mean * 10000 / 180)
print("hue A                           : " + str(hue_a_degrees) + " degrees, a red")
print("hue B                           : " + str(hue_b_degrees) + " degrees, a red")
print("arithmetic mean                 : " + str(arithmetic_mean_degrees) + " degrees, cyan")
print("circular mean                   : " + str(circular_mean_degrees) + " degrees, red")
print("error of the arithmetic mean    : " + str(degrees_from_the_true_mean) + " degrees")
print("of the farthest possible error  : " + str(share_of_the_farthest_possible_error_per_myriad) + " per ten thousand")
print("")
print("the representative-hue pick")
print("  reads : the real hue of every pixel")
print("  mean : the engine's own arithmetic mean")
print("  weighting : every pixel equal")
print("  intent : the hue that represents the image")
print("  pixels omitted : 0")
print("  verdict : MEAN HUE IS 180")
print("")
print("  taking the exact arithmetic mean of every pixel's real hue")
print("  is the part done right here, and it is why 180 is")
print("  precisely the mean of the numbers")
print("")
print("hue as a number")
print("  what hue is : an angle around a wheel, 0 and 360 the same")
print("    colour")
print("  where 350 and 10 sit : 20 degrees apart, across the seam")
print("  what the arithmetic mean does : treats 350 and 10 as 340")
print("    apart and lands halfway, at 180")
print("  what 180 is : the hue opposite both inputs")
print("  so the representative hue of a red image : cyan")
print("")
print("the palette")
print("  image : reds, 350 and 10")
print("  representative hue chosen : " + str(arithmetic_mean_degrees) + ", cyan")
print("  is the mean miscomputed : no; it is exact")
print("  is a mean of angles the same as a mean of numbers : no;")
print("    across the seam it is the opposite")
print("")
nc_mean_as_numbers = 180
nc_mean_as_directions = 0
nc_degrees_the_circular_mean_corrects = 180
print("null control - average the directions, not the numbers")
print("  mean as numbers : " + str(nc_mean_as_numbers) + " degrees")
print("  mean as directions : " + str(nc_mean_as_directions) + " degrees")
print("  degrees the circular mean corrects : " + str(nc_degrees_the_circular_mean_corrects))
print("  no pixel and no hue changed; the mean stopped crossing")
print("  the seam")
print("")
print("what an arithmetic mean of hues guarantees")
print("  the result is the mean of the hue numbers : exactly, every")
print("    pixel, the engine's own mean")
print("  the result is a hue between the inputs : not addressed;")
print("    hue wraps at 360, and two reds at " + str(hue_a_degrees) + " and " + str(hue_b_degrees) + " average to " + str(arithmetic_mean_degrees) + ",")
print("    the hue opposite both - " + str(share_of_the_farthest_possible_error_per_myriad) + " per ten thousand of the worst")
print("    possible error")
print("")
print("a circle has no smallest number, and a mean that assumes one puts the middle")
print("of two neighbours on the far side of the wheel; the same seam that broke")
print("longitude at 180 breaks hue at 360, for the same reason")
print("")
print("It takes the exact arithmetic mean of every pixel's real hue - 180 is the mean")
print("of the numbers. But hue is an angle, and " + str(hue_a_degrees) + " and " + str(hue_b_degrees) + " are two reds 20 degrees")
print("apart across the seam; their arithmetic mean is " + str(arithmetic_mean_degrees) + ", cyan, " + str(degrees_from_the_true_mean) + " degrees off, until")
print("the hues are averaged as directions.")
```

## stdout (executed)

```text
hue A                           : 350 degrees, a red
hue B                           : 10 degrees, a red
arithmetic mean                 : 180 degrees, cyan
circular mean                   : 0 degrees, red
error of the arithmetic mean    : 180 degrees
of the farthest possible error  : 10000 per ten thousand

the representative-hue pick
  reads : the real hue of every pixel
  mean : the engine's own arithmetic mean
  weighting : every pixel equal
  intent : the hue that represents the image
  pixels omitted : 0
  verdict : MEAN HUE IS 180

  taking the exact arithmetic mean of every pixel's real hue
  is the part done right here, and it is why 180 is
  precisely the mean of the numbers

hue as a number
  what hue is : an angle around a wheel, 0 and 360 the same
    colour
  where 350 and 10 sit : 20 degrees apart, across the seam
  what the arithmetic mean does : treats 350 and 10 as 340
    apart and lands halfway, at 180
  what 180 is : the hue opposite both inputs
  so the representative hue of a red image : cyan

the palette
  image : reds, 350 and 10
  representative hue chosen : 180, cyan
  is the mean miscomputed : no; it is exact
  is a mean of angles the same as a mean of numbers : no;
    across the seam it is the opposite

null control - average the directions, not the numbers
  mean as numbers : 180 degrees
  mean as directions : 0 degrees
  degrees the circular mean corrects : 180
  no pixel and no hue changed; the mean stopped crossing
  the seam

what an arithmetic mean of hues guarantees
  the result is the mean of the hue numbers : exactly, every
    pixel, the engine's own mean
  the result is a hue between the inputs : not addressed;
    hue wraps at 360, and two reds at 350 and 10 average to 180,
    the hue opposite both - 10000 per ten thousand of the worst
    possible error

a circle has no smallest number, and a mean that assumes one puts the middle
of two neighbours on the far side of the wheel; the same seam that broke
longitude at 180 breaks hue at 360, for the same reason

It takes the exact arithmetic mean of every pixel's real hue - 180 is the mean
of the numbers. But hue is an angle, and 350 and 10 are two reds 20 degrees
apart across the seam; their arithmetic mean is 180, cyan, 180 degrees off, until
the hues are averaged as directions.
```

## Round-trip

`ok: true` — round-trip fixpoint reached (python1 == python2)

## Trace event types

eml:run:start · eml:assign · eml:output · eml:run:done
