Skip to content

Commit 2a62de2

Browse files
authored
Fix viz (#106)
1 parent 8e3892c commit 2a62de2

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

viz/to_json.py

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# viz/to_json.py
12
# Copyright 2025 Google LLC
23
#
34
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,13 +18,20 @@
1718
import re
1819
import numpy as np
1920

21+
INT_RE = re.compile(r'-?\d+')
22+
23+
def parse_int_list(text):
24+
"""Extract all integers from a string, tolerant to spaces/commas/brackets."""
25+
return [int(x) for x in INT_RE.findall(text)]
26+
2027
def parse_implicit_list(line, prefix):
2128
if not line.startswith(prefix):
2229
raise ValueError(f"Expected line to start with '{prefix}', got: {line}")
2330
list_part = line[len(prefix):].strip().rstrip(',')
2431
if not list_part:
2532
return []
26-
return [int(x.strip()) for x in list_part.split(',') if x.strip()]
33+
# Be tolerant: accept "1, 2, 3" or "1 2 3"
34+
return parse_int_list(list_part)
2735

2836
def parse_logfile(filepath):
2937
detector_coords = {}
@@ -38,21 +46,37 @@ def parse_logfile(filepath):
3846
line = lines[i].strip()
3947

4048
if not any(line.startswith(s) for s in ['Error', 'Detector', 'activated_errors', 'activated_detectors']):
41-
continue
49+
i += 1
50+
continue
4251

4352
if line.startswith("Detector D"):
44-
match = re.match(r'Detector D(\d+) coordinate \(([-\d.]+), ([-\d.]+), ([-\d.]+)\)', line)
53+
# Example: "Detector D123 coordinate (1.0, 2.0, 3.0)"
54+
match = re.match(
55+
r'Detector D(\d+)\s+coordinate\s*\(\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*\)',
56+
line
57+
)
4558
if match:
4659
idx = int(match.group(1))
4760
coord = tuple(float(match.group(j)) for j in range(2, 5))
4861
detector_coords[idx] = coord
4962

5063
elif line.startswith("Error{"):
51-
match = re.search(r'Symptom\{([^\}]+)\}', line)
52-
if match:
53-
dets = match.group(1).split()
54-
det_indices = [int(d[1:]) for d in dets if d.startswith('D')]
55-
error_to_detectors.append(det_indices)
64+
# New format: Error{..., symptom=Symptom{detectors=[75 89 93 100], observables=[...]}}
65+
# Fallback: old format with "D###" tokens inside Symptom{...}
66+
dets = []
67+
68+
m_detlist = re.search(r'detectors=\[([^\]]*)\]', line)
69+
if m_detlist:
70+
dets = parse_int_list(m_detlist.group(1))
71+
else:
72+
# Old fallback: scrape Symptom{...} and look for D###
73+
m_sym = re.search(r'Symptom\{([^}]*)\}', line)
74+
if m_sym:
75+
tokens = m_sym.group(1).split()
76+
dets = [int(t[1:]) for t in tokens if t.startswith('D') and t[1:].isdigit()]
77+
78+
# Store (even if empty—we keep the index alignment with errors)
79+
error_to_detectors.append(dets)
5680

5781
elif line.startswith("activated_errors"):
5882
try:
@@ -62,34 +86,39 @@ def parse_logfile(filepath):
6286
activated_errors = parse_implicit_list(error_line, "activated_errors =")
6387
activated_dets = parse_implicit_list(det_line, "activated_detectors =")
6488

65-
frame = {
89+
frames.append({
6690
"activated": activated_dets,
6791
"activated_errors": activated_errors
68-
}
69-
frames.append(frame)
70-
i += 1
92+
})
93+
94+
# We consumed two lines in this block
95+
i += 2
96+
continue # skip the unconditional i+=1 below (already advanced)
7197
except Exception as e:
7298
print(f"\n⚠️ Error parsing frame at lines {i}-{i+1}: {e}")
7399
print(f" {lines[i].strip()}")
74100
print(f" {lines[i+1].strip() if i+1 < len(lines) else ''}")
101+
75102
i += 1
76103

77104
if not detector_coords:
78105
raise RuntimeError("No detectors parsed!")
79106

107+
# Center detector coordinates
80108
coords_array = np.array(list(detector_coords.values()))
81109
mean_coord = coords_array.mean(axis=0)
82110
for k in detector_coords:
83111
detector_coords[k] = (np.array(detector_coords[k]) - mean_coord).tolist()
84112

113+
# Error coordinates as mean of their detectors (if known)
85114
error_coords = {}
86-
for i, det_list in enumerate(error_to_detectors):
115+
for ei, det_list in enumerate(error_to_detectors):
87116
try:
88117
pts = np.array([detector_coords[d] for d in det_list if d in detector_coords])
89118
if len(pts) > 0:
90-
error_coords[i] = pts.mean(axis=0).tolist()
119+
error_coords[ei] = pts.mean(axis=0).tolist()
91120
except KeyError as e:
92-
print(f"⚠️ Skipping error {i}: unknown detector {e}")
121+
print(f"⚠️ Skipping error {ei}: unknown detector {e}")
93122

94123
error_to_detectors_dict = {str(i): dets for i, dets in enumerate(error_to_detectors)}
95124

0 commit comments

Comments
 (0)