"""Read and write .thr (theta-rho) pattern files. Each line holds " ": theta: angle in radians, continuous (it keeps counting past 2*pi; it is not wrapped) rho: distance from the centre, 0 (centre) to 1 (edge) Lines starting with '#' or '//' are comments. This is the format used by Sandify, Sisyphus and Dune Weaver. """ import math Pattern = list # list of (theta_rad, rho) tuples def loads(text): pts = [] for raw in text.splitlines(): line = raw.strip() if not line or line.startswith('#') or line.startswith('//'): continue parts = line.replace(',', ' ').split() if len(parts) < 2: continue try: th, rho = float(parts[0]), float(parts[1]) except ValueError: continue if math.isfinite(th) and math.isfinite(rho): pts.append((th, min(1.0, max(0.0, rho)))) return pts def load(path): with open(path, encoding='utf-8', errors='replace') as f: pts = loads(f.read()) if len(pts) < 2: raise ValueError(f'{path}: no theta-rho points found') return pts def dumps(pts, header=None): out = [] if header: out += [f'# {h}' for h in header.splitlines()] out += [f'{th:.5f} {rho:.5f}' for th, rho in pts] return '\n'.join(out) + '\n' def save(path, pts, header=None): with open(path, 'w') as f: f.write(dumps(pts, header))