From 84f37195ad1abe6cece44cf710e443fe7c057e65 Mon Sep 17 00:00:00 2001 From: jan Date: Sat, 7 Mar 2026 00:33:18 -0800 Subject: [PATCH] [Pather / RenderPather / Tool] Rename path->trace in more locations --- masque/builder/pather.py | 64 ++++++++++++++++------------------ masque/builder/pather_mixin.py | 29 ++++++++------- masque/builder/renderpather.py | 17 +++++---- masque/builder/tools.py | 38 ++++++++++---------- 4 files changed, 71 insertions(+), 77 deletions(-) diff --git a/masque/builder/pather.py b/masque/builder/pather.py index e34aa00..df00cc0 100644 --- a/masque/builder/pather.py +++ b/masque/builder/pather.py @@ -28,7 +28,7 @@ class Pather(Builder, PatherMixin): single-use patterns (e.g. wires or waveguides) and bundles / buses of such patterns. `Pather` is mostly concerned with calculating how long each wire should be. It calls - out to `Tool.path` functions provided by subclasses of `Tool` to build the actual patterns. + out to `Tool.traceL` functions provided by subclasses of `Tool` to build the actual patterns. `Tool`s are assigned on a per-port basis and stored in `.tools`; a key of `None` represents a "default" `Tool` used for all ports which do not have a port-specific `Tool` assigned. @@ -63,7 +63,10 @@ class Pather(Builder, PatherMixin): Examples: Adding to a pattern ============================= - - `pather.path('my_port', ccw=True, distance)` creates a "wire" for which the output + - `pather.straight('my_port', distance)` creates a straight wire with a length + of `distance` and `plug`s it into `'my_port'`. + + - `pather.bend('my_port', ccw=True, distance)` creates a "wire" for which the output port is `distance` units away along the axis of `'my_port'` and rotated 90 degrees counterclockwise (since `ccw=True`) relative to `'my_port'`. The wire is `plug`ged into the existing `'my_port'`, causing the port to move to the wire's output. @@ -72,22 +75,15 @@ class Pather(Builder, PatherMixin): there may be a significant width to the bend that is used to accomplish the 90 degree turn. However, an error is raised if `distance` is too small to fit the bend. - - `pather.path('my_port', ccw=None, distance)` creates a straight wire with a length - of `distance` and `plug`s it into `'my_port'`. - - - `pather.path_to('my_port', ccw=False, position)` creates a wire which starts at + - `pather.trace_to('my_port', ccw=False, x=position)` creates a wire which starts at `'my_port'` and has its output at the specified `position`, pointing 90 degrees clockwise relative to the input. Again, the off-axis position or distance to the - output is not specified, so `position` takes the form of a single coordinate. To - ease debugging, position may be specified as `x=position` or `y=position` and an - error will be raised if the wrong coordinate is given. + output is not specified, so `position` takes the form of a single coordinate. - - `pather.mpath(['A', 'B', 'C'], ..., spacing=spacing)` is a superset of `path` - and `path_to` which can act on multiple ports simultaneously. Each port's wire is - generated using its own `Tool` (or the default tool if left unspecified). - The output ports are spaced out by `spacing` along the input ports' axis, unless - `ccw=None` is specified (i.e. no bends) in which case they all end at the same - destination coordinate. + - `pather.trace(['A', 'B', 'C'], ccw=True, spacing=spacing, xmax=position)` acts + on multiple ports simultaneously. Each port's wire is generated using its own + `Tool` (or the default tool if left unspecified). + The output ports are spaced out by `spacing` along the input ports' axis. - `pather.plug(wire, {'myport': 'A'})` places port 'A' of `wire` at 'myport' of `pather.pattern`. If `wire` has only two ports (e.g. 'A' and 'B'), no `map_out`, @@ -141,8 +137,8 @@ class Pather(Builder, PatherMixin): in which case it is interpreted as a name in `library`. Default `None` (no ports). tools: A mapping of {port: tool} which specifies what `Tool` should be used - to generate waveguide or wire segments when `path`/`path_to`/`mpath` - are called. Relies on `Tool.path` implementations. + to generate waveguide or wire segments when `trace`/`trace_to`/etc. + are called. Relies on `Tool.traceL` implementations. name: If specified, `library[name]` is set to `self.pattern`. """ self._dead = False @@ -213,7 +209,7 @@ class Pather(Builder, PatherMixin): and to which the new one should be added (if named). If not provided, `source.library` must exist and will be used. tools: `Tool`s which will be used by the pather for generating new wires - or waveguides (via `path`/`path_to`/`mpath`). + or waveguides (via `trace`/`trace_to`). in_prefix: Prepended to port names for newly-created ports with reversed directions compared to the current device. out_prefix: Prepended to port names for ports which are directly @@ -255,7 +251,7 @@ class Pather(Builder, PatherMixin): return s - def _pathU( + def _traceU( self, portspec: str, jog: float, @@ -281,21 +277,21 @@ class Pather(Builder, PatherMixin): self """ if self._dead: - logger.warning('Skipping geometry for _pathU() since device is dead') + logger.warning('Skipping geometry for _traceU() since device is dead') tool_port_names = ('A', 'B') tool = self.tools.get(portspec, self.tools[None]) in_ptype = self.pattern[portspec].ptype try: - tree = tool.pathU(jog, length=length, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) + tree = tool.traceU(jog, length=length, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) except (BuildError, NotImplementedError): if self._uturn_fallback(tool, portspec, jog, length, in_ptype, plug_into, **kwargs): return self if not self._dead: raise - logger.warning("Tool pathU failed for dead pather. Using dummy extension.") + logger.warning("Tool traceU failed for dead pather. Using dummy extension.") # Fallback for dead pather: manually update the port instead of plugging port = self.pattern[portspec] port_rot = port.rotation @@ -321,7 +317,7 @@ class Pather(Builder, PatherMixin): PortList.plugged(self, connections) return self - def _path( + def _traceL( self, portspec: str, ccw: SupportsBool | None, @@ -362,18 +358,18 @@ class Pather(Builder, PatherMixin): LibraryError if no valid name could be picked for the pattern. """ if self._dead: - logger.warning('Skipping geometry for _path() since device is dead') + logger.warning('Skipping geometry for _traceL() since device is dead') tool_port_names = ('A', 'B') tool = self.tools.get(portspec, self.tools[None]) in_ptype = self.pattern[portspec].ptype try: - tree = tool.path(ccw, length, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) + tree = tool.traceL(ccw, length, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) except (BuildError, NotImplementedError): if not self._dead: raise - logger.warning("Tool path failed for dead pather. Using dummy extension.") + logger.warning("Tool traceL failed for dead pather. Using dummy extension.") # Fallback for dead pather: manually update the port instead of plugging port = self.pattern[portspec] port_rot = port.rotation @@ -401,7 +397,7 @@ class Pather(Builder, PatherMixin): self.plug(tname, {portspec: tool_port_names[0], **output}) return self - def _pathS( + def _traceS( self, portspec: str, length: float, @@ -440,29 +436,29 @@ class Pather(Builder, PatherMixin): LibraryError if no valid name could be picked for the pattern. """ if self._dead: - logger.warning('Skipping geometry for _pathS() since device is dead') + logger.warning('Skipping geometry for _traceS() since device is dead') tool_port_names = ('A', 'B') tool = self.tools.get(portspec, self.tools[None]) in_ptype = self.pattern[portspec].ptype try: - tree = tool.pathS(length, jog, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) + tree = tool.traceS(length, jog, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) except NotImplementedError: # Fall back to drawing two L-bends ccw0 = jog > 0 kwargs_no_out = kwargs | {'out_ptype': None} try: - t_tree0 = tool.path( ccw0, length / 2, port_names=tool_port_names, in_ptype=in_ptype, **kwargs_no_out) + t_tree0 = tool.traceL( ccw0, length / 2, port_names=tool_port_names, in_ptype=in_ptype, **kwargs_no_out) t_pat0 = t_tree0.top_pattern() (_, jog0), _ = t_pat0[tool_port_names[0]].measure_travel(t_pat0[tool_port_names[1]]) - t_tree1 = tool.path(not ccw0, abs(jog - jog0), port_names=tool_port_names, in_ptype=t_pat0[tool_port_names[1]].ptype, **kwargs) + t_tree1 = tool.traceL(not ccw0, abs(jog - jog0), port_names=tool_port_names, in_ptype=t_pat0[tool_port_names[1]].ptype, **kwargs) t_pat1 = t_tree1.top_pattern() (_, jog1), _ = t_pat1[tool_port_names[0]].measure_travel(t_pat1[tool_port_names[1]]) kwargs_plug = kwargs | {'plug_into': plug_into} - self._path(portspec, ccw0, length - abs(jog1), **kwargs_no_out) - self._path(portspec, not ccw0, abs(jog - jog0), **kwargs_plug) + self._traceL(portspec, ccw0, length - abs(jog1), **kwargs_no_out) + self._traceL(portspec, not ccw0, abs(jog - jog0), **kwargs_plug) except (BuildError, NotImplementedError): if not self._dead: raise @@ -475,7 +471,7 @@ class Pather(Builder, PatherMixin): # Fall through to dummy extension below if self._dead: - logger.warning("Tool pathS failed for dead pather. Using dummy extension.") + logger.warning("Tool traceS failed for dead pather. Using dummy extension.") # Fallback for dead pather: manually update the port instead of plugging port = self.pattern[portspec] port_rot = port.rotation diff --git a/masque/builder/pather_mixin.py b/masque/builder/pather_mixin.py index 239f5a9..eeae7ad 100644 --- a/masque/builder/pather_mixin.py +++ b/masque/builder/pather_mixin.py @@ -74,14 +74,14 @@ class PatherMixin(PortList, metaclass=ABCMeta): raise BuildError('length is only allowed with a single port in trace()') if bounds: raise BuildError('length and bounds are mutually exclusive in trace()') - return self._path(portspec[0], ccw, length) + return self._traceL(portspec[0], ccw, length) if 'each' in bounds: each = bounds.pop('each') if bounds: raise BuildError('each and other bounds are mutually exclusive in trace()') for port in portspec: - self._path(port, ccw, each) + self._traceL(port, ccw, each) return self # Bundle routing (formerly mpath logic) @@ -106,7 +106,7 @@ class PatherMixin(PortList, metaclass=ABCMeta): extensions = ell(ports, ccw, spacing=spacing, bound=bound, bound_type=bound_type, set_rotation=set_rotation) for port_name, ext_len in extensions.items(): - self._path(port_name, ccw, ext_len, **bounds) + self._traceL(port_name, ccw, ext_len, **bounds) return self def trace_to( @@ -180,7 +180,7 @@ class PatherMixin(PortList, metaclass=ABCMeta): if 'length' in bounds and bounds['length'] is not None: raise BuildError('Cannot specify both relative length and absolute position in trace_to()') - return self._path(port_name, ccw, length, **other_bounds) + return self._traceL(port_name, ccw, length, **other_bounds) # Bundle routing (delegate to trace which handles ell) return self.trace(portspec, ccw, spacing=spacing, **bounds) @@ -211,7 +211,7 @@ class PatherMixin(PortList, metaclass=ABCMeta): if l_actual is None: # TODO: use bounds to determine length? raise BuildError('jog() currently requires a length') - self._pathS(port, l_actual, offset, **bounds) + self._traceS(port, l_actual, offset, **bounds) return self def uturn(self, portspec: str | Sequence[str], offset: float, length: float | None = None, **bounds) -> Self: @@ -224,7 +224,7 @@ class PatherMixin(PortList, metaclass=ABCMeta): if l_actual is None: # TODO: use bounds to determine length? l_actual = 0 - self._pathU(port, offset, length=l_actual, **bounds) + self._traceU(port, offset, length=l_actual, **bounds) return self def trace_into( @@ -360,15 +360,15 @@ class PatherMixin(PortList, metaclass=ABCMeta): L2 = abs(jog) - R kwargs_plug = kwargs | {'plug_into': plug_into} - self._path(portspec, ccw, L1, **kwargs_no_out) - self._path(portspec, ccw, L2, **kwargs_plug) + self._traceL(portspec, ccw, L1, **kwargs_no_out) + self._traceL(portspec, ccw, L2, **kwargs_plug) except (BuildError, NotImplementedError): return False else: return True @abstractmethod - def _path( + def _traceL( self, portspec: str, ccw: SupportsBool | None, @@ -380,7 +380,7 @@ class PatherMixin(PortList, metaclass=ABCMeta): pass @abstractmethod - def _pathS( + def _traceS( self, portspec: str, length: float, @@ -392,7 +392,7 @@ class PatherMixin(PortList, metaclass=ABCMeta): pass @abstractmethod - def _pathU( + def _traceU( self, portspec: str, jog: float, @@ -406,17 +406,17 @@ class PatherMixin(PortList, metaclass=ABCMeta): def path(self, *args, **kwargs) -> Self: import warnings warnings.warn("path() is deprecated; use trace(), straight(), or bend() instead", DeprecationWarning, stacklevel=2) - return self._path(*args, **kwargs) + return self._traceL(*args, **kwargs) def pathS(self, *args, **kwargs) -> Self: import warnings warnings.warn("pathS() is deprecated; use jog() instead", DeprecationWarning, stacklevel=2) - return self._pathS(*args, **kwargs) + return self._traceS(*args, **kwargs) def pathU(self, *args, **kwargs) -> Self: import warnings warnings.warn("pathU() is deprecated; use uturn() instead", DeprecationWarning, stacklevel=2) - return self._pathU(*args, **kwargs) + return self._traceU(*args, **kwargs) @abstractmethod def plug( @@ -762,4 +762,3 @@ class PortPather: del self.pather.pattern.ports[name] self.ports = [pp for pp in self.ports if pp != name] return self - diff --git a/masque/builder/renderpather.py b/masque/builder/renderpather.py index 2f78f8e..0e16c7b 100644 --- a/masque/builder/renderpather.py +++ b/masque/builder/renderpather.py @@ -377,7 +377,7 @@ class RenderPather(PatherMixin): PortList.plugged(self, connections) return self - def _pathU( + def _traceU( self, portspec: str, jog: float, @@ -403,7 +403,7 @@ class RenderPather(PatherMixin): self """ if self._dead: - logger.warning('Skipping geometry for _pathU() since device is dead') + logger.warning('Skipping geometry for _traceU() since device is dead') port = self.pattern[portspec] in_ptype = port.ptype @@ -437,7 +437,7 @@ class RenderPather(PatherMixin): self.plugged({portspec: plug_into}) return self - def _path( + def _traceL( self, portspec: str, ccw: SupportsBool | None, @@ -480,7 +480,7 @@ class RenderPather(PatherMixin): LibraryError if no valid name could be picked for the pattern. """ if self._dead: - logger.warning('Skipping geometry for _path() since device is dead') + logger.warning('Skipping geometry for _traceL() since device is dead') port = self.pattern[portspec] in_ptype = port.ptype @@ -520,7 +520,7 @@ class RenderPather(PatherMixin): return self - def _pathS( + def _traceS( self, portspec: str, length: float, @@ -564,7 +564,7 @@ class RenderPather(PatherMixin): LibraryError if no valid name could be picked for the pattern. """ if self._dead: - logger.warning('Skipping geometry for _pathS() since device is dead') + logger.warning('Skipping geometry for _traceS() since device is dead') port = self.pattern[portspec] in_ptype = port.ptype @@ -587,8 +587,8 @@ class RenderPather(PatherMixin): jog1 = Port((0, 0), 0).measure_travel(t_port1)[0][1] kwargs_plug = kwargs | {'plug_into': plug_into} - self._path(portspec, ccw0, length - abs(jog1), **kwargs_no_out) - self._path(portspec, not ccw0, abs(jog - jog0), **kwargs_plug) + self._traceL(portspec, ccw0, length - abs(jog1), **kwargs_no_out) + self._traceL(portspec, not ccw0, abs(jog - jog0), **kwargs_plug) except (BuildError, NotImplementedError): if not self._dead: raise @@ -803,4 +803,3 @@ class RenderPather(PatherMixin): def rect(self, *args, **kwargs) -> Self: self.pattern.rect(*args, **kwargs) return self - diff --git a/masque/builder/tools.py b/masque/builder/tools.py index c964fe7..f8a72fb 100644 --- a/masque/builder/tools.py +++ b/masque/builder/tools.py @@ -93,7 +93,7 @@ class Tool: unimplemented (e.g. in cases where they don't make sense or the required components are impractical or unavailable). """ - def path( + def traceL( self, ccw: SupportsBool | None, length: float, @@ -136,9 +136,9 @@ class Tool: Raises: BuildError if an impossible or unsupported geometry is requested. """ - raise NotImplementedError(f'path() not implemented for {type(self)}') + raise NotImplementedError(f'traceL() not implemented for {type(self)}') - def pathS( + def traceS( self, length: float, jog: float, @@ -178,7 +178,7 @@ class Tool: Raises: BuildError if an impossible or unsupported geometry is requested. """ - raise NotImplementedError(f'path() not implemented for {type(self)}') + raise NotImplementedError(f'traceS() not implemented for {type(self)}') def planL( self, @@ -260,7 +260,7 @@ class Tool: """ raise NotImplementedError(f'planS() not implemented for {type(self)}') - def pathU( + def traceU( self, jog: float, *, @@ -298,7 +298,7 @@ class Tool: Raises: BuildError if an impossible or unsupported geometry is requested. """ - raise NotImplementedError(f'pathU() not implemented for {type(self)}') + raise NotImplementedError(f'traceU() not implemented for {type(self)}') def planU( self, @@ -467,7 +467,7 @@ class SimpleTool(Tool, metaclass=ABCMeta): pat.plug(bend, {port_names[1]: inport}, mirrored=mirrored) return tree - def path( + def traceL( self, ccw: SupportsBool | None, length: float, @@ -484,7 +484,7 @@ class SimpleTool(Tool, metaclass=ABCMeta): out_ptype = out_ptype, ) - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'path') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceL') pat.add_port_pair(names=port_names, ptype='unk' if in_ptype is None else in_ptype) self._renderL(data=data, tree=tree, port_names=port_names, straight_kwargs=kwargs) return tree @@ -497,7 +497,7 @@ class SimpleTool(Tool, metaclass=ABCMeta): **kwargs, ) -> ILibrary: - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'path') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceL') pat.add_port_pair(names=(port_names[0], port_names[1])) for step in batch: @@ -774,7 +774,7 @@ class AutoTool(Tool, metaclass=ABCMeta): pat.plug(data.out_transition.abstract, {port_names[1]: data.out_transition.our_port_name}) return tree - def path( + def traceL( self, ccw: SupportsBool | None, length: float, @@ -791,7 +791,7 @@ class AutoTool(Tool, metaclass=ABCMeta): out_ptype = out_ptype, ) - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'path') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceL') pat.add_port_pair(names=port_names, ptype='unk' if in_ptype is None else in_ptype) self._renderL(data=data, tree=tree, port_names=port_names, straight_kwargs=kwargs) return tree @@ -930,7 +930,7 @@ class AutoTool(Tool, metaclass=ABCMeta): pat.plug(data.out_transition.abstract, {port_names[1]: data.out_transition.our_port_name}) return tree - def pathS( + def traceS( self, length: float, jog: float, @@ -946,7 +946,7 @@ class AutoTool(Tool, metaclass=ABCMeta): in_ptype = in_ptype, out_ptype = out_ptype, ) - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'pathS') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceS') pat.add_port_pair(names=port_names, ptype='unk' if in_ptype is None else in_ptype) self._renderS(data=data, tree=tree, port_names=port_names, gen_kwargs=kwargs) return tree @@ -1036,7 +1036,7 @@ class AutoTool(Tool, metaclass=ABCMeta): self._renderL(data.ldata1, tree, port_names, gen_kwargs) return tree - def pathU( + def traceU( self, jog: float, *, @@ -1053,7 +1053,7 @@ class AutoTool(Tool, metaclass=ABCMeta): out_ptype = out_ptype, **kwargs, ) - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'pathU') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceU') pat.add_port_pair(names=port_names, ptype='unk' if in_ptype is None else in_ptype) self._renderU(data=data, tree=tree, port_names=port_names, gen_kwargs=kwargs) return tree @@ -1066,7 +1066,7 @@ class AutoTool(Tool, metaclass=ABCMeta): **kwargs, ) -> ILibrary: - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'path') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceL') pat.add_port_pair(names=(port_names[0], port_names[1])) for step in batch: @@ -1107,7 +1107,7 @@ class PathTool(Tool, metaclass=ABCMeta): # self.width = width # self.ptype: str - def path( + def traceL( self, ccw: SupportsBool | None, length: float, @@ -1124,7 +1124,7 @@ class PathTool(Tool, metaclass=ABCMeta): out_ptype=out_ptype, ) - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'path') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceL') pat.path(layer=self.layer, width=self.width, vertices=[(0, 0), (length, 0)]) if ccw is None: @@ -1219,7 +1219,7 @@ class PathTool(Tool, metaclass=ABCMeta): # If the path ends in a bend, we need to add the final vertex path_vertices.append(local_batch[-1].end_port.offset) - tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'path') + tree, pat = Library.mktree(SINGLE_USE_PREFIX + 'traceL') pat.path(layer=self.layer, width=self.width, vertices=path_vertices) pat.ports = { port_names[0]: local_batch[0].start_port.copy().rotate(pi),