Drogheda/03-Architecture-Hardware/Auditoria-Final-V56-V57/scripts/gcmp.py

64 lines
3.0 KiB
Python

import re, sys
from PIL import Image, ImageDraw
import numpy as np
from scipy import ndimage
def regions(path):
inreg=False; regs=[]; cur=[]; x=y=0; pol="D"
for line in open(path, errors="replace"):
s=line.strip()
if s=="%LPC*%": pol="C"
if s=="%LPD*%": pol="D"
if s=="G36*": inreg=True; cur=[]; continue
if s=="G37*": inreg=False; regs.append((pol,cur)); continue
m=re.match(r"(?:X(-?\d+))?(?:Y(-?\d+))?D0([123])\*$",s)
if m:
nx=int(m.group(1)) if m.group(1) is not None else x; ny=int(m.group(2)) if m.group(2) is not None else y
if inreg: cur.append((nx,ny))
x,y=nx,ny
return regs
def prims(path):
ap=None; inreg=False; x=y=0; flashes=set(); draws=set(); apdefs={}
for line in open(path, errors="replace"):
s=line.strip()
if s.startswith("G04") or s.startswith("%T"): continue
m=re.match(r"%ADD(\d+)(.*)\*%",s)
if m: apdefs[m.group(1)]=m.group(2); continue
if s=="G36*": inreg=True; continue
if s=="G37*": inreg=False; continue
m=re.match(r"D(\d+)\*$",s)
if m and int(m.group(1))>=10: ap=apdefs.get(m.group(1)); continue
m=re.match(r"(?:X(-?\d+))?(?:Y(-?\d+))?D0([123])\*$",s)
if m:
nx=int(m.group(1)) if m.group(1) is not None else x; ny=int(m.group(2)) if m.group(2) is not None else y
if not inreg:
if m.group(3)=="3": flashes.add((ap,nx,ny))
elif m.group(3)=="1": draws.add((ap,x,y,nx,ny))
x,y=nx,ny
return flashes,draws
SC=50; W,H=int(141*SC),int(101*SC)
def raster_regs(regs):
im=Image.new("1",(W,H),0); d=ImageDraw.Draw(im)
for pol,pts in regs:
d.polygon([((x/1e6-60)*SC,(-y/1e6-40)*SC) for x,y in pts], fill=1 if pol=="D" else 0)
return np.array(im)
def compare(a,b):
fa,da=prims(a); fb,db=prims(b)
ra=raster_regs(regions(a)); rb=raster_regs(regions(b))
x=ra^rb
er=ndimage.binary_erosion(x, structure=np.ones((3,3)))
lab,n=ndimage.label(er)
blobs=[]
for i in range(1,n+1):
ys,xs=np.nonzero(lab==i)
if len(xs)<9: continue
blobs.append((len(xs)/SC/SC, round(xs.min()/SC+60,1),round(ys.min()/SC+40,1),round(xs.max()/SC+60,1),round(ys.max()/SC+40,1), "A-only" if ra[ys[0],xs[0]] else "B-only"))
blobs.sort(reverse=True)
return fa==fb, da==db, x.sum()/SC/SC, blobs
if __name__=="__main__":
base="../in/03-Architecture-Hardware/kicad"
for v,b,prod in (("v56","v5","HBOX_v5_Rev6_PROD"),("v57","v57","HBOX_v5_Rev7_PROD")):
print("=====",v)
for lay,e1 in (("F_Cu","gtl"),("In1_Cu","g1"),("In2_Cu","g2"),("B_Cu","gbl")):
fs,ds,xa,blobs=compare(f"{base}/production/{prod}/hbox-watchdog-{b}-{lay}.{e1}", f"{base}/_to_delete/audit-20261022/{v}/rf/gerber/hbox-watchdog-{b}-{lay}.gbr")
print(f" {lay:7s} flashes={fs} draws={ds} fill-xor={xa:.3f} mm2 blobs={len(blobs)}", [f"{a:.2f}@({x1},{y1})-({x2},{y2}){t}" for a,x1,y1,x2,y2,t in blobs[:5]])