Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 27 additions & 37 deletions nbs/examples/14_probes.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,9 @@
"import sax"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4",
"metadata": {},
"outputs": [],
"source": [
"sax.__file__"
]
},
{
"cell_type": "markdown",
"id": "5",
"id": "4",
"metadata": {},
"source": [
"## Define Component Models\n",
Expand All @@ -69,7 +59,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "6",
"id": "5",
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -101,7 +91,7 @@
},
{
"cell_type": "markdown",
"id": "7",
"id": "6",
"metadata": {},
"source": [
"## MZI Circuit\n",
Expand All @@ -121,7 +111,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "8",
"id": "7",
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -154,7 +144,7 @@
},
{
"cell_type": "markdown",
"id": "9",
"id": "8",
"metadata": {},
"source": [
"## Adding Probes\n",
Expand All @@ -167,7 +157,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "10",
"id": "9",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -183,7 +173,7 @@
},
{
"cell_type": "markdown",
"id": "11",
"id": "10",
"metadata": {},
"source": [
"The circuit now has additional ports for each probe. Each probe creates two ports:\n",
Expand All @@ -194,7 +184,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "12",
"id": "11",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -205,7 +195,7 @@
},
{
"cell_type": "markdown",
"id": "13",
"id": "12",
"metadata": {},
"source": [
"## Simulating with Probes\n",
Expand All @@ -216,7 +206,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "14",
"id": "13",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -231,7 +221,7 @@
},
{
"cell_type": "markdown",
"id": "15",
"id": "14",
"metadata": {},
"source": [
"### Output Transmission\n",
Expand All @@ -242,7 +232,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "16",
"id": "15",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -260,7 +250,7 @@
},
{
"cell_type": "markdown",
"id": "17",
"id": "16",
"metadata": {},
"source": [
"### Signal at Probe Points\n",
Expand All @@ -271,7 +261,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "18",
"id": "17",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -289,15 +279,15 @@
},
{
"cell_type": "markdown",
"id": "19",
"id": "18",
"metadata": {},
"source": [
"As expected with a 50/50 coupler, the signal is split equally between the two arms.\n"
]
},
{
"cell_type": "markdown",
"id": "20",
"id": "19",
"metadata": {},
"source": [
"## Probes Don't Affect Circuit Behavior\n",
Expand All @@ -308,7 +298,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "21",
"id": "20",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -324,15 +314,15 @@
},
{
"cell_type": "markdown",
"id": "22",
"id": "21",
"metadata": {},
"source": [
"The outputs are identical (within numerical precision), confirming that probes are purely observational."
]
},
{
"cell_type": "markdown",
"id": "23",
"id": "22",
"metadata": {},
"source": [
"## Summary\n",
Expand All @@ -354,18 +344,18 @@
},
{
"cell_type": "markdown",
"id": "24",
"id": "23",
"metadata": {},
"source": [
"## Ports as probes\n",
"\n",
"When a port is applied on an internal node (i.e., an instance port that is already part of a connection), it will automatically be interpreted as a probe. SAX will issue a warning and create `{name}_fwd` and `{name}_bwd` ports instead of the original port name."
"When a port is applied on an internal node (i.e., an instance port that is already part of a connection) it usually is ignored, however we can also make it it automatically be interpreted as a probe:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "25",
"id": "24",
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -397,7 +387,7 @@
" \"waveguide\": waveguide,\n",
"}\n",
"\n",
"circuit, _ = sax.circuit(mzi_netlist, models)\n",
"circuit, _ = sax.circuit(mzi_netlist, models, on_internal_port=\"as_probes\")\n",
"\n",
"S = circuit(\n",
" wl=wl,\n",
Expand All @@ -411,7 +401,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "26",
"id": "25",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -432,7 +422,7 @@
},
{
"cell_type": "markdown",
"id": "27",
"id": "26",
"metadata": {},
"source": [
"## Hierarchical Probes\n",
Expand All @@ -445,7 +435,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "28",
"id": "27",
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -500,7 +490,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "29",
"id": "28",
"metadata": {},
"outputs": [],
"source": [
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dev = [
"scikit-learn>=1.6.1",
"tmm>=0.2.0",
"towncrier>=24.0.0",
"ty>=0.0.1a11"
"ty>=0.0.20"
]
docs = [
"altair>=5.5.0",
Expand Down
24 changes: 23 additions & 1 deletion src/sax/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@
__all__ = ["circuit", "draw_dag", "get_required_circuit_models"]


def _filter_portless_subnets(
netlist: sax.RecursiveNetlist,
) -> sax.RecursiveNetlist:
"""Remove sub-netlists that have no ports (except the top-level entry)."""
top_level_name = next(iter(netlist))
return {
name: flatnet
for name, flatnet in netlist.items()
if name == top_level_name or flatnet.get("ports", {})
}


@overload
def circuit(
netlist: dict[str, Any],
Expand All @@ -37,6 +49,7 @@ def circuit(
top_level_name: str = "top_level",
ignore_impossible_connections: bool = False,
probes: dict[str, str] | None = None,
on_internal_port: Literal["warn", "ignore", "as_probes"] = "warn",
) -> tuple[sax.SDictModel, sax.CircuitInfo]: ...


Expand All @@ -50,6 +63,7 @@ def circuit(
top_level_name: str = "top_level",
ignore_impossible_connections: bool = False,
probes: dict[str, str] | None = None,
on_internal_port: Literal["warn", "ignore", "as_probes"] = "warn",
) -> tuple[sax.SDictModel, sax.CircuitInfo]: ...


Expand All @@ -63,6 +77,7 @@ def circuit(
top_level_name: str = "top_level",
ignore_impossible_connections: bool = False,
probes: dict[str, str] | None = None,
on_internal_port: Literal["warn", "ignore", "as_probes"] = "warn",
) -> tuple[sax.SDenseModel, sax.CircuitInfo]: ...


Expand All @@ -76,6 +91,7 @@ def circuit(
top_level_name: str = "top_level",
ignore_impossible_connections: bool = False,
probes: dict[str, str] | None = None,
on_internal_port: Literal["warn", "ignore", "as_probes"] = "warn",
) -> tuple[sax.SCooModel, sax.CircuitInfo]: ...


Expand All @@ -88,6 +104,7 @@ def circuit(
top_level_name: str = "top_level",
ignore_impossible_connections: bool = False,
probes: dict[str, str] | None = None,
on_internal_port: Literal["warn", "ignore", "as_probes"] = "warn",
) -> tuple[sax.Model, sax.CircuitInfo]:
"""Create a circuit function for a given netlist.

Expand All @@ -113,6 +130,10 @@ def circuit(
connection and exposes forward and backward traveling wave ports.
For a probe named "X" at instance port "inst,port", two new circuit
ports are created: "X_fwd" and "X_bwd". Defaults to None.
on_internal_port: How to handle top-level ports that map to internal
connection nodes. ``"warn"`` (default) drops them with a warning,
``"ignore"`` drops them silently, ``"as_probes"`` converts them
to measurement probes (legacy behaviour).

Returns:
Tuple containing:
Expand Down Expand Up @@ -158,13 +179,14 @@ def waveguide(length=10.0, neff=2.4, wl=1.55):
)
patch_netlist_array_instances(recnet)
recnet = sax.into[sax.RecursiveNetlist](recnet)
recnet, auto_probes = extract_port_probes(recnet)
recnet, auto_probes = extract_port_probes(recnet, on_internal_port)
if auto_probes:
probes = {**(probes or {}), **auto_probes}
if probes:
recnet = expand_probes(recnet, probes)
models = {"_ideal_probe": ideal_probe, **(models or {})}
recnet = resolve_array_instances(recnet)
recnet = _filter_portless_subnets(recnet)
recnet = remove_unused_instances(recnet)
_validate_netlist_ports(recnet)
dependency_dag = _create_dag(recnet, models, validate=True)
Expand Down
6 changes: 4 additions & 2 deletions src/sax/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ def to_df(
obj: an xarray or a sax.SType object.
target_name: the name of the target column
in the dataframe (ignored when obj is an SType).
kwargs: the coordinates of the SType values axes
(ignored when obj is an xarray).
kwargs: the coordinates of the SType values axes. You probably want to supply
'wl' or 'f' here, i.e. the coordinates you supplied to generate the SType.
The kwargs are ignored when the object is an xarray as the coordinates are
already embedded in the xarray in that case.
"""
if isinstance(obj, xr.DataArray):
xarr = obj
Expand Down
Loading
Loading