import os, numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import imageio.v2 as imageio
img_path = "/mnt/data/Screenshot 2026-03-16 172344(92).png"
out_dir = "/mnt/data/haiti_htgusd_batch_001_020"
os.makedirs(out_dir, exist_ok=True)
img =
Image.open(img_path).convert("RGB")
arr = np.array(img)
h, w, _ = arr.shape
x0, x1 = 55, w - 75
y0, y1 = 40, h - 60
crop = arr[y0:y1, x0:x1]
R, G, B = crop[:,:,0], crop[:,:,1], crop[:,:,2]
mask = ((R > 150) & (G < 90) & (B < 90)) | ((G > 120) & (R < 90) & (B < 140)) | ((G > 120) & (B > 120) & (R < 110))
ys, xs = np.where(mask)
if len(xs) < 50:
raise RuntimeError("Not enough colored chart pixels found to extract HTGUSD curve.")
x_unique = np.unique(xs)
median_y = np.array([np.median(ys[xs == xu]) for xu in x_unique])
n = 260
xi = np.linspace(x_unique.min(), x_unique.max(), n)
yi = np.interp(xi, x_unique, median_y)
kernel = np.ones(5)/5
yi = np.convolve(yi, kernel, mode="same")
price = (yi.max() - yi) / (yi.max() - yi.min() 1e-9)
price = 0.00645 price * (0.0225 - 0.00645)
t = np.linspace(0, 1, n)
returns = np.gradient(price)
trend = np.convolve(price, np.ones(15)/15, mode="same")
momentum = np.gradient(trend)
curvature = np.gradient(momentum)
price_z = (price - price.mean())/(price.std() 1e-9)
ret_z = (returns - returns.mean())/(returns.std() 1e-9)
theta = 2*np.pi*t
r = (price - price.min())/(price.max()-price.min() 1e-9) 0.15
def save_fig(fig, name):
p = os.path.join(out_dir, f"{name}.png")
fig.savefig(p, dpi=120, bbox_inches="tight")
plt.close(fig)
return p
frames = []
# 001
fig, ax = plt.subplots(figsize=(8,5)); ax.plot(t, price); ax.set_title("001 Cartesian 2D: extracted HTGUSD curve"); ax.set_xlabel("normalized time"); ax.set_ylabel("approx price"); ax.grid(True, alpha=.25); frames.append(save_fig(fig,"001_cartesian_2d"))
# 002
fig=plt.figure(figsize=(8,5)); ax=fig.add_subplot(111,projection="3d"); ax.plot(t,price,returns); ax.set_title("002 Cartesian 3D: time / price / return"); ax.set_xlabel("time"); ax.set_ylabel("price"); ax.set_zlabel("return"); frames.append(save_fig(fig,"002_cartesian_3d"))
# 003
fig=plt.figure(figsize=(7,7)); ax=fig.add_subplot(111,projection="polar"); ax.plot(theta,r); ax.set_title("003 Polar: price as radius"); frames.append(save_fig(fig,"003_polar"))
# 004
phi=np.pi*(price-price.min())/(price.max()-price.min() 1e-9); xs3=np.sin(phi)*np.cos(theta); ys3=np.sin(phi)*np.sin(theta); zs3=np.cos(phi)
fig=plt.figure(figsize=(8,5)); ax=fig.add_subplot(111,projection="3d"); ax.plot(xs3,ys3,zs3); ax.set_title("004 Spherical: price bends latitude"); frames.append(save_fig(fig,"004_spherical"))
# 005
fig=plt.figure(figsize=(8,5)); ax=fig.add_subplot(111,projection="3d"); ax.plot(np.cos(theta),np.sin(theta),price_z); ax.set_title("005 Cylindrical: cycle wrapped around price"); ax.set_zlabel("price z-score"); frames.append(save_fig(fig,"005_cylindrical"))
# 006
u=np.linspace(-2.2,2.2,n); scale=.35 (price-price.min())/(price.max()-price.min() 1e-9)
fig,ax=plt.subplots(figsize=(8,5)); ax.plot(np.sinh(u)*scale,np.cosh(u)*scale); ax.set_title("006 Hyperbolic: selloff stretched into curved space"); ax.axis("equal"); ax.grid(True, alpha=.25); frames.append(save_fig(fig,"006_hyperbolic"))
# 007
rlog=np.exp(2*(price-price.min())/(price.max()-price.min() 1e-9))
fig=plt.figure(figsize=(7,7)); ax=fig.add_subplot(111,projection="polar"); ax.plot(theta,rlog); ax.set_title("007 Log-polar: compression / shock expansion"); frames.append(save_fig(fig,"007_log_polar"))
# 008
spiral_r=(1 4*t)*r
fig,ax=plt.subplots(figsize=(7,7)); ax.plot(spiral_r*np.cos(6*np.pi*t),spiral_r*np.sin(6*np.pi*t)); ax.set_title("008 Spiral: time unwrap with price radius"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"008_spiral"))
# 009
fig,ax=plt.subplots(figsize=(7,7))
for a,rr in zip(theta[::3],r[::3]): ax.plot([0,rr*np.cos(a)],[0,rr*np.sin(a)],linewidth=.8)
ax.set_title("009 Radial wheel: each week as a spoke"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"009_radial_wheel"))
# 010
def primes_up_to(k):
primes=[]
for q in range(2,k 1):
ok=True
for d in range(2,int(q**0.5) 1):
if q%d==0: ok=False; break
if ok: primes.append(q)
return np.array(primes)
pr=primes_up_to(1600); idx=np.linspace(0,n-1,len(pr)).astype(int); ptheta=pr*.12; prr=.25 3*(price[idx]-price.min())/(price.max()-price.min() 1e-9) np.sqrt(pr)/45
fig,ax=plt.subplots(figsize=(7,7)); ax.scatter(prr*np.cos(ptheta),prr*np.sin(ptheta),s=10); ax.set_title("010 Prime wheel: prime-indexed price sampling"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"010_prime_wheel"))
m=24; ids=np.linspace(0,n-1,m).astype(int); pts2=np.column_stack([t[ids],price_z[ids]]); pts_norm=(pts2-pts2.mean(axis=0))/(pts2.std(axis=0) 1e-9)
# 011
fig,ax=plt.subplots(figsize=(8,5)); ax.scatter(pts_norm[:,0],pts_norm[:,1],s=35)
for i in range(m-1): ax.plot(pts_norm[i:i 2,0],pts_norm[i:i 2,1],linewidth=.8)
for i in range(0,m,3):
j=(i 7)%m; ax.plot([pts_norm[i,0],pts_norm[j,0]],[pts_norm[i,1],pts_norm[j,1]],linewidth=.5,alpha=.6)
ax.set_title("011 Node-link: sampled weeks as connected states"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"011_node_link"))
# 012
pos=pts_norm.copy(); edges=[(i,i 1) for i in range(m-1)] [(i,(i 5)%m) for i in range(0,m,4)]
for _ in range(160):
force=np.zeros_like(pos)
for i in range(m):
diff=pos[i]-pos; dist2=(diff**2).sum(axis=1) .01; force[i] =(diff/dist2[:,None]).sum(axis=0)*.002
for i,j in edges:
d=pos[j]-pos[i]; force[i] =d*.01; force[j]-=d*.01
pos =force
fig,ax=plt.subplots(figsize=(7,7)); ax.scatter(pos[:,0],pos[:,1],s=35)
for i,j in edges: ax.plot([pos[i,0],pos[j,0]],[pos[i,1],pos[j,1]],linewidth=.8)
ax.set_title("012 Force graph: price states pull into clusters"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"012_force_graph"))
# 013
ang=np.linspace(0,2*np.pi,m,endpoint=False); circ=np.column_stack([np.cos(ang),np.sin(ang)])
fig,ax=plt.subplots(figsize=(7,7)); ax.scatter(circ[:,0],circ[:,1],s=35)
for i in range(m):
j=(i 1)%m; ax.plot([circ[i,0],circ[j,0]],[circ[i,1],circ[j,1]],linewidth=.8)
if abs(price_z[ids[i]])>.7:
k=(i 6)%m; ax.plot([circ[i,0],circ[k,0]],[circ[i,1],circ[k,1]],linewidth=.6)
ax.set_title("013 Circular network: shock weeks create chords"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"013_circular_network"))
# 014-016 scipy spatial
from scipy.spatial import Voronoi, voronoi_plot_2d, Delaunay, ConvexHull
pv=pts_norm np.random.default_rng(7).normal(0,.01,pts_norm.shape)
vor=Voronoi(pv); fig=voronoi_plot_2d(vor,show_vertices=False,line_width=.8); fig.set_size_inches(7,7); ax=fig.axes[0]; ax.scatter(pv[:,0],pv[:,1],s=15); ax.set_title("014 Voronoi: market-state territory cells"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"014_voronoi"))
tri=Delaunay(pv); fig,ax=plt.subplots(figsize=(7,7)); ax.triplot(pv[:,0],pv[:,1],tri.simplices,linewidth=.8); ax.scatter(pv[:,0],pv[:,1],s=15); ax.set_title("015 Delaunay: nearest-state triangle mesh"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"015_delaunay"))
hull=ConvexHull(pv); fig,ax=plt.subplots(figsize=(7,7)); ax.scatter(pv[:,0],pv[:,1],s=15)
for simplex in hull.simplices: ax.plot(pv[simplex,0],pv[simplex,1],linewidth=1)
ax.set_title("016 Convex hull: outer boundary of price behavior"); ax.axis("equal"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"016_convex_hull"))
# 017 fixed heatmap: compare each lag on same first n-lags columns
lags=40; base_len=n-lags; M=np.zeros((lags,base_len))
for lag in range(1,lags 1): M[lag-1]=price_z[lag:lag base_len]-price_z[:base_len]
fig,ax=plt.subplots(figsize=(8,5)); im=ax.imshow(M,aspect="auto",origin="lower"); fig.colorbar(im,ax=ax,fraction=.046,pad=.04); ax.set_title("017 Heatmap: lagged price-difference memory"); ax.set_xlabel("time"); ax.set_ylabel("lag"); frames.append(save_fig(fig,"017_heatmap"))
# 018
windows=np.arange(3,43,2); Z=[]
for win in windows: Z.append(np.convolve(price_z,np.ones(win)/win,mode="same"))
Z=np.array(Z); X,Y=np.meshgrid(t,windows); fig=plt.figure(figsize=(8,5)); ax=fig.add_subplot(111,projection="3d"); ax.plot_surface(X,Y,Z,linewidth=0,antialiased=True); ax.set_title("018 Surface: price across smoothing scales"); ax.set_xlabel("time"); ax.set_ylabel("window"); ax.set_zlabel("z-price"); frames.append(save_fig(fig,"018_surface"))
# 019
grid_t,grid_p=np.meshgrid(np.linspace(0,1,20),np.linspace(price_z.min(),price_z.max(),20)); slope=np.interp(grid_t.ravel(),t,ret_z).reshape(grid_t.shape); curve=np.interp(grid_t.ravel(),t,(curvature-curvature.mean())/(curvature.std() 1e-9)).reshape(grid_t.shape)
fig,ax=plt.subplots(figsize=(8,5)); ax.quiver(grid_t,grid_p,np.ones_like(slope)*.08,slope .2*curve); ax.set_title("019 Vector field: trend pressure arrows"); ax.set_xlabel("time"); ax.set_ylabel("price z-score"); ax.grid(True,alpha=.25); frames.append(save_fig(fig,"019_vector_field"))
# 020
from scipy.integrate import solve_ivp
def drive(tt): return np.interp((tt/40)%1,t,price_z)
def f(tt,state):
x,y,z=state; d=drive(tt); return [10*(y-x) .15*d, x*(28-z)-y, x*y-(8/3)*z .15*d]
sol=solve_ivp(f,(0,40),[1,1,1],max_step=.02)
fig=plt.figure(figsize=(8,5)); ax=fig.add_subplot(111,projection="3d"); ax.plot(sol.y[0],sol.y[1],sol.y[2],linewidth=.7); ax.set_title("020 Lorenz: chaos engine nudged by HTGUSD"); frames.append(save_fig(fig,"020_lorenz"))
gif_path="/mnt/data/HTGUSD_Haiti_batch_001_020_math_lenses.gif"
images=[]
for p in frames:
im=
Image.open(p).convert("RGB")
im.thumbnail((900,650))
canvas=
Image.new("RGB",(900,650),"white")
canvas.paste(im,((900-im.width)//2,(650-im.height)//2))
images.append(np.array(canvas))
imageio.mimsave(gif_path,images,duration=1.15,loop=0)
thumbs=[
Image.open(p).convert("RGB").resize((320,230)) for p in frames]
sheet=
Image.new("RGB",(4*320,5*230),"white")
for i,th in enumerate(thumbs): sheet.paste(th,((i%4)*320,(i//4)*230))
sheet_path="/mnt/data/HTGUSD_Haiti_batch_001_020_contact_sheet.png";
sheet.save(sheet_path)
csv_path="/mnt/data/HTGUSD_Haiti_extracted_curve_from_screenshot.csv"
np.savetxt(csv_path,np.column_stack([t,price,returns,trend,momentum,curvature]),delimiter=",",header="t,approx_price,return,trend,momentum,curvature",comments="")
print("Created:")
print(gif_path)
print(sheet_path)
print(csv_path)
print(f"Extracted {n} approximate data points from the screenshot curve.")