File size: 12,158 Bytes
9e41b00
 
 
 
 
 
 
 
 
 
 
 
7f2103c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e41b00
 
936798b
9e41b00
caee978
9e41b00
 
 
 
d55f641
 
9e41b00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
caee978
936798b
caee978
936798b
 
9e41b00
 
 
 
 
 
 
 
 
 
caee978
 
 
 
 
 
 
 
 
 
 
 
936798b
9e41b00
 
 
caee978
 
 
9e41b00
 
 
 
 
936798b
9e41b00
936798b
 
 
 
 
 
9e41b00
 
 
936798b
 
caee978
 
936798b
9e41b00
 
 
 
caee978
 
 
 
936798b
caee978
936798b
 
 
 
 
 
 
 
 
 
 
caee978
9e41b00
936798b
 
9e41b00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
caee978
 
 
 
9e41b00
caee978
9e41b00
 
 
 
 
caee978
9e41b00
 
 
 
caee978
 
9e41b00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
caee978
9e41b00
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
---
license: apache-2.0
library_name: onnx
pipeline_tag: image-segmentation
tags:
- electrical
- floor-plan
- construction
- circuit
- connectivity
- onnx
- takeoff
metrics:
- f1
- precision
- recall
model-index:
  - name: electrical-circuit-connectivity
    results:
      - task:
          type: image-segmentation
          name: Electrical symbol detection on E-sheets
        dataset:
          name: Synthetic held-out sheets (800 tiles, scan-degraded)
          type: constructelligence/circuits-synthetic
          split: test
        metrics:
          - type: f1
            value: 0.966
            name: Symbols F1 (all classes)
      - task:
          type: image-segmentation
          name: Circuit connectivity on real E-sheets
        dataset:
          name: Real US E-sheets, held out (5 plan regions)
          type: constructelligence/circuits-real
          split: test
        metrics:
          - type: recall
            value: 0.736
            name: Circuited devices found
          - type: f1
            value: 0.541
            name: Wiring runs F1
          - type: f1
            value: 0.759
            name: Same-circuit pair F1
---

# Electrical circuit connectivity (circuits-0.6)

**Trained for UK and US electrical drawings.** Reads an **electrical floor plan** (scan, photo or PDF render of an E-sheet) and returns **which devices are on
which circuit**: every receptacle, switch, light fixture, exit sign and junction box it finds, the wiring runs
drawn between them, which circuits have a home run, and roughly how much wiring each circuit draws on the sheet.

> **This is a lite model**, trained on synthetic sheets and openly published public drawing sets. It is released
> for research and evaluation. **Constructelligence is developing frontier construction-AI models** — this open kit
> is the *lite* tier, and the company's proprietary production models are available at
> **[constructelligence.co](https://constructelligence.co)**.

It is a drafting aid for takeoff and review. **It is not a code-compliance check and it is not an as-built.** It
reads what is drawn. Accuracy on real sheets is moderate and varies with drafting style (see *Results on real E-sheets*).

## How it works

1. **CircuitNet** is a 1.7M-parameter U-Net that takes grayscale input and produces stride-2
   outputs:
   - `peaks`: 13 per-class centre heatmaps, already 3×3-NMS'd (12 symbol classes plus the home-run arrowhead).
   - `size`: log box size.
   - `wire`: a single wiring mask. Arcs and home-run lines appear as continuous centre lines, dashed runs are
     bridged, and walls, door swings, dimension strings and conductor hash marks are excluded.
2. **`decode.py`** turns those outputs into a graph:
   - It cuts the mask at every symbol so each drawn run becomes its own stroke, thins the strokes and builds a
     skeleton graph.
   - It resolves crossings: at an X, the two straightest continuations pair up, so runs that cross without a dot
     stay separate circuits. A dead-straight pair of arms next to a symbol is a run passing by, not landing on it.
   - Stroke ends land on symbols or arrowheads, and a union-find groups the devices into circuits.

Classes: `receptacle`, `gfci_receptacle`, `switch`, `switch_3way`, `ceiling_fixture`, `downlight`, `troffer`, `strip_light`, `exit_sign`, `junction_box`, `panelboard`, `data_outlet`, `homerun_arrow`. `data_outlet` and `panelboard` are detected but never wired: data is
low voltage, and panels are fed by home runs.

## Results

These are measured on **800 held-out synthetic 512×512 sheets** (seeds never used in training), with scan
degradation applied: noise, blur, JPEG, thresholding and faded contrast.

| | model | decoder on perfect inputs (ceiling) | nearest-neighbour baseline |
|---|---|---|---|
| Wiring runs F1 | **0.836** | 0.902 | 0.323 |
| Same-circuit pair F1 | **0.817** | 0.839 | 0.247 |
| Circuits reproduced exactly | **60.0%** | 70.7% | 2.3% |
| Home runs found | **90.8%** | 95.9% | — |
| Symbols F1 (all classes) | **0.966** | 1.000 | 1.000 |

- *Decoder on perfect inputs* feeds the decoder the ground-truth wire mask and symbol boxes. The gap between the
  model column and this one is the model's error, and the gap between this column and 1.0 is the decoder's.
- *Nearest-neighbour baseline* uses ground-truth symbols and wires each device to its nearest neighbour. It shows
  what you would get without reading the wiring at all.

Per-class symbol detection:

| class | GT boxes | precision | recall | F1 |
|---|---|---|---|---|
| `receptacle` | 11000 | 0.961 | 0.999 | **0.979** |
| `gfci_receptacle` | 1595 | 0.984 | 0.870 | **0.923** |
| `switch` | 2008 | 0.894 | 0.906 | **0.900** |
| `switch_3way` | 677 | 0.963 | 0.852 | **0.904** |
| `ceiling_fixture` | 884 | 0.934 | 0.829 | **0.878** |
| `downlight` | 4052 | 0.942 | 0.981 | **0.961** |
| `troffer` | 4266 | 0.995 | 0.997 | **0.996** |
| `strip_light` | 1017 | 0.990 | 0.997 | **0.994** |
| `exit_sign` | 963 | 0.993 | 0.975 | **0.984** |
| `junction_box` | 133 | 0.716 | 0.511 | **0.597** |
| `panelboard` | 19 | 1.000 | 0.474 | **0.643** |
| `data_outlet` | 260 | 0.996 | 0.965 | **0.981** |
| `homerun_arrow` | 7257 | 0.956 | 0.995 | **0.975** |

## Results on real E-sheets (held out)

**United States.** The model was tested on **5 plan regions from 4 real US sheets it never
trained on** (Colusa County Admin Office lighting plans, Town of Windsor Highway Garage lighting and power plans).
That's 439 circuited devices and 284 drawn runs.

The ground truth is read from each PDF's own vector geometry: circuit-layer strokes are the runs, their ends on
fixture symbols are the devices (CAD bends contracted), and filled arrowheads mark home runs. Every sheet was
checked for 100% ink alignment. Each region was run at the page's default symbol size, with no per-sheet tuning.

| real sheets, pooled | circuits-0.6 | circuits-0.1 (synthetic only) |
|---|---|---|
| Circuited devices found | **0.736** | 0.731 |
| Wiring runs F1 | **0.541** | 0.343 |
| Wiring runs precision | **0.523** | 0.267 |
| Same-circuit pair F1 | **0.759** | 0.606 |
| Same-circuit pair precision | **0.719** | 0.604 |
| Home runs found | **0.138** | 0.238 |

| region | GT devices | GT runs | devices found | runs F1 | pair F1 | home runs |
|---|---|---|---|---|---|---|
| `colusa-e11#0` | 112 | 84 | 0.80 | 0.63 | 0.88 | 0.36 |
| `colusa-e11a#0` | 100 | 78 | 0.84 | 0.64 | 0.85 | 0.36 |
| `colusa-e11a#1` | 11 | 5 | 1.00 | 0.46 | 1.00 | 0.00 |
| `windsor-e101#0` | 116 | 75 | 0.72 | 0.50 | 0.42 | 0.00 |
| `windsor-e103#0` | 100 | 42 | 0.55 | 0.25 | 0.90 | 0.02 |

This is still far below the synthetic numbers, so check real output against the drawing. Home-run detection on
real sheets is the weakest part.

**United Kingdom.** Two held-out UK lighting layouts by two different design firms, drafted to BS EN 60617 (a
school refurbishment in Cardiff and a basement lighting layout in Camden, London): 187 circuited
devices and 141 drawn runs, scored exactly like the US sheets.

| UK sheets, pooled | circuits-0.6 | circuits-0.3 (US-only training) |
|---|---|---|
| Circuited devices found | **0.743** | 0.449 |
| Wiring runs F1 | **0.188** | 0.047 |
| Same-circuit pair F1 | **0.497** | 0.056 |
| Home runs found | **0.667** | 0.333 |

| region | GT devices | GT runs | devices found | runs F1 | pair F1 | home runs |
|---|---|---|---|---|---|---|
| `uk-cardiff-gf#0` | 114 | 80 | 0.87 | 0.33 | 0.79 | 0.67 |
| `uk-camden-streat#0` | 73 | 61 | 0.55 | 0.00 | 0.04 | 0.00 |

UK accuracy is lower than US and varies by firm: on the Camden layout the model finds about half the devices but reads none of the runs correctly yet.

Harder synthetic sheets (v2 generator: type tags, ceiling grids, clouds, long linear fixtures), 400 held out:
runs F1 **0.797**, pair F1 **0.800**, symbols F1
**0.943**, home runs **87.6%**.

## Use

```bash
pip install onnxruntime numpy pillow
python predict.py plan.png --symbol-px 20 --out circuits.png --json circuits.json
```

`--symbol-px` sets the sheet scale: 20 suits a PDF rendered at 150 dpi (tuned on real sheets). The model saw symbols of about
12–24 px, and the script rescales the sheet to match. Sheets of any size are processed in overlapping 512 px
tiles. The same ONNX also runs in the browser with onnxruntime-web.

## Training data

The model trained first on synthetic sheets with exact ground truth, then was fine-tuned on a mix of new synthetic
sheets and real public drawing sets. Real training labels come from the PDFs' vector geometry, with no hand
labelling:
- **US wired sheets (5):** Pender County Hampstead Annex; SW Polk Fire District Rickreall Station; Sparks.
- **UK wired sheets (8):** Derbyshire Fire & Rescue temporary accommodation; Saunders Interiors, 12 Madrid Road London SW13; Seaford Town Council, Martello Cafe & Public Toilets.
- **Philippine wired sheets (1):** Southern Leyte State University.
- **Negatives (15):** architectural, mechanical, plumbing and reflected-ceiling sheets, and sheets that give circuits by tag with no drawn runs (a common UK convention). They teach "no devices" or "no drawn wiring".

The real test sheets were never used for training.

The synthetic sheets contain:

- **Background:** a screened architectural layer with walls (outlined, filled or hatched), doors and door swings,
  windows, furniture, room tags, column grid bubbles, keynote hexagons and dimension strings.
- **Symbols:** NECA/ANSI-style devices in several drafting styles; 30% of sheets drafted UK-style (BS EN 60617: semicircle sockets, switch levers, cross-in-circle lamps, dashed switching links, DB/circuit tags); 10% German-style (DIN EN 60617-11: protective-earth sockets, conductor ticks, NYM cable callouts, UV/F tags). German drawings were synthetic only: there is no German real-sheet evaluation; 5% Australian/NZ-style (AS/NZS 1102: double GPOs, L3.5-style board.circuit tags); 5% Indian-style (IS 732 point wiring: fans and tube lights wired back to wall switchboards); these styles were synthetic only (no held-out real sheets from those countries), so no accuracy is claimed for them.
- **Circuits:** runs drawn curved, straight or orthogonal, some dashed, some with conductor hash marks and
  neutral ticks. Home-run arrows are single or double, with circuit tags.
- **Routing rules a drafter follows:** runs route around other symbols, and arrowheads never touch another run.

The real sheets are public bid, tender and planning documents published by public bodies in the US, UK, Australia, Canada and the Philippines. They were
used to train and evaluate and are not redistributed here.

This repository is inference-only: ONNX weights, the graph decoder and an example. Training code and the synthetic sheet generator are not published.

## Limitations

- **Real-sheet accuracy is moderate** (see the real results above), and it varies a lot by drafting style.
  Expect misses on symbol styles it hasn't seen. Stroke ends that reach no recognised symbol become
  "unrecognized" devices, so connectivity survives a missed symbol, but the device type is unknown.
- **Text is not read.** Circuit numbers beside home runs, panel names and switch letters are not OCR'd, so a
  circuit is "a group of connected devices with or without a home run", not "LP-1-12".
- **Shallow crossings and tangent arcs** are where the decoder still merges or splits circuits. That is the
  ceiling column above.
- **Wiring length** is measured on the drawing in pixels. It becomes feet only once you apply the sheet scale,
  and drawn arcs are schematic, not routed conduit.

## Files

- `circuits.onnx`: the model. Input `image` is [N,1,H,W] grayscale 0–255 with H and W multiples of 32. Outputs
  are `peaks`, `size` and `wire` at H/2 × W/2.
- `decode.py`: the graph decoder (pure Python and NumPy).
- `decoder_config.json`: the decoder's settings (thresholds, distances), tuned on real sheets.
- `predict.py`: command-line example (onnxruntime only).
- `config.json`: classes, strides, decoder thresholds and metrics.
- `example.png` / `example-circuits.png`: a held-out test sheet and the model's reading of it.