# Software Map
This page is the top-level mental map of the Public Quantum Network: how the whole system fits together, how a single Node is structured, where each package lives, and how a real request flows through everything.
```{note}
For a glossary of the terms used here (Node, Node API, Instrument Provider, ProxyInstrument, Protocol, Experiment, GUI), see `CONTEXT.md` at the repository root.
Deeper, package-specific details live under {doc}`../pqn-node/index`, {doc}`../pqn-gui/index`, and {doc}`../pqn-hardware/index`. Operator-focused setup lives under {doc}`../deployment/index`.
```
## 1. The PQN Network
At the network level the PQN is a small group of optical labs scattered across a few institutions. Each lab is a **Node**: it can run quantum experiments end to end on its own, and any pair of Nodes that have been physically connected can team up on experiments that need two sites at once, like the CHSH Bell test.
Connecting two Nodes takes two channels. Classically, like normal computers, every Node sits on a shared VPN that links all the participating sites. Quantumly, the two labs are physically joined by an optical fibre that lets them exchange entangled photons. The fibre carries the quantum state of the experiment; the VPN carries the classical bookkeeping the two Nodes need to agree on what they measured.
A visitor meets a Node through its **GUI**, a small web app that runs alongside the Node API. The GUI is the part of the PQN that the public actually sees.
```{mermaid}
flowchart LR
GUIA[GUI]:::client
GUIB[GUI]:::client
subgraph NodeA["Node A"]
APIA[Node API]
InstrA[(Optical
hardware)]
end
subgraph NodeB["Node B"]
APIB[Node API]
InstrB[(Optical
hardware)]
end
GUIA -.HTTP.-> APIA
GUIB -.HTTP.-> APIB
APIA <==>|"classical (VPN)"| APIB
InstrA <==>|"quantum (optical fibre)"| InstrB
classDef client fill:#fff3e0,stroke:#b36b1f;
```
Inside a Node, the Node API is the only component that ever talks to anything outside the Node. Everything else (Router, Instrument Providers, drivers, instruments) lives on the Node's local network and is reachable only through the Node API. Nothing in the PQN is exposed to the public internet.
## 2. A single Node
Zoom into one Node. It contains four logical layers:
```{mermaid}
flowchart TB
GUI[GUI / browser]:::ext
Peer[Peer Node API]:::ext
subgraph Node["Node (site intranet)"]
API[Node API
pqn-node]
Router[Router
pqn-hardware]
Provider1[Instrument Provider
pqn-hardware]
Provider2[Instrument Provider
pqn-hardware]
Driver1[Driver]
Driver2[Driver]
Driver3[Driver]
Instr1[(Physical
Instrument)]
Instr2[(Physical
Instrument)]
Instr3[(Physical
Instrument)]
end
GUI -.HTTP / WebSocket.-> API
Peer -.HTTP.-> API
API -- ZMQ --> Router
Router -- ZMQ --> Provider1
Router -- ZMQ --> Provider2
Provider1 --> Driver1
Provider1 --> Driver2
Provider2 --> Driver3
Driver1 --> Instr1
Driver2 --> Instr2
Driver3 --> Instr3
classDef ext fill:#eee,stroke:#888,stroke-dasharray: 4 2;
```
- **Node API** (in `pqn-node`): FastAPI service. The only component reachable from outside. Handles GUI requests and peer-Node coordination. Owns the orchestration logic for each Experiment.
- **Router** (in `pqn-hardware`): ZMQ message broker. All in-Node messaging passes through it.
- **Instrument Provider** (in `pqn-hardware`): process that hosts physical instruments. A Node can run more than one Provider; for example, one machine per optics table or per piece of expensive hardware.
- **Driver** (in `pqn-hardware`): concrete instrument implementation. Talks to one piece of physical hardware (Thorlabs rotator, TimeTagger, etc.).
The Node API never talks to a Driver directly. It calls a **ProxyInstrument**, a client-side handle whose method calls are serialised onto the Router and dispatched to whichever Instrument Provider hosts the real instrument. This means the Node API code does not need to know which machine an instrument is plugged into.
## 3. The three packages
The same picture, redrawn around the package boundary instead of the runtime topology:
```{mermaid}
flowchart LR
GUI["pqn-gui
Next.js · TypeScript
public web UI"]:::ts
Node["pqn-node
FastAPI · Python
Node API service"]:::py
HW["pqn-hardware
library · Python
drivers, Router, Provider"]:::py
GUI -- HTTP / WebSocket --> Node
Node -- imports --> HW
Node -- launches --> RouterProc["Router process
pqn-hw start-router"]
Node -- launches --> ProviderProc["Instrument Provider process
pqn-hw start-provider"]
RouterProc -. provided by .- HW
ProviderProc -. provided by .- HW
classDef py fill:#e6f0ff,stroke:#3b6cb3;
classDef ts fill:#fff3e0,stroke:#b36b1f;
```
- **`pqn-node`** is the only package that actually runs the Node API service. It depends on `pqn-hardware` as a git-pinned library and orchestrates everything: HTTP routing, peer-Node coordination, Protocol logic, Experiment lifecycle, WebSocket streaming.
- **`pqn-gui`** is a Next.js application. It has no Python; it knows the Node API only through its HTTP/WebSocket surface.
- **`pqn-hardware`** is a Python library *and* a CLI (`pqn-hw`). The library is consumed in-process by `pqn-node` for ProxyInstrument calls. The CLI runs the Router and Instrument Provider as separate long-lived processes, started during deployment.
The split between `pqn-node` and `pqn-hardware` exists so that hardware-driver work (which moves at the pace of new instruments and ZMQ infrastructure changes) can evolve independently of the FastAPI service (which moves at the pace of new Experiments and UI features).
## 4. Walkthrough: a single-Node experiment
What happens when a visitor clicks **Run** on the Quantum Fortune page in the GUI:
```{mermaid}
sequenceDiagram
actor User
participant GUI as GUI
(pqn-gui)
participant API as Node API
(pqn-node)
participant Proto as Protocol
(pqn-node)
participant Router as Router
(pqn-hardware)
participant Provider as Instrument Provider
(pqn-hardware)
participant Instr as Physical Instrument
User->>GUI: click "Run"
GUI->>API: POST /experiments/quantum-fortune
API->>Proto: invoke Protocol
Proto->>Router: ProxyInstrument call
Router->>Provider: routed ZMQ message
Provider->>Instr: driver call
Instr-->>Provider: measurement
Provider-->>Router: result
Router-->>Proto: result
Proto-->>API: result
API-->>GUI: WebSocket update
GUI-->>User: render result
```
Two things to notice:
1. **ProxyInstruments hide the network.** From the Protocol's point of view, calling an instrument looks like a local method call, but the call is actually marshalled across ZMQ to wherever the Hardware Provider is running.
2. **Results stream back over WebSocket.** Long-running experiments emit progress updates as they go, so the GUI can render live counts and partial results rather than waiting for a single response at the end.
## 5. Walkthrough: a two-Node CHSH experiment
The CHSH Bell test is the canonical multi-Node Experiment. Two Nodes (call them Alice and Bob) each measure one half of an entangled pair on independently chosen polarisation bases, and the Node API on the initiating side aggregates the results.
```{mermaid}
sequenceDiagram
actor User
participant GUI as GUI
(at Alice)
participant Alice as Node API
Alice
participant Bob as Node API
Bob
participant InstrA as Alice's
instruments
participant InstrB as Bob's
instruments
User->>GUI: click "Run CHSH"
GUI->>Alice: POST /experiments/chsh
(peer = Bob)
Alice->>Bob: announce run, exchange config
par measurement on each side
Alice->>InstrA: rotate, measure
InstrA-->>Alice: counts
and
Bob->>InstrB: rotate, measure
InstrB-->>Bob: counts
end
Bob-->>Alice: counts for Bob's bases
Alice->>Alice: compute CHSH inequality value
Alice-->>GUI: WebSocket result
GUI-->>User: render Bell-violation plot
```
Key points:
- The **GUI only talks to one Node API** (Alice's). The peer-Node coordination is entirely between Node APIs over HTTP. The GUI never connects to Bob.
- Each Node drives its own instruments through its own Router and Instrument Providers; neither side touches the other side's hardware.
- The initiating Node (Alice) is responsible for aggregating the joint statistics and computing the Bell inequality value.
## Where to go next
- {doc}`../deployment/index`: how to actually stand up a Node and join a network.
- {doc}`../pqn-node/index`, {doc}`../pqn-gui/index`, {doc}`../pqn-hardware/index`: package-specific internals.
- {doc}`../physical-devices/index`: build guides for the physical instruments referenced throughout this page.