live_viewer.LiveViewer
LiveViewer( port: int = 0, *, start: bool = True, host: str | None = None, allowed_hosts: Sequence[str] = (), auto_refresh: bool = True, auto_refresh_delay: float = 0.1, verbose: bool = True,) -> NoneLive viewer for PhotonForge objects and layout files.
A displayed component can be edited in the Schematic view: move, turn,
flip and resize symbols, draw wires, place components added with
add_to_component_library, delete, group, undo and redo. Edits
change the component passed in, in place (there is no separate copy),
and component holds it. Save, in the viewer’s toolbar, writes it
to a .phf file. Moving, turning or resizing a symbol changes only
the drawing, never the layout.
The server listens on this machine only (127.0.0.1), and accepts
edits, file opens and folder listings only from its own page. On a
remote machine, reach it through a tunnel:
- SSH:
ssh -L 8765:127.0.0.1:8765 user@remote, then openhttp://localhost:8765. The local port can differ. - A proxy on the remote machine (jupyter-server-proxy, a VS Code tunnel
or a Codespace) reaches the viewer on
127.0.0.1too, but the page is opened under the proxy’s name, which the viewer must be told:allowed_hosts=["jupyter.example.com", "*.app.github.dev"]. - In VS Code in the browser (code-server), the viewer allows the name in
VSCODE_PROXY_URIby itself and gives its address under that proxy. - To be reached directly over the network, or from outside a container,
pass
host="0.0.0.0"(andallowed_hostsfor the name the page is opened by). Anything that can reach the port can then try to edit the design, so prefer a tunnel.
The plugins.photonforge.live_viewer_host and
plugins.photonforge.live_viewer_allowed_hosts tidy3d settings
provide machine-wide defaults. Their environment overrides are named
TIDY3D_PLUGINS__PHOTONFORGE__LIVE_VIEWER_<FIELD>.
Args
- port: Port the viewer listens on;
0takes any free one. If the port is not available, another one is used (see notes below). - start: If
True, the viewer server is automatically started. - host: Address the server listens on. Defaults to
127.0.0.1. - allowed_hosts: Host names the viewer’s page may be opened by (see description above).
- auto_refresh: If
True, automatically refresh the most recently displayed component after successful IPython cell executions. - auto_refresh_delay: Seconds to wait for another cell execution before rebuilding the displayed component.
- verbose: If
True, print status messages and notices: the server address, ports in use, refused edits, and where edits are kept. IfFalse, the viewer prints nothing.
Example
>>> from photonforge.live_viewer import LiveViewer>>> viewer = LiveViewer()>>> component = pf.parametric.straight(port_spec="Strip", length=3)>>> viewer(component)Note
If port is being used by another viewer in this Python session,
that viewer is replaced. Otherwise, the port number is incremented
until a free port is found. LiveViewer.port holds the used
port number. A port that another program or another Python process’s
viewer uses is never taken: a verbose viewer says which process uses
it and how to stop that process.
Methods
Section titled “Methods”| Method | Description |
|---|---|
add_to_component_library | Add a component to the schematic editor’s component library, to place from there. |
changes | What was changed in the viewer, to write into the script that builds the design. |
display | Display a component, reference, 2D structure or GDSII/OASIS path. |
generate | |
set_status | Show a live status line in the browser’s loading overlay. |
start | Start the server. |
stop | Stop the server and free its port. |
add_to_component_library
Section titled “add_to_component_library”add_to_component_library( self, source: Any, name: str | None = None, category: str | None = None) -> strAdd a component to the schematic editor’s component library, to place from there.
The library is listed under the schematic toolbar’s Add button, as the GUI’s Component Library panel is, and keeps what it holds whatever is displayed. A placed component is added to the circuit and to the chip, where it goes into free space past the right edge of the layout, unrouted; on the page it lands where it was dropped.
Args
- source: A component, or a callable returning one. A callable is called again for every placement, so each drop can be its own cell.
- name: What the menu calls it. Defaults to the component’s name as the schematic captions it, without the parametric digest, with a number added if taken.
- category: The group the panel lists it under, as the GUI lists each library under its own name (“Passives”, “SiEPIC”, “My PCells”). Entries without one are listed under “Added from Python”.
Returns
The name to pass as cell in an add_instance edit.
changes
Section titled “changes”changes( self, since: photonforge._live_viewer.schematic_changes.Changes | None = None,) -> photonforge._live_viewer.schematic_changes.ChangesWhat was changed in the viewer, to write into the script that builds the design.
Edits made here change the component in place, and a script that builds it again makes it as it was. This lists the net effect of every edit to the component on screen since the first one: instances added, deleted, moved, turned or given new parameters; wires, nets and routes added or taken off, and route settings changed; the circuit’s own ports and terminals; shapes drawn on it. Each change is said in words and given as Python, with instances named as the viewer names them and identified by their cell and where the script put them, so the script’s own variable can be found. A device moved and moved back is no change; a route rebuilt because its devices moved is none.
Args
- since: An earlier result, for only what changed after it.
Returns
The changes: print them, iterate over them, python() for the code,
as_dicts() for plain data, and edits for the edits themselves with the
time each was made and the browser tab it came from.
Example
>>> changes = viewer.changes()>>> print(changes) # what the person changed, in words>>> print(changes.python()) # the same, as lines for the scriptdisplay
Section titled “display”display(self, item: ~_T) -> ~_TDisplay a component, reference, 2D structure or GDSII/OASIS path.
generate
Section titled “generate”generate(self) -> AsyncGenerator[str, NoneType]No description available.
set_status
Section titled “set_status”set_status(self, text: str, *, scene_transition_done: bool = False) -> NoneShow a live status line in the browser’s loading overlay.
start(self) -> 'LiveViewer'Start the server.
Calling this again while the viewer runs does nothing. On the port asked for, a
different viewer this session already runs there is replaced, and one another program
holds is skipped for the next free port (see the port argument).
stop(self) -> NoneStop the server and free its port.
Properties
Section titled “Properties”| Property | Description |
|---|---|
component | The component on screen. |
scene_generation | Generation of the currently published native scene. |
component
Section titled “component”The component on screen.
A shape is shown in a component named after it ("Rectangle"), with the default
technology; a Reference in "LiveViewer Support", with its cell’s technology.
Returns None for a file or untouched blank canvas.
scene_generation
Section titled “scene_generation”Generation of the currently published native scene.
Attributes
Section titled “Attributes”| Attribute | Description |
|---|---|
AUTOSAVE_FOLDER | Path subclass for non-Windows systems. |
AUTOSAVE_KEEP | int([x]) -> integer |
MESSAGES_FOLDER | Path subclass for non-Windows systems. |
MESSAGES_KEEP | int([x]) -> integer |
AUTOSAVE_FOLDER
Section titled “AUTOSAVE_FOLDER”Path subclass for non-Windows systems.
On a POSIX system, instantiating a Path should return this object.
AUTOSAVE_KEEP
Section titled “AUTOSAVE_KEEP”int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ’+’ or ’-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer iteral.
>>> int('0b100', base=0)4MESSAGES_FOLDER
Section titled “MESSAGES_FOLDER”Path subclass for non-Windows systems.
On a POSIX system, instantiating a Path should return this object.
MESSAGES_KEEP
Section titled “MESSAGES_KEEP”int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ’+’ or ’-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer iteral.
>>> int('0b100', base=0)4