✈ Contrail Formation Predictor

Atmospheric data at cruise altitudes • Schmidt-Appleman criterion • Updated 2026-10-29 10:01 UTC

Headline result

Comparing forecast classes only within each city (Mantel–Haenszel, 33 cities carrying both classes), the PERSISTENT–EPHEMERAL detection gap is +32pp (95% CI [+30, +34]pp) on n = 13296 city-hours across 108 observation days.

Honest caveat: about 11% of the raw pooled +36pp gap is city mix, not forecast class; stratifying by city removes it. The interval sits well clear of zero over 108 observation days, so the sign and significance are robust on this sample. Every figure here is recomputed live from scorecard.json — see the rolling scorecard below for the full derivation.

Detector limit: the satellite detector this gap is measured against has a held-out recall of only about 1.1%, so it sees few real contrails; the gap compares what it does flag, not all contrails.

Current Status — Major Cities
Columbus, OH
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
17:00–18:00 UTC (PERSISTENT, 1 h)
Denver, CO
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
00:00–00:00 UTC (PERSISTENT, 24 h)
Seattle, WA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Chicago, IL
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
12:00–21:00 UTC (PERSISTENT, 9 h)
New York, NY
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Miami, FL
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Los Angeles, CA
Persistent
PERSISTENT 3/3 levels PERSISTENT
right now
CONTRAIL WINDOW (48h)
07:00–19:00 UTC (PERSISTENT, 12 h)
Dallas, TX
Persistent
PERSISTENT 2/3 levels PERSISTENT
right now
CONTRAIL WINDOW (48h)
10:00–23:00 UTC (PERSISTENT, 13 h)
Anchorage, AK
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
12:00–17:00 UTC (PERSISTENT, 5 h)
Mexico City, MX
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Atlanta, GA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Houston, TX
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
23:00–07:00 UTC (PERSISTENT, 8 h)
St. Louis, MO
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
03:00–14:00 UTC (PERSISTENT, 11 h)
Kansas City, MO
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
15:00–00:00 UTC (PERSISTENT, 9 h)
Memphis, TN
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
17:00–02:00 UTC (PERSISTENT, 9 h)
Nashville, TN
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
15:00–21:00 UTC (PERSISTENT, 6 h)
Indianapolis, IN
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
14:00–16:00 UTC (PERSISTENT, 2 h)
Detroit, MI
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
19:00–23:00 UTC (PERSISTENT, 4 h)
Minneapolis, MN
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
13:00–22:00 UTC (PERSISTENT, 9 h)
Charlotte, NC
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
12:00–13:00 UTC (PERSISTENT, 1 h)
Pittsburgh, PA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Boston, MA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Philadelphia, PA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Washington, DC
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
New Orleans, LA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
02:00–00:00 UTC (PERSISTENT, 22 h)
Oklahoma City, OK
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
20:00–00:00 UTC (PERSISTENT, 28 h)
Omaha, NE
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
14:00–00:00 UTC (PERSISTENT, 10 h)
Milwaukee, WI
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
13:00–22:00 UTC (PERSISTENT, 9 h)
Phoenix, AZ
Persistent
PERSISTENT 1/3 levels PERSISTENT
right now
CONTRAIL WINDOW (48h)
09:00–19:00 UTC (PERSISTENT, 34 h)
San Francisco, CA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
15:00–05:00 UTC (PERSISTENT, 14 h)
Portland, OR
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
12:00–14:00 UTC (PERSISTENT, 2 h)
Salt Lake City, UT
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
11:00–09:00 UTC (PERSISTENT, 22 h)
San Diego, CA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
21:00–05:00 UTC (PERSISTENT, 8 h)
Las Vegas, NV
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
11:00–11:00 UTC (PERSISTENT, 24 h)
São Paulo, BR
Persistent
PERSISTENT 1/3 levels PERSISTENT
right now
CONTRAIL WINDOW (48h)
08:00–11:00 UTC (PERSISTENT, 3 h)
London, UK
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
00:00–05:00 UTC (PERSISTENT, 5 h)
Paris, FR
Persistent
PERSISTENT 1/3 levels PERSISTENT
right now
CONTRAIL WINDOW (48h)
00:00–11:00 UTC (PERSISTENT, 11 h)
Frankfurt, DE
Persistent
PERSISTENT 2/3 levels PERSISTENT
right now
CONTRAIL WINDOW (48h)
04:00–12:00 UTC (PERSISTENT, 8 h)
Reykjavík, IS
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
00:00–05:00 UTC (PERSISTENT, 5 h)
Moscow, RU
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
12:00–00:00 UTC (PERSISTENT, 12 h)
Cairo, EG
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Dubai, AE
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Johannesburg, ZA
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
all 48 h (EPHEMERAL)
Delhi, India
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
00:00–06:00 UTC (PERSISTENT, 6 h)
Tokyo, JP
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
18:00–20:00 UTC (PERSISTENT, 2 h)
Singapore, SG
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
06:00–11:00 UTC (PERSISTENT, 5 h)
Sydney, AU
Ephemeral
EPHEMERAL
right now
CONTRAIL WINDOW (48h)
21:00–22:00 UTC (PERSISTENT, 1 h)
All Locations — 47 cities, worldwide

Every row below is a full Schmidt-Appleman forecast, precomputed from Open-Meteo pressure-level data. The forecaster is not limited to these cities — the same core runs for any coordinate on Earth:

python predictor.py --latlon 52.52 13.40 "Berlin, DE"

Add --json for a machine-readable payload (location, 48h contrail window, per-hour classification series). This static page ships a curated set so no live backend is needed; the forecast_location(lat, lon, name) function behind it will forecast anywhere on demand.

Peak RHice is the highest ice-relative humidity at any cruise level in the next 48h; “N h ≥90%” counts hours where any level came within 10% of ice saturation, so quiet cities are ordered by how close they came to persistence. “Mean” is the 48-hour average of the most humid level’s RHice; it is what actually tells quiet cities apart, because some cruise level sits below Tc in nearly every hour everywhere, so the closest approach to Tc is nearly identical in most cities and is shown only when it exceeds the 0.5°C grid-resolution floor.“Closest approach” is the smallest gap between ambient temperature and the Schmidt-Appleman threshold Tc at any cruise level in the next 48h: above Tc is too warm for any contrail, below Tc the temperature test is met.

Location ↕ Lat, Lon ↕ Now (this hour) ↕ Levels persistent now ↕ Next 48h: window & hours by class ↕ Peak RHice 48h ↕ Forecast horizon ↕
Phoenix, AZ33.45, -112.07Now: PERSISTENT
48h: mostly PERSISTENT
1/3
levels persistent this hour
09:00–19:00 UTC (PERSISTENT, 34 h)
35h persistent · 13h ephemeral · 0h none
mean 110.7% over 48h
peak 148.3%
41h ≥90%
to 10-31 23:00 UTC
Salt Lake City, UT40.76, -111.89Now: EPHEMERAL
48h: mostly PERSISTENT
0/3
levels persistent this hour
11:00–09:00 UTC (PERSISTENT, 22 h)
31h persistent · 17h ephemeral · 0h none
mean 96.1% over 48h
closest approach: 3.1°C below Tc (300 hPa, 10-29 08:00 UTC)
peak 129.1%
33h ≥90%
to 10-31 23:00 UTC
Oklahoma City, OK35.47, -97.52Now: EPHEMERAL
48h: mostly PERSISTENT
0/3
levels persistent this hour
20:00–00:00 UTC (PERSISTENT, 28 h)
30h persistent · 18h ephemeral · 0h none
mean 102.0% over 48h
peak 151.4%
31h ≥90%
to 10-31 23:00 UTC
Moscow, RU55.76, 37.62Now: EPHEMERAL
48h: mostly PERSISTENT
0/3
levels persistent this hour
12:00–00:00 UTC (PERSISTENT, 12 h)
28h persistent · 20h ephemeral · 0h none
mean 98.1% over 48h
closest approach: 5.1°C below Tc (300 hPa, 10-30 08:00 UTC)
peak 104.2%
39h ≥90%
to 10-31 23:00 UTC
Dallas, TX32.78, -96.80Now: PERSISTENT
48h: mostly PERSISTENT
2/3
levels persistent this hour
10:00–23:00 UTC (PERSISTENT, 13 h)
27h persistent · 21h ephemeral · 0h none
mean 102.6% over 48h
closest approach: 2.7°C below Tc (250 hPa, 10-29 02:00 UTC)
peak 142.8%
32h ≥90%
to 10-31 23:00 UTC
Denver, CO39.74, -104.98Now: EPHEMERAL
48h: mostly PERSISTENT
0/3
levels persistent this hour
00:00–00:00 UTC (PERSISTENT, 24 h)
26h persistent · 22h ephemeral · 0h none
mean 96.5% over 48h
closest approach: 1.1°C below Tc (300 hPa, 10-30 14:00 UTC)
peak 141.0%
28h ≥90%
to 10-31 23:00 UTC
New Orleans, LA29.95, -90.07Now: EPHEMERAL
48h: mostly PERSISTENT
0/3
levels persistent this hour
02:00–00:00 UTC (PERSISTENT, 22 h)
24h persistent · 24h ephemeral · 0h none
mean 95.3% over 48h
closest approach: 0.7°C below Tc (250 hPa, 10-29 21:00 UTC)
peak 143.0%
30h ≥90%
to 10-31 23:00 UTC
Las Vegas, NV36.17, -115.14Now: EPHEMERAL
48h: mostly PERSISTENT
0/3
levels persistent this hour
11:00–11:00 UTC (PERSISTENT, 24 h)
24h persistent · 24h ephemeral · 0h none
mean 94.0% over 48h
closest approach: 1.6°C below Tc (300 hPa, 10-29 00:00 UTC)
peak 145.3%
27h ≥90%
to 10-31 23:00 UTC
Kansas City, MO39.10, -94.58Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
15:00–00:00 UTC (PERSISTENT, 9 h)
22h persistent · 26h ephemeral · 0h none
mean 93.1% over 48h
peak 139.1%
27h ≥90%
to 10-31 23:00 UTC
San Francisco, CA37.77, -122.42Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
15:00–05:00 UTC (PERSISTENT, 14 h)
19h persistent · 29h ephemeral · 0h none
mean 94.2% over 48h
closest approach: 2.6°C below Tc (300 hPa, 10-29 00:00 UTC)
peak 135.4%
31h ≥90%
to 10-31 23:00 UTC
San Diego, CA32.72, -117.16Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
21:00–05:00 UTC (PERSISTENT, 8 h)
18h persistent · 30h ephemeral · 0h none
mean 82.0% over 48h
closest approach: 0.6°C below Tc (300 hPa, 10-29 01:00 UTC)
peak 141.4%
26h ≥90%
to 10-31 23:00 UTC
St. Louis, MO38.63, -90.20Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
03:00–14:00 UTC (PERSISTENT, 11 h)
18h persistent · 30h ephemeral · 0h none
mean 79.0% over 48h
peak 136.1%
22h ≥90%
to 10-31 23:00 UTC
Paris, FR48.86, 2.35Now: PERSISTENT
48h: mostly EPHEMERAL
1/3
levels persistent this hour
00:00–11:00 UTC (PERSISTENT, 11 h)
18h persistent · 30h ephemeral · 0h none
mean 100.7% over 48h
peak 171.4%
21h ≥90%
to 10-31 23:00 UTC
Omaha, NE41.26, -95.93Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
14:00–00:00 UTC (PERSISTENT, 10 h)
18h persistent · 30h ephemeral · 0h none
mean 85.2% over 48h
peak 139.6%
20h ≥90%
to 10-31 23:00 UTC
Singapore, SG1.35, 103.82Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
06:00–11:00 UTC (PERSISTENT, 5 h)
17h persistent · 31h ephemeral · 0h none
mean 95.2% over 48h
closest approach: 1.8°C above Tc (250 hPa, 10-30 02:00 UTC)
peak 105.1%
39h ≥90%
to 10-31 23:00 UTC
Los Angeles, CA34.05, -118.24Now: PERSISTENT
48h: mostly EPHEMERAL
3/3
levels persistent this hour
07:00–19:00 UTC (PERSISTENT, 12 h)
16h persistent · 32h ephemeral · 0h none
mean 81.4% over 48h
closest approach: 1.1°C below Tc (300 hPa, 10-29 01:00 UTC)
peak 145.2%
22h ≥90%
to 10-31 23:00 UTC
Houston, TX29.76, -95.37Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
23:00–07:00 UTC (PERSISTENT, 8 h)
15h persistent · 33h ephemeral · 0h none
mean 100.2% over 48h
closest approach: 1.2°C below Tc (250 hPa, 10-29 17:00 UTC)
peak 146.4%
30h ≥90%
to 10-31 23:00 UTC
Frankfurt, DE50.11, 8.68Now: PERSISTENT
48h: mostly EPHEMERAL
2/3
levels persistent this hour
04:00–12:00 UTC (PERSISTENT, 8 h)
15h persistent · 33h ephemeral · 0h none
mean 90.6% over 48h
closest approach: 1.1°C below Tc (300 hPa, 10-30 21:00 UTC)
peak 162.5%
19h ≥90%
to 10-31 23:00 UTC
Chicago, IL41.88, -87.63Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
12:00–21:00 UTC (PERSISTENT, 9 h)
14h persistent · 34h ephemeral · 0h none
mean 78.4% over 48h
closest approach: 1.6°C below Tc (300 hPa, 10-29 01:00 UTC)
peak 141.9%
18h ≥90%
to 10-31 23:00 UTC
Minneapolis, MN44.98, -93.27Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
13:00–22:00 UTC (PERSISTENT, 9 h)
13h persistent · 35h ephemeral · 0h none
mean 72.6% over 48h
closest approach: 2.6°C below Tc (300 hPa, 10-29 00:00 UTC)
peak 123.8%
18h ≥90%
to 10-31 23:00 UTC
Anchorage, AK61.22, -149.90Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
12:00–17:00 UTC (PERSISTENT, 5 h)
12h persistent · 36h ephemeral · 0h none
mean 65.8% over 48h
peak 102.3%
18h ≥90%
to 10-31 23:00 UTC
Milwaukee, WI43.04, -87.91Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
13:00–22:00 UTC (PERSISTENT, 9 h)
11h persistent · 37h ephemeral · 0h none
mean 82.7% over 48h
closest approach: 1.6°C below Tc (300 hPa, 10-29 02:00 UTC)
peak 146.8%
22h ≥90%
to 10-31 23:00 UTC
Nashville, TN36.16, -86.78Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
15:00–21:00 UTC (PERSISTENT, 6 h)
11h persistent · 37h ephemeral · 0h none
mean 70.9% over 48h
closest approach: 0.9°C above Tc (300 hPa, 10-29 00:00 UTC)
peak 126.9%
17h ≥90%
to 10-31 23:00 UTC
Detroit, MI42.33, -83.05Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
19:00–23:00 UTC (PERSISTENT, 4 h)
11h persistent · 37h ephemeral · 0h none
mean 70.4% over 48h
closest approach: 1.6°C below Tc (300 hPa, 10-29 09:00 UTC)
peak 111.0%
14h ≥90%
to 10-31 23:00 UTC
Memphis, TN35.15, -90.05Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
17:00–02:00 UTC (PERSISTENT, 9 h)
10h persistent · 38h ephemeral · 0h none
mean 84.3% over 48h
closest approach: 1.9°C above Tc (300 hPa, 10-29 01:00 UTC)
peak 124.7%
20h ≥90%
to 10-31 23:00 UTC
São Paulo, BR-23.55, -46.63Now: PERSISTENT
48h: mostly EPHEMERAL
1/3
levels persistent this hour
08:00–11:00 UTC (PERSISTENT, 3 h)
8h persistent · 40h ephemeral · 0h none
mean 83.5% over 48h
peak 104.0%
33h ≥90%
to 10-31 23:00 UTC
London, UK51.51, -0.13Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
00:00–05:00 UTC (PERSISTENT, 5 h)
7h persistent · 41h ephemeral · 0h none
mean 88.9% over 48h
peak 130.0%
25h ≥90%
to 10-31 23:00 UTC
Delhi, India28.61, 77.21Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
00:00–06:00 UTC (PERSISTENT, 6 h)
6h persistent · 42h ephemeral · 0h none
mean 61.2% over 48h
peak 105.6%
17h ≥90%
to 10-31 23:00 UTC
Reykjavík, IS64.15, -21.94Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
00:00–05:00 UTC (PERSISTENT, 5 h)
5h persistent · 43h ephemeral · 0h none
mean 41.4% over 48h
closest approach: 0.9°C below Tc (200 hPa, 10-30 17:00 UTC)
peak 164.4%
6h ≥90%
to 10-31 23:00 UTC
Tokyo, JP35.68, 139.69Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
18:00–20:00 UTC (PERSISTENT, 2 h)
3h persistent · 45h ephemeral · 0h none
mean 64.4% over 48h
peak 106.6%
14h ≥90%
to 10-31 23:00 UTC
Portland, OR45.52, -122.68Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
12:00–14:00 UTC (PERSISTENT, 2 h)
2h persistent · 46h ephemeral · 0h none
mean 53.9% over 48h
closest approach: 4.9°C below Tc (200 hPa, 10-30 23:00 UTC)
peak 110.1%
5h ≥90%
to 10-31 23:00 UTC
Indianapolis, IN39.77, -86.16Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
14:00–16:00 UTC (PERSISTENT, 2 h)
2h persistent · 46h ephemeral · 0h none
mean 61.6% over 48h
peak 105.0%
2h ≥90%
to 10-31 23:00 UTC
Sydney, AU-33.87, 151.21Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
21:00–22:00 UTC (PERSISTENT, 1 h)
1h persistent · 47h ephemeral · 0h none
mean 65.0% over 48h
peak 100.2%
15h ≥90%
to 10-31 23:00 UTC
Charlotte, NC35.23, -80.84Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
12:00–13:00 UTC (PERSISTENT, 1 h)
1h persistent · 47h ephemeral · 0h none
mean 53.3% over 48h
closest approach: 0.9°C above Tc (300 hPa, 10-29 00:00 UTC)
peak 105.8%
5h ≥90%
to 10-31 23:00 UTC
Columbus, OH39.96, -82.99Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
17:00–18:00 UTC (PERSISTENT, 1 h)
1h persistent · 47h ephemeral · 0h none
mean 54.4% over 48h
peak 101.5%
1h ≥90%
to 10-31 23:00 UTC
No persistent hours in the next 48h, ordered by hours within 10% of ice saturation (still searchable). Unless a row says otherwise, each shows: all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
Dubai, AE25.20, 55.27Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-29 13:00 UTC, 300 hPa
mean 49.4% over 48h
closest approach: 0.9°C above Tc (300 hPa, 10-29 17:00 UTC)
peak 100.0%
11h ≥90%
to 10-31 23:00 UTC
Miami, FL25.76, -80.19Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 23:00 UTC, 300 hPa
mean 49.3% over 48h
peak 110.2%
6h ≥90%
to 10-31 23:00 UTC
Atlanta, GA33.75, -84.39Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 11:00 UTC, 300 hPa
mean 66.3% over 48h
closest approach: 1.9°C above Tc (300 hPa, 10-29 00:00 UTC)
peak 105.7%
6h ≥90%
to 10-31 23:00 UTC
Pittsburgh, PA40.44, -79.99Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 20:00 UTC, 200 hPa
mean 52.4% over 48h
peak 96.3%
3h ≥90%
to 10-31 23:00 UTC
Mexico City, MX19.43, -99.13Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-29 03:00 UTC, 250 hPa
mean 41.7% over 48h
peak 97.9%
2h ≥90%
to 10-31 23:00 UTC
Boston, MA42.36, -71.06Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 09:00 UTC, 300 hPa
mean 45.0% over 48h
closest approach: 1.1°C below Tc (300 hPa, 10-29 00:00 UTC)
peak 96.8%
1h ≥90%
to 10-31 23:00 UTC
Philadelphia, PA39.95, -75.16Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 23:00 UTC, 200 hPa
mean 46.7% over 48h
peak 87.5%
0h ≥90%
to 10-31 23:00 UTC
New York, NY40.71, -74.01Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 03:00 UTC, 200 hPa
mean 44.9% over 48h
peak 86.0%
0h ≥90%
to 10-31 23:00 UTC
Washington, DC38.91, -77.04Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-29 00:00 UTC, 300 hPa
mean 43.5% over 48h
peak 82.2%
0h ≥90%
to 10-31 23:00 UTC
Cairo, EG30.04, 31.24Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 21:00 UTC, 250 hPa
mean 36.6% over 48h
peak 77.4%
0h ≥90%
to 10-31 23:00 UTC
Johannesburg, ZA-26.20, 28.05Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-29 21:00 UTC, 200 hPa
mean 51.0% over 48h
closest approach: 3.2°C below Tc (250 hPa, 10-29 08:00 UTC)
peak 76.0%
0h ≥90%
to 10-31 23:00 UTC
Seattle, WA47.61, -122.33Now: EPHEMERAL
48h: mostly EPHEMERAL
0/3
levels persistent this hour
all 48 h (EPHEMERAL)
0h persistent · 48h ephemeral · 0h none
closest to persistence: 10-30 14:00 UTC, 300 hPa
mean 32.5% over 48h
closest approach: 3.4°C below Tc (200 hPa, 10-30 23:00 UTC)
peak 46.8%
0h ≥90%
to 10-31 23:00 UTC

Click a column header to sort; type above to filter. “Now” and “N/3 levels persistent” describe the current hour only; “48h: mostly…” and the window cover the next 48 hours, so a city can show “Now: EPHEMERAL”, “48h: mostly PERSISTENT” and 0/3 at once (e.g. Seattle): the humid spell simply hasn't arrived yet. Likewise a city can read “Now: PERSISTENT” yet “48h: mostly EPHEMERAL” (e.g. San Francisco); the two labels cover different time scopes, not a contradiction. The hour counts under each window are the real per-city numbers.

72-Hour Timeline — Columbus, OH

Each pixel = 1 hour. Hover for time + status.

2026-10-29T00:00 UTC: Ephemeral2026-10-29T01:00 UTC: Ephemeral2026-10-29T02:00 UTC: Ephemeral2026-10-29T03:00 UTC: Ephemeral2026-10-29T04:00 UTC: Ephemeral2026-10-29T05:00 UTC: Ephemeral2026-10-29T06:00 UTC: Ephemeral2026-10-29T07:00 UTC: Ephemeral2026-10-29T08:00 UTC: Ephemeral2026-10-29T09:00 UTC: Ephemeral2026-10-29T10:00 UTC: Ephemeral2026-10-29T11:00 UTC: Ephemeral2026-10-29T12:00 UTC: Ephemeral2026-10-29T13:00 UTC: Ephemeral2026-10-29T14:00 UTC: Ephemeral2026-10-29T15:00 UTC: Ephemeral2026-10-29T16:00 UTC: Ephemeral2026-10-29T17:00 UTC: Ephemeral2026-10-29T18:00 UTC: Ephemeral2026-10-29T19:00 UTC: Ephemeral2026-10-29T20:00 UTC: Ephemeral2026-10-29T21:00 UTC: Ephemeral2026-10-29T22:00 UTC: Ephemeral2026-10-29T23:00 UTC: Ephemeral2026-10-30T00:00 UTC: Ephemeral2026-10-30T01:00 UTC: Ephemeral2026-10-30T02:00 UTC: Ephemeral2026-10-30T03:00 UTC: Ephemeral2026-10-30T04:00 UTC: Ephemeral2026-10-30T05:00 UTC: Ephemeral2026-10-30T06:00 UTC: Ephemeral2026-10-30T07:00 UTC: Ephemeral2026-10-30T08:00 UTC: Ephemeral2026-10-30T09:00 UTC: Ephemeral2026-10-30T10:00 UTC: Ephemeral2026-10-30T11:00 UTC: Ephemeral2026-10-30T12:00 UTC: Ephemeral2026-10-30T13:00 UTC: Ephemeral2026-10-30T14:00 UTC: Ephemeral2026-10-30T15:00 UTC: Ephemeral2026-10-30T16:00 UTC: Ephemeral2026-10-30T17:00 UTC: Persistent2026-10-30T18:00 UTC: Ephemeral2026-10-30T19:00 UTC: Ephemeral2026-10-30T20:00 UTC: Ephemeral2026-10-30T21:00 UTC: Ephemeral2026-10-30T22:00 UTC: Ephemeral2026-10-30T23:00 UTC: Ephemeral2026-10-31T00:00 UTC: Ephemeral2026-10-31T01:00 UTC: Ephemeral2026-10-31T02:00 UTC: Ephemeral2026-10-31T03:00 UTC: Ephemeral2026-10-31T04:00 UTC: Persistent2026-10-31T05:00 UTC: Persistent2026-10-31T06:00 UTC: Persistent2026-10-31T07:00 UTC: Persistent2026-10-31T08:00 UTC: Persistent2026-10-31T09:00 UTC: Persistent2026-10-31T10:00 UTC: Persistent2026-10-31T11:00 UTC: Persistent2026-10-31T12:00 UTC: Persistent2026-10-31T13:00 UTC: Persistent2026-10-31T14:00 UTC: Persistent2026-10-31T15:00 UTC: Persistent2026-10-31T16:00 UTC: Persistent2026-10-31T17:00 UTC: Persistent2026-10-31T18:00 UTC: Persistent2026-10-31T19:00 UTC: Persistent2026-10-31T20:00 UTC: Persistent2026-10-31T21:00 UTC: Persistent2026-10-31T22:00 UTC: Persistent2026-10-31T23:00 UTC: Persistent10/2910/3010/31NOW
No contrails
Ephemeral (dissolve quickly)
Persistent (contrail cirrus)
48-Hour Detail — Columbus, OH (3 pressure levels)

T = temperature at pressure level • RH = relative humidity w.r.t. ice • [N/3] = persistent level count

Time (UTC)200 hPa (FL387)250 hPa (FL344)300 hPa (FL295)Status
10-29 00:00 UTC-58.5°C / 26% RH_ice-50.5°C / 35% RH_ice-42.5°C / 45% RH_iceEphemeral
10-29 01:00 UTC-58.5°C / 26% RH_ice-50.5°C / 26% RH_ice-42.5°C / 48% RH_iceEphemeral
10-29 02:00 UTC-59.0°C / 26% RH_ice-50.5°C / 18% RH_ice-43.0°C / 57% RH_iceEphemeral
10-29 03:00 UTC-58.5°C / 26% RH_ice-50.5°C / 14% RH_ice-43.0°C / 42% RH_iceEphemeral
10-29 04:00 UTC-58.0°C / 22% RH_ice-50.5°C / 21% RH_ice-43.0°C / 42% RH_iceEphemeral
10-29 05:00 UTC-58.5°C / 26% RH_ice-50.0°C / 21% RH_ice-42.5°C / 18% RH_iceEphemeral
10-29 06:00 UTC-58.5°C / 26% RH_ice-49.0°C / 14% RH_ice-41.5°C / 15% RH_iceEphemeral
10-29 07:00 UTC-58.5°C / 31% RH_ice-49.0°C / 14% RH_ice-41.0°C / 12% RH_iceEphemeral
10-29 08:00 UTC-58.5°C / 31% RH_ice-49.0°C / 14% RH_ice-40.0°C / 9% RH_iceEphemeral
10-29 09:00 UTC-58.5°C / 39% RH_ice-49.5°C / 14% RH_ice-40.0°C / 9% RH_iceEphemeral
10-29 10:00 UTC-58.5°C / 34% RH_ice-49.0°C / 14% RH_ice-40.0°C / 9% RH_iceEphemeral
10-29 11:00 UTC-58.5°C / 34% RH_ice-49.0°C / 14% RH_ice-40.0°C / 9% RH_iceEphemeral
10-29 12:00 UTC-58.5°C / 39% RH_ice-49.5°C / 17% RH_ice-40.0°C / 9% RH_iceEphemeral
10-29 13:00 UTC-58.5°C / 42% RH_ice-49.5°C / 17% RH_ice-40.5°C / 9% RH_iceEphemeral
10-29 14:00 UTC-59.0°C / 51% RH_ice-49.5°C / 17% RH_ice-40.5°C / 6% RH_iceEphemeral
10-29 15:00 UTC-59.0°C / 65% RH_ice-49.5°C / 17% RH_ice-41.0°C / 15% RH_iceEphemeral
10-29 16:00 UTC-59.0°C / 68% RH_ice-50.0°C / 21% RH_ice-41.0°C / 15% RH_iceEphemeral
10-29 17:00 UTC-59.5°C / 77% RH_ice-50.0°C / 29% RH_ice-41.0°C / 15% RH_iceEphemeral
10-29 18:00 UTC-59.5°C / 74% RH_ice-50.5°C / 29% RH_ice-41.5°C / 12% RH_iceEphemeral
10-29 19:00 UTC-59.5°C / 74% RH_ice-51.0°C / 26% RH_ice-41.5°C / 12% RH_iceEphemeral
10-29 20:00 UTC-60.5°C / 74% RH_ice-51.0°C / 26% RH_ice-41.5°C / 15% RH_iceEphemeral
10-29 21:00 UTC-60.0°C / 57% RH_ice-51.0°C / 43% RH_ice-41.5°C / 12% RH_iceEphemeral
10-29 22:00 UTC-60.0°C / 52% RH_ice-51.0°C / 61% RH_ice-41.5°C / 33% RH_iceEphemeral
10-29 23:00 UTC-59.5°C / 48% RH_ice-51.0°C / 50% RH_ice-41.5°C / 36% RH_iceEphemeral
10-30 00:00 UTC-59.5°C / 39% RH_ice-51.0°C / 18% RH_ice-41.5°C / 38% RH_iceEphemeral
10-30 01:00 UTC-60.0°C / 34% RH_ice-51.0°C / 18% RH_ice-41.5°C / 9% RH_iceEphemeral
10-30 02:00 UTC-61.0°C / 40% RH_ice-51.0°C / 18% RH_ice-41.5°C / 9% RH_iceEphemeral
10-30 03:00 UTC-60.5°C / 40% RH_ice-51.5°C / 21% RH_ice-41.5°C / 9% RH_iceEphemeral
10-30 04:00 UTC-60.5°C / 40% RH_ice-51.5°C / 21% RH_ice-41.5°C / 12% RH_iceEphemeral
10-30 05:00 UTC-61.0°C / 43% RH_ice-52.0°C / 26% RH_ice-42.0°C / 15% RH_iceEphemeral
10-30 06:00 UTC-61.0°C / 43% RH_ice-52.0°C / 32% RH_ice-42.0°C / 15% RH_iceEphemeral
10-30 07:00 UTC-61.5°C / 49% RH_ice-52.0°C / 26% RH_ice-42.0°C / 15% RH_iceEphemeral
10-30 08:00 UTC-61.0°C / 48% RH_ice-51.5°C / 21% RH_ice-42.0°C / 15% RH_iceEphemeral
10-30 09:00 UTC-61.0°C / 43% RH_ice-51.5°C / 26% RH_ice-42.5°C / 18% RH_iceEphemeral
10-30 10:00 UTC-61.0°C / 43% RH_ice-51.5°C / 29% RH_ice-42.5°C / 30% RH_iceEphemeral
10-30 11:00 UTC-61.0°C / 48% RH_ice-51.0°C / 18% RH_ice-42.5°C / 39% RH_iceEphemeral
10-30 12:00 UTC-61.5°C / 52% RH_ice-51.0°C / 14% RH_ice-42.5°C / 45% RH_iceEphemeral
10-30 13:00 UTC-62.0°C / 70% RH_ice-51.0°C / 26% RH_ice-42.5°C / 33% RH_iceEphemeral
10-30 14:00 UTC-61.5°C / 83% RH_ice-50.5°C / 35% RH_ice-42.5°C / 45% RH_iceEphemeral
10-30 15:00 UTC-61.5°C / 78% RH_ice-51.0°C / 58% RH_ice-42.0°C / 54% RH_iceEphemeral
10-30 16:00 UTC-62.0°C / 84% RH_ice-50.5°C / 38% RH_ice-42.0°C / 54% RH_iceEphemeral
10-30 17:00 UTC-62.5°C / 102% RH_ice-51.0°C / 43% RH_ice-42.0°C / 42% RH_icePersistent[1/3]
10-30 18:00 UTC-63.0°C / 88% RH_ice-51.0°C / 43% RH_ice-42.0°C / 33% RH_iceEphemeral
10-30 19:00 UTC-63.0°C / 79% RH_ice-51.5°C / 36% RH_ice-42.0°C / 42% RH_iceEphemeral
10-30 20:00 UTC-62.5°C / 70% RH_ice-51.5°C / 47% RH_ice-42.0°C / 33% RH_iceEphemeral
10-30 21:00 UTC-61.5°C / 66% RH_ice-52.0°C / 53% RH_ice-42.0°C / 39% RH_iceEphemeral
10-30 22:00 UTC-61.5°C / 75% RH_ice-52.0°C / 53% RH_ice-42.0°C / 45% RH_iceEphemeral
10-30 23:00 UTC-61.5°C / 61% RH_ice-52.0°C / 68% RH_ice-42.0°C / 65% RH_iceEphemeral
Validation — METAR High-Cloud Correlation (15-Day Hindcast)

Method: 15-day hindcast via Open-Meteo + IEM ASOS hourly sky conditions. High cloud = any sky layer ≥ 20,000 ft (FEW/SCT/BKN/OVC) in the METAR report of the nearest major airport. The table shows: when we predict PERSISTENT or EPHEMERAL, how often does the METAR show high-altitude cloudiness?


Note: METAR high cloud ≠ contrail observation. Natural cirrus and contrail cirrus are indistinguishable. London EGLL uses automated ceilometers (NCD = No Cloud Detected) that cannot detect thin cirrus — excluded from aggregate. Miami shows equal high-cloud rates for both classes due to tropical convective cirrus (not sensitive to upper-tropospheric humidity). This is a directional sanity check, not a precision/recall measurement.

City Predicted Hours High Cloud When Predicted
Columbus, OHPERSISTENT6162%
Columbus, OHEPHEMERAL28740%
Denver, COPERSISTENT3686%
Denver, COEPHEMERAL31256%
Seattle, WAPERSISTENT7478%
Seattle, WAEPHEMERAL27436%
Chicago, ILPERSISTENT4070%
Chicago, ILEPHEMERAL30859%
New York, NYPERSISTENT4185%
New York, NYEPHEMERAL30770%
Miami, FLPERSISTENT8685%
Miami, FLEPHEMERAL26285%
Los Angeles, CAPERSISTENT3020%
Los Angeles, CAEPHEMERAL3181%
London, UKPERSISTENT187— (63% NCD — ceilometer blind to thin cirrus)
London, UKEPHEMERAL173— (87% NCD — ceilometer blind to thin cirrus)
All 7 cirrus-capable stationsPERSISTENT36873%
All 7 cirrus-capable stationsEPHEMERAL206849%

6/7 cities show higher high-cloud agreement for PERSISTENT than EPHEMERAL. Aggregate: PERSISTENT = 73% vs EPHEMERAL = 49% (Δ = +24pp, ex-London). Miami is a special case: tropical convective cirrus saturates both classes at ~85%. This layer cannot separate contrail cirrus from natural cirrus — see the GOES-19 satellite layer below, which can.

Validation — GOES-19 Linear-Contrail Detection (Satellite)

Why a second layer: the METAR table above cannot tell a contrail from natural cirrus. This layer can, because it keys on the one thing natural cirrus is not: linearity.


Method: GOES-19 ABI split-window brightness-temperature difference (C13 10.3µm − C15 12.3µm) over a ~200 km box per city. Thin ice cloud shows a positive BTD. A bank of oriented line filters then scores each pixel by how much more it responds along its best orientation than along a typical one — large for a long, narrow contrail, ~0 for a diffuse cirrus deck — normalised by local BTD variability so the test does not simply re-flag any high-contrast scene.


Data: s3://noaa-goes19 ABI-L1b-RadC (public, no credentials). Window 2026-06-15 → 2026-06-29, 4×/day, 406 city-hours. GOES-19 is used rather than GOES-16 — GOES-16 ABI stopped producing CONUS imagery on 2025-04-07 when it was retired as GOES-East. GOES-19 carries the same instrument in the same slot. Only cities GOES-East can actually see are scored — membership is computed from a geometric limb test, not a hand-kept list (see the data-integrity note in the robustness panel for why that distinction cost us four bad city-hours).

Predicted City-Hours Linear Contrail Detected Mean Thin-Ice Cover
PERSISTENT5466.7%34.5%
EPHEMERAL35248.6%21.5%
City PERSISTENT EPHEMERAL Ordered?
columbus60% (10)56% (48)✓
denver75% (4)74% (54)✓
seattle92% (12)70% (46)✓
chicago67% (6)56% (52)✓
nyc71% (7)53% (51)✓
miami58% (12)33% (46)✓
la0% (3)2% (55)·

When we predict PERSISTENT, GOES-19 finds a linear contrail overhead 67% of the time, vs 49% for EPHEMERAL (Δ = +18pp). 6/7 cities show the correct ordering — the same score the independent METAR layer reaches, from a different instrument.

Null test: the classes are very unequal (54 PERSISTENT vs 352 EPHEMERAL), so a gap this size could in principle be small-sample noise. Shuffling the predicted labels against the observations 20,000 times reproduces a gap this large in p = 0.010 of shuffles — so the signal is unlikely to be chance.

Honest caveat: the city-level rates above (does this city-hour show a linear contrail overhead, yes/no) are a coarser measure than pixel-level precision/recall, so they are not restated as calibrated numbers here. The same detector has since been calibrated pixel-by-pixel against OpenContrails human labels — see the calibration panel below (6.3% precision, 1.9% recall, 32× lift over chance at the shipped threshold) — so the detector overall is no longer uncalibrated, even though this panel's own city-level rates are not the calibrated figures. Only the relative ordering between classes at this city-level granularity is claimed from this panel alone. Los Angeles is the outlier in both layers — June marine-layer subsidence leaves it with almost no upper-level ice cloud for either class to work with.

Detector calibration — scored against human labels

The panel above establishes that PERSISTENT scenes score higher than EPHEMERAL ones. It never established that what the detector flags is a contrail — so the standing caveat was “uncalibrated; only the class ordering is meaningful.” This panel replaces that caveat with a measured number by scoring the detector directly against all 151 human-labelled scenes (40 containing contrails) in the OpenContrails validation shards on disk — OpenContrails (Ng et al. 2023, CC BY 4.0). Labels are pixel-level; we score the aggregated ground truth (a pixel counts as contrail when >50% of annotators marked it).

anisotropy threshold precision recall F1 lift vs chance
0.250.33%18.95%0.0062×
0.51.09%9.31%0.0206×
0.752.94%4.17%0.03515×
1.0 ← shipped6.30%1.94%0.03032×
1.2511.77%0.91%0.01760×
1.517.39%0.39%0.00888×
1.7530.25%0.18%0.004153×
2.042.86%0.08%0.002217×
2.560.00%0.03%0.001304×
3.0100.00%0.01%0.000506×
0%25%50%75%100%shipped 0.251.02.03.0 anisotropy threshold (local σ) precision recall

What this says, plainly. At the shipped operating point the detector reaches 6.3% precision and 1.9% recall (F1 0.030). In absolute terms that is a weak segmenter — it finds a small minority of contrail pixels and most of what it flags is not one. But contrail pixels are only 0.20% of all pixels, so that precision is 32× better than chance. Both halves of that sentence are the result: the detector is emphatically not a random number generator, which is what licenses the class-ordering claim above — and it is also nowhere near good enough to call a contrail segmenter.

How sure are we? Bootstrapping over scenes (10,000 resamples with replacement, seed 0) puts a 95% confidence interval of 2.0–11.3% on precision and 0.7–3.2% on recall. The interval is wide — contrail pixels are rare, so the numbers ride on the 40 labelled scenes that contain one — but even the lower precision bound of 2.0% is about 10× the 0.20% base rate, so “far above chance” survives the uncertainty; “a good segmenter” does not.

It behaves like a real detector. Sweeping the anisotropy threshold traces a clean precision/recall trade-off — precision climbs monotonically from 1.1% to 100% as the threshold tightens, while recall falls. A noise source has no such curve. That monotonic ordering, not any single point, is the strongest single piece of evidence that the line filter is keying on real linear structure.

Where the signal comes from. The brightness-temperature candidate gate alone scores 0.14% precision — at or below the 0.20% base rate, i.e. no better than guessing. The oriented line filter supplies essentially all of the discriminative power. That is a load-bearing detail: the physics gate finds cold thin ice, which over CONUS is mostly ordinary cirrus; only the anisotropy test asks the question that separates a contrail from the cirrus around it.

Where the recall goes. The candidate gate keeps only 25% of human-labelled contrail pixels before the line filter ever runs, so it — not the line filter — is the ceiling on recall. The gate demands cold (BT13 < 273 K) and thin-ice (BTD > 0.5 K); a young or semi-transparent contrail over warm ground satisfies neither cleanly. Raising recall means loosening the physics gate, not sharpening the anisotropy test.

Not results-shopping. The +18pp separation above was measured at the shipped threshold (1.0) and is not restated at any other value. Best F1 over the sweep is 0.035 at threshold 0.75; that is reported as an observation for future work, not retro-fitted to the published headline.

Honest caveat — GOES-16 labels, GOES-19 detector. OpenContrails labels GOES-16 scenes; the dataset predates GOES-16's retirement as GOES-East on 2025-04-07. Our detector runs on GOES-19, which took the same 75.2°W slot with the same ABI instrument and the same bands — so the calibration should transfer, but it was measured on GOES-16 and applied to GOES-19. These are not numbers measured on our own scenes.

Session 28 — a second satellite (GOES-West / GOES-18). Western and Pacific-facing cities (LA, Seattle, Phoenix, San Francisco, Portland, Salt Lake City, San Diego, Las Vegas) sit deep in the GOES-East limb, where a fixed-degree box foreshortens badly. They are now scored by GOES-18 (137.2°W), which gives them near-nadir geometry. Each city is assigned to its best-geometry satellite by the same derived limb test that keeps Tokyo out — never a hand-kept list. G18 carries the identical ABI instrument, product and C13/C15 bands, so the detector is band-for-band applicable, and as of Session 29 the transfer is measured, not assumed: the same city-hours in the FOV overlap (8 western cities, 2026-07-18 to 2026-07-24) were scored through both satellites with the shared calibration — Cohen's kappa 0.64 (95% CI [0.57, 0.71]), concordance 83.0%, n=448 paired city-hours, detection rate G19 43.5% vs G18 31.5%. That is at least moderate agreement at the interval floor — the transfer holds on real scenes, with the interval still to tighten. West cities enter as new-roster strata and accrue forward-only, so they accelerate future evidence rather than tightening today's CI.

Rolling forecast-vs-GOES scorecard — a growing track record

The satellite panels above are a one-time check over a fixed June window. This one turns that into an ongoing, append-only track record: every day a scheduled job takes the forecast that was already archived before that day (a genuine forecast with real lead time, not a hindcast) and scores it against what the calibrated GOES-19 detector actually observed over each CONUS city's footprint. It grows one day at a time.

Read this as small-sample, weak-detector evidence — because it is. The detector is a weak segmenter (~6% pixel precision; see the calibration panel), so a single day's per-city detection bool is noisy. Daily samples are a handful of cities × a few hours, so early numbers carry almost no statistical power — only the accumulated contrast means anything. At cruise altitude in summer nearly every hour forecasts EPHEMERAL and NONE is essentially never forecast, so the literal PERSISTENT-vs-NONE table is near-empty; the useful signal is whether the detection rate rises from EPHEMERAL to PERSISTENT. And the detector is calibrated on GOES-16 labels but run on GOES-19.

Cumulative over 108 day(s) (2026-06-28 → 2026-10-28) — how often GOES saw a linear contrail, by forecast class:

forecast class city-hours contrail seen detection rate 95% CI (Wilson)
None443273%—
Ephemeral10679392237%[36–38%]
Persistent2617191073%[71–75%]

The detection rate rises from 37% (EPHEMERAL, n = 10679) to 73% (PERSISTENT, n = 2617), a +36pp gap (bootstrap 95% CI [+34, +38]pp) that is now statistically distinguishable from zero — two-sided Fisher's exact p < 0.001, and the bootstrap gap CI excludes zero. That pooled number is confounded, though — see the city-stratified check below, which is the one to believe.

Robustness check: the pooled gap is inflated by which city, not just by forecast class

Baseline detectability varies enormously between cities — cirrus climatology, viewing geometry and GOES scan angle differ, and the table below shows per-city detection rates spanning nearly the full range. The PERSISTENT hours are not spread evenly across those cities, so pooling every city-hour together lets “this sample came from an easy-to-see city” masquerade as “this sample was forecast PERSISTENT.” That is Simpson's paradox, and it is the obvious way this panel could fool itself.

Comparing classes only within each city and averaging (Mantel–Haenszel risk difference, 33 cities carrying both classes) gives +32pp (95% CI [+30, +34]pp) — against the pooled +36pp. 11% of the headline gap was city mix. On the current sample the within-city gap survives stratification: the honest reading is that the ordering is real but smaller than the pooled number suggests.

-20 -10 +0 +10 +20 +30 +40 +32.3pp, Wald 95% [+30.8, +34.5] 2026-06-30 2026-10-28 Stratified gap, PERSISTENT minus EPHEMERAL detection rate (pp), cumulative to each day observation day (first point has 4 informative cities, last 33) band = Wald 95%; the headline CI is a bootstrap, so its bounds differ slightly

How the stratified gap accrued: each point recomputes it from only the days up to then. It starts noisy with few informative cities and settles as days are added.

city PERSISTENT seen EPHEMERAL seen within-city gap
seattle89% (n=138)54% (n=316)+35pp
mexico79% (n=126)56% (n=278)+23pp
nyc77% (n=120)43% (n=332)+33pp
milwaukee84% (n=116)47% (n=275)+36pp
miami49% (n=112)36% (n=340)+14pp
chicago78% (n=109)47% (n=351)+31pp
columbus73% (n=105)39% (n=354)+35pp
omaha83% (n=104)50% (n=288)+33pp
minneapolis88% (n=102)52% (n=288)+36pp
pittsburgh79% (n=97)45% (n=295)+35pp
boston88% (n=96)48% (n=296)+39pp
portland79% (n=94)40% (n=277)+39pp
detroit86% (n=93)41% (n=299)+44pp
philadelphia77% (n=86)42% (n=306)+34pp
stlouis76% (n=85)36% (n=307)+40pp
indianapolis77% (n=83)41% (n=309)+36pp
washington73% (n=83)39% (n=309)+34pp
denver89% (n=81)68% (n=379)+21pp
kansascity79% (n=71)39% (n=321)+40pp
sanfrancisco51% (n=70)15% (n=303)+37pp
houston36% (n=69)24% (n=323)+12pp
saltlakecity91% (n=67)59% (n=305)+32pp
charlotte64% (n=59)27% (n=333)+37pp
neworleans36% (n=58)25% (n=334)+11pp
atlanta62% (n=53)27% (n=339)+35pp
nashville65% (n=51)26% (n=341)+39pp
dallas56% (n=50)18% (n=354)+38pp
memphis57% (n=46)25% (n=346)+31pp
oklahomacity61% (n=46)26% (n=346)+35pp
phoenix67% (n=43)33% (n=335)+35pp
lasvegas62% (n=39)27% (n=338)+34pp
sandiego38% (n=34)16% (n=344)+22pp
la39% (n=31)16% (n=418)+23pp

Two kinds of stratum carry no trustworthy within-city signal and are held out of the estimate separately. Single-class (none): only one forecast class was ever observed, so there is no contrast at all. Small-cell (none): both classes appear but one has fewer than 3 observations, so its rate is one or two coin-flips — exactly the noise that let a lone PERSISTENT hour in Denver drag the average by tens of points. Leave-one-day-out over the 108 observation days moves the pooled gap between +36pp and +37pp, and the city-stratified gap between +32pp and +33pp (both sign-stable): no single day flips the direction. The point estimate is robust to dropping any one day; the stratified interval sits well clear of zero over 108 observation days, so the sign and significance are robust on this sample.

How the estimate got here: the CONUS roster was tripled to 33+ GOES-East cities (adding humid mid-continent and eastern locations that generate PERSISTENT hours), a minimum-cell rule (3 observations per class) was added to drop noise strata like Denver's single PERSISTENT hour, and every reachable trailing day of archived forecasts was scored. Effect on the honest headline: the city-stratified estimate moved to +32.3pp (95% CI [+30, +34]pp), which now separates from zero — the deadlock the earlier straddling-CI reported is broken on the current sample.

Is Mantel–Haenszel itself the right pooling choice? A second, independently-weighted stratified estimator — inverse-variance-weighted fixed-effect meta-analysis, which weights each city's within-city gap by 1/variance instead of MH's sample-size-only weight — run over the same 33 informative cities gives +32.6pp (95% CI [+31, +34]pp) against MH's +32.3pp. The two agree in sign with overlapping intervals, so the estimator choice is not carrying the result.

New-roster watch (since 2026-07-22): 29 additional GOES-East cities joined the roster but hold no honest history — a forecast must predate its observation, so they can only validate forward via the daily timer, never by backfill. So far they have accrued 98 obs day(s) and 9336 city-hour(s), and on the current sample they are corroborating it — folding them in lifts the stratified gap (a shift of +4.2pp). This line updates itself from scorecard.json as the new cities accumulate.

Per-day record (detected / forecast, newest first):

obs date (UTC) P+E+N city-hrs median lead PERSISTENT EPHEMERAL
2026-10-2813218.5h34/4435/88
2026-10-2713217.0h28/3447/98
2026-10-2613226.7h41/5236/80
2026-10-2513226.7h32/3826/94
2026-10-2413214.6h16/2041/112
2026-10-2313226.7h5/1221/120
2026-10-2213222.7h10/1033/121
2026-10-2113225.0h10/1336/119
2026-10-2013222.1h18/2037/112
2026-10-1913226.7h15/2019/112
2026-10-1813226.7h5/836/124
2026-10-1713217.6h8/1056/122
2026-10-1613220.0h6/959/118
2026-10-1513218.5h15/1548/117
2026-10-1413220.2h11/1244/118
2026-10-1313222.1h8/828/120
2026-10-1213226.7h8/1244/113
2026-10-1113226.7h24/2552/97
2026-10-1013226.7h40/4437/86
2026-10-0913226.7h18/2435/108
2026-10-0813226.7h11/1531/117
2026-10-0713226.7h11/1618/116
2026-10-0613213.2h6/721/125
2026-10-0513226.7h12/2025/112
2026-10-0413226.7h27/2946/103
2026-10-0313226.7h23/2648/106
2026-10-0213226.7h41/4733/85
2026-10-0113226.7h45/5729/75
2026-09-3013226.7h42/5028/80
2026-09-2913226.7h18/2131/108
2026-09-2813226.7h17/2442/105
2026-09-2713226.7h38/4656/86
2026-09-2613226.7h33/5637/76
2026-09-2513226.7h39/5631/76
2026-09-2413226.7h29/4334/89
2026-09-2313226.7h19/2446/108
2026-09-2213226.7h33/3953/93
2026-09-2113226.7h45/5056/82
2026-09-2013226.7h34/4148/91
2026-09-1913226.7h17/2344/109
2026-09-1813226.7h13/1440/118
2026-09-1713226.7h16/1644/116
2026-09-1613226.7h16/1946/113
2026-09-1513226.7h18/2531/107
2026-09-1413226.7h8/1040/122
2026-09-1313226.7h21/3239/98
2026-09-1213226.7h27/3546/97
2026-09-1113226.7h29/3442/98
2026-09-1013226.7h16/2855/104
2026-09-0913226.7h17/3337/99
2026-09-0813226.7h22/3630/96
2026-09-0713226.7h15/2041/112
2026-09-0613226.7h12/1643/116
2026-09-0513226.7h10/1638/116
2026-09-0413226.7h8/1339/119
2026-09-0313226.7h14/1832/113
2026-09-0213226.7h22/3127/101
2026-09-0113226.7h25/3830/94
2026-08-3113212.1h30/3632/96
2026-08-3013250.7h52/7625/56
2026-08-2913226.7h26/3541/96
2026-08-2713226.7h18/2156/111
2026-08-2613226.7h19/3140/101
2026-08-2513226.0h12/3619/96
2026-08-2413226.7h16/2340/109
2026-08-2313226.7h18/2443/108
2026-08-2213226.7h22/3049/102
2026-08-2113226.7h18/3334/99
2026-08-2013226.7h15/1846/114
2026-08-1913226.7h27/5824/74
2026-08-1813226.7h16/3136/101
2026-08-1713226.7h22/3025/102
2026-08-1613226.7h16/2839/104
2026-08-1513226.7h16/2443/108
2026-08-1413226.7h27/3643/96
2026-08-1313226.7h27/3249/100
2026-08-1213226.0h27/3838/94
2026-08-1113226.7h16/2950/103
2026-08-1013226.7h15/2048/112
2026-08-0913226.7h5/1151/121
2026-08-0813226.7h9/1351/119
2026-08-0713216.5h11/1545/117
2026-08-0613214.9h13/1745/115
2026-08-0513215.6h6/744/125
2026-08-0413226.7h5/823/124
2026-08-0313226.7h9/1325/119
2026-08-0213226.7h13/1947/113
2026-08-0113226.7h29/3534/97
2026-07-3113226.7h14/2428/108
2026-07-3013226.4h4/1025/122
2026-07-2913226.1h7/1335/119
2026-07-2813220.9h10/1440/118
2026-07-2713220.6h13/2339/109
2026-07-2613220.0h8/1144/121
2026-07-2513226.7h12/1643/116
2026-07-2410826.7h22/2728/81
2026-07-2310826.7h2/440/104
2026-07-2210826.7h8/1434/94
2026-07-213626.7h10/137/23
2026-07-203625.6h3/49/32
2026-07-193624.2h0/214/34
2026-07-185630.2h9/1127/45
2026-07-175615.7h2/232/54
2026-07-025645.9h9/1313/43
2026-07-015621.9h8/913/47
2026-06-305646.9h6/1612/40
2026-06-295622.9h6/812/48
2026-06-283213.5h1/215/29

The full 2×2 (PERSISTENT vs not-PERSISTENT), per-day samples, and lead times are in scorecard.json. Refreshed daily by the contrail-scorecard systemd timer; no manual step.

Research: ground truth beyond satellite (Session 9)

Two queued research tasks asked whether ground cameras and ADS-B flight tracks could give the predictor a third validation layer. Both were surveyed and both came back don't build it. The reasons are more interesting than the verdict.


Cameras — NO-GO. Two premises failed before feasibility even came up:


• “Near airports” is backwards. Contrails form at 8–12 km. Aircraft within ~30 km of an airport are climbing through 0–3 km — far below the layer. The planes easiest to identify from an airport camera are exactly the ones making nothing. Jets reach contrail altitude roughly 110–220 km downrange. What matters is enroute traffic overhead, not the airport.


• Aviation weather cameras cannot see the sky. FAA cameras are aimed by compass azimuth — the API schema has no elevation or tilt field at all. 83% have a 45° FOV, putting the top of frame at ~25° elevation. Zenith is never in view. They are built to judge ceiling and visibility, which is a horizon question.


Coverage settled it regardless: 1 of the 8 cities checked has an archive-grade sky camera (SRRL Golden CO, 17 km from Denver, verified live). Columbus — the default location — has none. And the field is occupied: Schumann et al. (2013) did this with four cameras and aircraft matching; EUROCONTROL's GVCCS (2025) published 24,228 labelled frames.


ADS-B — scoped, then built as a narrow negative control. A free ODbL backfill (adsb.lol) covers real flight tracks over CONUS. The ceiling on full attribution is why this was never built as one: a contrail is only observable ~41 minutes after it forms — young ones are ~100 m wide against ABI's 2 km pixels — by which point it has drifted 60–150 km. Google's own matching, human-checked over 1,000 segments, confirms only 50%.


That asymmetry is the useful part: “an aircraft was plausibly there” is weak evidence (over CONUS, one nearly always was), while “no aircraft at any plausible offset” is strong evidence a detection is not a contrail. So the version that got built is exactly that one number, not an attribution pipeline: across 72 city-hours (2026-08-01, 24 CONUS cities), positive detections had no plausible aircraft nearby 19.6% of the time, versus 26.9% for pixels the detector called clear — the opposite direction from what cirrus contamination would predict, though the gap is not statistically significant at this sample size (Fisher's exact p=0.56). It does not support cirrus contamination as the dominant driver of the detector's precision. Full method and caveats: NEGATIVE_CONTROL.md in the project source.


The finding that outranked both tasks. This project's notes recorded that calibrating the detector to real precision/recall was blocked behind Kaggle terms a human had to accept. It isn't. The OpenContrails human labels sit in a public Google Cloud Storage bucket — anonymous, CC BY 4.0, a 78 GB validation split at 780 MB per shard.


This is the second false blocker found in two sessions. The previous one claimed the satellite archive needed credentials; NOAA publishes all of it openly, and the layer shown above got built once someone checked. Both blockers were inherited assumptions, recorded in the doc used to make decisions, and never tested. Both took one command to disprove.


The standing caveat below — “uncalibrated; only the ordering is meaningful” — is therefore fixable, with no permission needed.

The Physics

Contrails form when the mixing line between hot engine exhaust and cold ambient air passes through or above the ice saturation curve — the Schmidt-Appleman criterion.


The critical temperature Tc is the ambient temperature below which contrails must form. Whether they persist depends on whether the air is supersaturated with respect to ice (RHice ≥ 100%). Open-Meteo reports RH w.r.t. liquid water, so we convert: RHice = RHliq × (esat,liq / esat,ice). At −45°C this factor is ~1.53 — meaning 65% RH (liquid) is already supersaturated w.r.t. ice.


Engine parameters used: EIH₂O = 1.25 kg/kg • LHV = 43.2 MJ/kg • η = 0.30


PressureAltitudeG (Pa/K)Tc (contrails form below)
200 hPa~11.8 km / FL3871.334 Pa/K-44.1°C
250 hPa~10.5 km / FL3441.668 Pa/K-41.8°C
300 hPa~9.0 km / FL2952.002 Pa/K-39.9°C
350 hPa~7.9 km / FL2592.335 Pa/K-38.2°C
Try It — Schmidt-Appleman Calculator

Drag the sliders to set the ambient pressure, temperature, and humidity a contrail-forming aircraft might fly through. The classification below updates instantly — the same formulas as the forecast above, computed live in your browser.

Tc (critical temp)—
RHice—
Classification—