my eye

author Angelo Gladding

published 2025-09-12T15:43:36.151537-07:00

type entry

updated 2025-09-14T20:40:04.350049-07:00

url /2025/09/12/vk

visibility public

widescreen yes

Content

$def capacity_score_k(pop_k, inc_k, P0_k=50, I0_k=75, w_pop=0.4, w_inc=0.6, sharp=1.0):
    $ r_pop = max(pop_k, 0.001) / float(P0_k)
    $ r_inc = max(inc_k, 0.001) / float(I0_k)
    $ gm_norm = (r_pop ** w_pop) * (r_inc ** w_inc)
    $ gm_norm = gm_norm ** sharp
    $ k = 1.25
    $ score = 1.0 + 9.0 * (gm_norm / (k + gm_norm))
    $round(min(10.0, max(1.0, score)), 2)

$ cities = {
$   "San Marino": (8.7, 9.6, 13, 187.6, 2018),
$   "Palo Alto": (8.5, 8.6, 68, 220.4, 1951),
$   "Pasadena": (9.2, 7.8, 138, 103.8, 1987),
$   "Atlanta": (8.6, 8.3, 500, 91.5, 1967),
$   "Portland": (8.4, 8.2, 652, 88.8, 2011),
$   "Oakland": (8.2, 8.2, 440, 97.4, 1932),
$   "La Cañada Flintridge": (7.8, 8.5, 20.5, 221.5, 1990),
$   "Los Angeles City (eg. Highland Park, Eagle Rock, Montecito Heights, El Sereno, Pacific Palisades, Bel Air, Brentwood)": (8.0, 8.0, 3900, 80.4, 1982),
$   "Austin": (8.3, 7.7, 975, 91.5, 1983),
$   "Glendale": (7.6, 8.4, 196, 84.3, 1982),
$   "San Francisco": (8.0, 7.5, 874, 141.4, 1991),
$   "South Pasadena (Current)": (8.6, 6.9, 26, 128.1, 1991),
$   "Malibu": (7.9, 6.8, 12.7, 192.2, 2002),
$   "Alhambra": (7.2, 7.4, 82, 85.2, 2018),
$   "Cupertino": (7.6, 7.0, 60.3, 231.1, 2007),
$   "Berkeley": (7.5, 7.0, 124, 108.6, 2006),
$   "San Jose": (7.0, 7.2, 1013, 141.6, ""),
$   "West Hollywood": (7.4, 6.8, 35.7, 94.8, 2006),
$   "Arcadia": (7.2, 6.8, 57, 116.1, 1962),
$   "Sierra Madre": (7.5, 6.5, 11, 141.1, 1998),
$   "Burbank": (7.3, 6.6, 103, 95.8, 2023),
$   "Beverly Hills": (7.2, 6.6, 32, 128.0, 1991),
$   "Santa Monica": (7.0, 6.5, 93, 109.7, 2012),
$   "Minneapolis": (6.8, 6.6, 429, 80.3, 2009),
$   "Monrovia": (6.9, 6.3, 38, 106.0, 1994),
$   "San Gabriel": (6.8, 6.2, 39, 90.1, 1991),
$   "Culver City": (6.5, 6.2, 40.7, 122.3, 2013),
$   "Glendora": (6.6, 5.9, 52, 105.0, ""),
$   "Covina": (6.6, 5.8, 51, 80.0, 1996),
$   "San Dimas": (6.4, 5.8, 34, 104.0, ""),
$   "La Verne": (6.5, 5.7, 31, 108.0, ""),
$   "Azusa": (6.4, 5.7, 51, 79.0, 2002),
$   "Baldwin Park": (6.2, 5.8, 72, 75.0, 2011),
$   "El Monte": (6.0, 5.5, 107, 64.5, 2012),
$   "Buffalo": (5.9, 5.4, 278, 48.1, 1974),
$   "West Covina": (6.1, 5.2, 109, 93.0, 2019),
$   "Duarte": (6.0, 5.2, 22, 98.1, 2018),
$   "Palm Springs": (5.8, 5.2, 45, 72.0, 2025),
$   "Bradbury": (6.0, 5.0, 1.1, 200.0, ""),
$   "Los Angeles County (eg. Altadena, East San Gabriel, South San Gabriel, La Crescenta–Montrose, East Pasadena, Kinneloa Mesa)": (5.6, 4.8, 10000, 80.0, 1982),
$   "Denton": (5.4, 4.6, 150, 73.7, 2001),
$   "Palm Desert": (5.0, 4.8, 53, 79.5, 2001),
$   "South Pasadena (Proposed)": (6.0, 4.0, 26, 128.1, 1991),
$   "South Pasadena (Practice)": (7.0, 3.0, 26, 128.1, 1991),
$   "Irwindale": (4.8, 4.2, 1.5, 85.0, ""),
$   "South El Monte": (4.5, 4.0, 21, 66.0, ""),
$   "Temple City": (3.8, 4.0, 36, 102.4, 2014),
$   "Montebello": (4.0, 3.5, 63, 71.0, ""),
$   "Claremont": (3.5, 3.0, 37, 122.1, 2004),
$   "Monterey Park": (3.0, 2.0, 61, 77.6, 1972),
$   "Rosemead": (2.5, 1.5, 51, 72.2, 1990),
$ }

<div id="map"></div>

<style>
  #map { height: 60em; width: 100%; }
</style>

<link href="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css" rel="stylesheet"/>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js"></script>
<script src="https://unpkg.com/@turf/turf@6.5.0/turf.min.js"></script>

<script>
  mapboxgl.accessToken = 'pk.eyJ1IjoicmFndC1hZyIsImEiOiJjbWR3ZjZ5cjkxMmRhMmtwbHVlcDBrN240In0.nCEdq0_XYbjl8jq6YV4p5g';
  const map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/satellite-streets-v12',
    center: [-118.25, 34.06],
    zoom: 9.5
  });
  map.addControl(new mapboxgl.NavigationControl());
</script>

<script>
  const cities = $:web.dump(cities);

  function baseName(k){ return k.replace(/\s*\(.*\)\s*/,'').trim(); }
  function norm(s){ try { return (s||'').normalize('NFD').replace(/[\u0300-\u036f]/g,'').toLowerCase(); } catch(e){ return (s||'').toLowerCase(); } }

  var LA_CITY_KEY   = Object.keys(cities).find(function(k){ return /^Los Angeles City\b/i.test(k); }) || null;
  var LA_COUNTY_KEY = Object.keys(cities).find(function(k){ return /^Los Angeles County\b/i.test(k); }) || null;
  var LCF_KEY       = Object.keys(cities).find(function(k){ return /La Ca(?:ñ|n)ada Flintridge/i.test(k); }) || null;

  // Map labels to the dict key that supplies their score
  var SCORE_FROM = {
    // County-governed
    'Altadena': LA_COUNTY_KEY,
    'East San Gabriel': LA_COUNTY_KEY,
    'South San Gabriel': LA_COUNTY_KEY,
    'La Crescenta-Montrose': LA_COUNTY_KEY,
    'East Pasadena': LA_COUNTY_KEY,
    'Kinneloa Mesa': LA_COUNTY_KEY,
    // LA City neighborhoods (one table row for LA City)
    'Highland Park': LA_CITY_KEY,
    'Eagle Rock': LA_CITY_KEY,
    'Montecito Heights': LA_CITY_KEY,
    'El Sereno': LA_CITY_KEY,
    'Pacific Palisades': LA_CITY_KEY,
    'Sunland': LA_CITY_KEY
  };

  // Everything we want to draw
  var DRAW_LABELS = [
    // keep first for clarity
    'Altadena',
    'La Cañada Flintridge',

    // LA City neighborhoods colored by LA City score
    'Highland Park','Eagle Rock','Montecito Heights','El Sereno','Pacific Palisades','Sunland',

    // Newly requested cities
    'Glendora','San Dimas','La Verne','Irwindale',
    // previously added but ensure present:
    'Burbank','Bradbury','South El Monte','West Covina','Covina','Azusa','Montebello',
    'Baldwin Park','Monrovia','Duarte',

    // Nearby comparison set
    'Pasadena','South Pasadena','San Marino','Alhambra','San Gabriel','Temple City','El Monte','Monterey Park',
    'Arcadia','Sierra Madre','Glendale','Claremont','Santa Monica','West Hollywood','Beverly Hills','Malibu'
  ];

  function dictKeyForLabel(label){
    if (SCORE_FROM[label]) return SCORE_FROM[label];
    var nl = norm(baseName(label));
    var keys = Object.keys(cities);
    for (var i=0;i<keys.length;i++){
      if (norm(baseName(keys[i])) === nl) return keys[i];
    }
    if (/la canada flintridge|la cañada flintridge/i.test(label) && LCF_KEY) return LCF_KEY;
    return null;
  }

  function scoreFromKey(key){
    if (!key) return null;
    var v = cities[key];
    if (!v || !isFinite(v[0]) || !isFinite(v[1])) return null;
    return Math.sqrt(v[0] * v[1]);
  }

  function productScore(label){
    var key = dictKeyForLabel(label);
    return scoreFromKey(key);
  }

  (function establishDomain(){
    var vals = [];
    for (var i=0;i<DRAW_LABELS.length;i++){
      var s = productScore(DRAW_LABELS[i]);
      if (s != null) vals.push(s);
    }
    var sCity = scoreFromKey(LA_CITY_KEY); if (sCity != null) vals.push(sCity);
    var sCounty = scoreFromKey(LA_COUNTY_KEY); if (sCounty != null) vals.push(sCounty);
    window.__S_MIN__ = vals.length ? Math.min.apply(null, vals) : 0;
    window.__S_MAX__ = vals.length ? Math.max.apply(null, vals) : 10;
  })();

  function colorScale(value, min, max){
    var t = (max > min) ? (value - min) / (max - min) : 0.5;
    if (t < 0) t = 0; if (t > 1) t = 1;
    var hue = 0 + t * 120; // 0=red → 120=green
    return 'hsl(' + hue + ',72%,45%)';
  }

  var LA_VIEWBOX = [-118.9448, 34.8233, -117.6464, 33.7037];

  function queryVariants(label){
    var map = {
      // County
      'Altadena': ['Altadena, Los Angeles County, California, USA','Altadena, California, USA'],
      'East San Gabriel': ['East San Gabriel, California, USA'],
      'South San Gabriel': ['South San Gabriel, California, USA'],
      'La Crescenta-Montrose': ['La Crescenta-Montrose, Los Angeles County, California, USA','La Crescenta, California, USA'],
      'East Pasadena': ['East Pasadena, California, USA'],
      'Kinneloa Mesa': ['Kinneloa Mesa, California, USA'],
      // LA City hoods
      'Highland Park': ['Highland Park, Los Angeles, California, USA','Highland Park, California, USA'],
      'Eagle Rock': ['Eagle Rock, Los Angeles, California, USA','Eagle Rock, California, USA'],
      'Montecito Heights': ['Montecito Heights, Los Angeles, California, USA','Montecito Heights, California, USA'],
      'El Sereno': ['El Sereno, Los Angeles, California, USA','El Sereno, California, USA'],
      'Pacific Palisades': ['Pacific Palisades, Los Angeles, California, USA','Pacific Palisades, California, USA'],
      'Sunland': ['Sunland, Los Angeles, California, USA','Sunland-Tujunga, Los Angeles, California, USA'],
      // Cities
      'La Cañada Flintridge': ['La Cañada Flintridge, Los Angeles County, California, USA','La Canada Flintridge, Los Angeles County, California, USA','La Cañada Flintridge, California, USA','La Canada Flintridge, California, USA'],
      'Glendora': ['Glendora, California, USA'],
      'San Dimas': ['San Dimas, California, USA'],
      'La Verne': ['La Verne, California, USA'],
      'Irwindale': ['Irwindale, California, USA'],
      'Burbank': ['Burbank, California, USA'],
      'Bradbury': ['Bradbury, California, USA'],
      'South El Monte': ['South El Monte, California, USA'],
      'West Covina': ['West Covina, California, USA'],
      'Covina': ['Covina, California, USA'],
      'Azusa': ['Azusa, California, USA'],
      'Baldwin Park': ['Baldwin Park, California, USA'],
      'Monrovia': ['Monrovia, California, USA'],
      'Duarte': ['Duarte, California, USA'],
      'Montebello': ['Montebello, California, USA'],
      'Pasadena': ['Pasadena, California, USA'],
      'South Pasadena': ['South Pasadena, California, USA'],
      'San Marino': ['San Marino, California, USA'],
      'Alhambra': ['Alhambra, California, USA'],
      'San Gabriel': ['San Gabriel, California, USA'],
      'Temple City': ['Temple City, California, USA'],
      'El Monte': ['El Monte, California, USA'],
      'Monterey Park': ['Monterey Park, California, USA'],
      'Arcadia': ['Arcadia, California, USA'],
      'Sierra Madre': ['Sierra Madre, California, USA'],
      'Glendale': ['Glendale, California, USA'],
      'Claremont': ['Claremont, California, USA'],
      'Santa Monica': ['Santa Monica, California, USA'],
      'West Hollywood': ['West Hollywood, California, USA'],
      'Beverly Hills': ['Beverly Hills, California, USA'],
      'Malibu': ['Malibu, California, USA']
    };
    return map[label] || [label + ', Los Angeles County, California, USA', label + ', California, USA'];
  }

  async function fetchPolygon(label){
    var queries = queryVariants(label);

    // bounded first
    for (var i=0;i<queries.length;i++){
      try{
        var url = 'https://nominatim.openstreetmap.org/search?format=json&addressdetails=1&namedetails=1&limit=10&polygon_geojson=1'
                + '&viewbox=' + LA_VIEWBOX[0] + ',' + LA_VIEWBOX[1] + ',' + LA_VIEWBOX[2] + ',' + LA_VIEWBOX[3] + '&bounded=1'
                + '&q=' + encodeURIComponent(queries[i]);
        var res = await fetch(url, { headers: { 'Accept': 'application/json' } });
        if (!res.ok) continue;
        var arr = await res.json();
        var match =
          arr.find(function(x){ return x.geojson && x['class'] === 'boundary' && (x.type === 'administrative' || x.type === 'political'); }) ||
          arr.find(function(x){ return x.geojson && x['class'] === 'place' && (x.type === 'neighbourhood' || x.type === 'suburb' || x.type === 'quarter'); }) ||
          arr.find(function(x){ return x.geojson; });
        if (match){
          return { type:'Feature', properties:{ name: label, display_name: match.display_name }, geometry: match.geojson };
        }
      }catch(e){}
    }

    // unbounded fallback
    for (var j=0;j<queries.length;j++){
      try{
        var url2 = 'https://nominatim.openstreetmap.org/search?format=json&addressdetails=1&namedetails=1&limit=10&polygon_geojson=1&q=' + encodeURIComponent(queries[j]);
        var res2 = await fetch(url2, { headers: { 'Accept': 'application/json' } });
        if (!res2.ok) continue;
        var arr2 = await res2.json();
        var match2 =
          arr2.find(function(x){ return x.geojson && x['class'] === 'boundary' && (x.type === 'administrative' || x.type === 'political'); }) ||
          arr2.find(function(x){ return x.geojson && x['class'] === 'place' && (x.type === 'neighbourhood' || x.type === 'suburb' || x.type === 'quarter'); }) ||
          arr2.find(function(x){ return x.geojson; });
        if (match2){
          return { type:'Feature', properties:{ name: label, display_name: match2.display_name }, geometry: match2.geojson };
        }
      }catch(e){}
    }

    throw new Error('No polygon for ' + label);
  }

  function idsFor(name){ var id = name.toLowerCase().replace(/[^a-z0-9]+/g,'-'); return { src: id+'-src', fill: id+'-fill', line: id+'-line' }; }

  function addLayers(feature, color, html){
    var ids = idsFor(feature.properties.name);
    if (!map.getSource(ids.src)) map.addSource(ids.src, { type:'geojson', data: feature });
    if (!map.getLayer(ids.fill)) map.addLayer({ id: ids.fill, type:'fill', source: ids.src, paint: { 'fill-color': color, 'fill-opacity': 0.28 } });
    if (!map.getLayer(ids.line)) map.addLayer({ id: ids.line, type:'line', source: ids.src, paint: { 'line-color': color, 'line-width': 2.5 } });
    map.on('click', ids.line, function(e){
      new mapboxgl.Popup()
        .setLngLat(e.lngLat)
        .setHTML('<strong>' + feature.properties.name + '</strong><br/><small>' + feature.properties.display_name + '</small><br/>' + html)
        .addTo(map);
    });
  }

  function sleep(ms){ return new Promise(function(r){ setTimeout(r, ms); }); }

  map.on('load', async function(){
    var features = [];
    for (var i=0;i<DRAW_LABELS.length;i++){
      var label = DRAW_LABELS[i];
      var s = productScore(label);
      var color = (s != null) ? colorScale(s, window.__S_MIN__, window.__S_MAX__) : 'hsl(0,0%,60%)';
      try{
        var feat = await fetchPolygon(label);
        var key = dictKeyForLabel(label);
        var html = (s != null ? 'Score √(P×R): ' + s.toFixed(1) : 'Score: N/A') + '<br/>From: ' + (key || '(no dict key)');
        addLayers(feat, color, html);
        features.push(feat);
      }catch(e){
        console.warn('Failed polygon for', label, e);
      }
      await sleep(240);
    }

    if (features.length){
      var fc = { type:'FeatureCollection', features: features };
      var box = turf.bbox(fc);
      map.fitBounds([[box[0], box[1]], [box[2], box[3]]], { padding: 44, duration: 900 });
    }
  });
</script>

<table>
  <thead>
    <tr>
      <th style="text-align:left">City</th>
      <th>Protections (P)</th>
      <th>Replacement (R)</th>
      <th>Score √(P×R)</th>
      <th>Population (in thou.)</th>
      <th>Income (in thou.)</th>
      <th>Capability</th>
      <th>Year First Ordinance</th>
    </tr>
  </thead>
  <tbody>
$for name, (protection_score, replacement_score, population, income, year) in sorted(cities.items(), key=lambda kv: kv[1][0] * kv[1][1], reverse=True):
    <tr>
      <td>$name</td>
      <td>$protection_score</td>
      <td>$replacement_score</td>
      <td>$f"{math.sqrt(protection_score * replacement_score):,.1f}"</td>
      <td>$f"{round(population):,}"</td>
      <td>$income</td>
      <td>$capacity_score_k(population, income)</td>
      <td>$year</td>
    </tr>
  </tbody>
</table>