Coverage for qpdk / helper.py: 67%
51 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-14 10:27 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-14 10:27 +0000
1"""Helper functions for the qpdk package."""
3import warnings
4from collections.abc import Callable, Sequence
5from functools import wraps
6from typing import Any, cast
8from gdsfactory import Component, ComponentAllAngle, LayerEnum, get_component
9from gdsfactory.technology import LayerViews
10from gdsfactory.typings import ComponentAllAngleSpec, ComponentSpec, Layer
13def deprecated(msg: str | Callable | None = None) -> Any:
14 """Decorator to mark functions as deprecated.
16 Can be used as @deprecated or @deprecated("custom message").
17 """
19 def decorator(func: Callable) -> Callable:
20 @wraps(func)
21 def wrapper(*args: Any, **kwargs: Any) -> Any:
22 m = (
23 msg
24 if isinstance(msg, str)
25 else f"{func.__name__} is deprecated and will be removed in a future version."
26 )
27 warnings.warn(m, category=DeprecationWarning, stacklevel=2)
28 return func(*args, **kwargs)
30 return wrapper
32 if callable(msg):
33 f = msg
34 msg = None
35 return decorator(f)
36 return decorator
39def denest_layerviews_to_layer_tuples(
40 layer_views: LayerViews,
41) -> dict[str, tuple[int, int]]:
42 """De-nest LayerViews into a flat dictionary of layer names to layer tuples.
44 Args:
45 layer_views: LayerViews object containing the layer views.
47 Returns:
48 Dictionary mapping layer names to their corresponding (layer, datatype) tuples.
49 """
51 def denest_layer_dict_recursive(items: dict) -> dict:
52 """Recursively denest layer views to any depth.
54 Args:
55 items: Dictionary of layer view items to process
57 Returns:
58 Dictionary mapping layer names to layer objects
59 """
60 layers = {}
62 for key, value in items.items():
63 if value.group_members:
64 # Recursively process nested group members and merge results
65 nested_layers = denest_layer_dict_recursive(value.group_members)
66 layers.update(nested_layers)
67 else:
68 # Base case: add the layer to our dictionary
69 if hasattr(value, "layer"):
70 layers[key] = value.layer
72 return layers
74 # Start the recursive denesting process and return the result
75 return denest_layer_dict_recursive(layer_views.layer_views)
78def show_components(
79 *args: ComponentSpec | ComponentAllAngleSpec,
80 spacing: int = 200,
81) -> Sequence[Component]:
82 """Show sequence of components in a single layout in a line.
84 The components are spaced based on the maximum width and height of the components.
86 Args:
87 *args: Component specifications to show.
88 spacing: Extra spacing between components.
90 Returns:
91 Components after :func:`gdsfactory.get_component`.
92 """
93 from qpdk import PDK
95 PDK.activate()
97 components = [get_component(component_spec) for component_spec in args]
98 any_all_angle = any(
99 isinstance(component, ComponentAllAngle) for component in components
100 )
102 c = ComponentAllAngle() if any_all_angle else Component()
104 max_component_width = max(component.size_info.width for component in components)
105 max_component_height = max(component.size_info.height for component in components)
106 if max_component_width > max_component_height:
107 shift = (0, max_component_height + spacing)
108 else:
109 shift = (max_component_width + spacing, 0)
111 for i, component in enumerate(components):
112 (c << component).move(
113 (
114 shift[0] * i,
115 shift[1] * i,
116 )
117 )
118 label_offset = (
119 shift[0] * i + (component.size_info.width / 2),
120 shift[1] * i + (component.size_info.height / 2),
121 )
122 label_text = component.name if hasattr(component, "name") else f"component_{i}"
123 c.add_label(
124 text=label_text,
125 position=label_offset,
126 layer=cast(LayerEnum, PDK.layers).TEXT,
127 )
128 c.show()
130 return components
133def layerenum_to_tuple(layerenum: LayerEnum) -> Layer:
134 """Convert a LayerEnum object to a tuple containing layer and datatype values.
136 Args:
137 layerenum: The LayerEnum object to convert.
138 """
139 return layerenum.layer, layerenum.datatype