import os, sys, numpy as np, tifffile
os.environ['PURE4_NO_MAIN'] = '1'
sys.path.insert(0, '/home/claude/loop/human/v3card'); sys.path.insert(0, '/home/claude/loop/lib'); sys.path.insert(0, '/home/claude/dv/cards')
import pure4 as P, render3 as r, g1
from PIL import Image
from pyproj import Transformer
BASE = dict(P.BASE, field_L=12, field_hue=270, field_C=16, land_L=18, land_hue=268, land_C=14)
P.NAVY = np.array(r.col(12, 270, 16), np.float32); P.ON_DARK = np.array(r.col(38, 265, 14), np.float32)
# --- GFW 存在時間（2025-09、0.1°、北緯60度以北） ---
TIF = '/home/claude/loop/human/gfw/layer-activity-data-0/public-global-presence-v4.0.tif'
pres = tifffile.imread(TIF).astype(np.float64); pres[pres >= 999999] = 0
LAT0, LON0, RES = 90.05, -180.05, 0.1   # 左上隅（tiepoint）
inv = Transformer.from_crs('EPSG:3411', 'EPSG:4326', always_xy=True)
def presence_field(sc):
    ys, xs = np.mgrid[0:r.H, 0:r.W]
    X = sc.cx + (xs / r.W - 0.5) * sc.wkm * 1000; Y = sc.cy - (ys / r.H - 0.5) * sc.hkm * 1000
    lon, lat = inv.transform(X, Y)
    row = ((LAT0 - lat) / RES).astype(int); col = ((lon - LON0) / RES).astype(int)
    ok = (row >= 0) & (row < pres.shape[0]) & (col >= 0) & (col < pres.shape[1])
    f = np.zeros((r.H, r.W)); f[ok] = pres[row[ok], col[ok]]
    return f
def build(path, gamma_ref=None, hmin=0, strength=0.85):
    out = r.render(BASE, '/home/claude/loop/human/v3card/pure6_base'); sc = P.sc
    im = Image.open(f'{out}/render.png'); size = im.size
    im = P.comp_rel(im, P.aa_mask(size, P.grat(sc)), 0.22, 0.16)
    im = P.comp_rel(im, P.aa_mask(size, P.circle66(sc)), 0.22, 0.16)
    im = P.comp_rel(im, P.aa_mask(size, P.lat_labels(sc)), 0.30, 0.20)
    f = presence_field(sc)
    ref = gamma_ref or np.percentile(f[f > 0], 97)
    alpha = np.clip(np.log1p(f) / np.log1p(ref), 0, 1); alpha[f < hmin] = 0
    # 船の存在: 紙の上では白へ、氷の上ではネイビーへ。強さは存在時間の対数
    im = P.comp_rel(im, alpha * strength, 0.75, 0.55)
    for it in P.PLACES: im = P.comp_label(im, P.aa_mask(size, P.text_fn(sc, it, 20)))
    for it in P.TOWNS: im = P.comp_label(im, P.aa_mask(size, P.text_fn(sc, it, 14, 0.10, dot=2.2)))
    im.save(path); return im, f, ref
im, f, ref = build('/home/claude/loop/human/v3card/S1.png')
im.crop((100,250,700,850)).save('/home/claude/loop/human/v3card/S1_detail.png')
im2, _, _ = build('/home/claude/loop/human/v3card/S2.png', hmin=3, strength=0.6)
im2.crop((100,250,700,850)).save('/home/claude/loop/human/v3card/S2_detail.png')
from PIL import ImageDraw
tw, th = 540, 675; sheet = Image.new('RGB', (tw*2+60, th+70), 'white'); d = ImageDraw.Draw(sheet); fnt = g1.font('Regular', 24)
for i, (k, m) in enumerate((('S1 全部（1時間以上）', im), ('S2 3時間以上・弱め', im2))):
    x = 20+i*(tw+20); d.text((x, 8), k, font=fnt, fill=(0,0,0)); sheet.paste(m.resize((tw,th), Image.LANCZOS), (x, 45))
sheet.save('/home/claude/loop/human/v3card/contact_s.png')
print('cells>0 in view:', int((f>0).sum()), 'ref hours:', round(float(ref),1), 'max:', float(f.max()))
