Troubleshooting & FAQ
Is there a way to not render a node in the SchematicGraph?
Rendering with a LayoutTarget
will skip all entities with the special metadata DeviceLayout.NORENDER_META = SemanticMeta(:norender)
, so there's a workaround: Try running map_metadata!(component(mynode), (_) -> DeviceLayout.NORENDER_META)
before calling build!
or render!
.
How do I attach components along a path in the schematic?
Given a schematic node containing the Path
, you can attach your component to that with attach!(::SchematicGraph, ...)
. For example:
pa = Path(
Point(0μm, 0μm),
α0=0°,
metadata=SemanticMeta(:metal_negative),
name=uniquename("coupseg")
)
straight!(pa, 250μm, cpw_style)
coupling_seg_node = add_node!(g, pa)
rres_node = add_node!(g, readout_resonator)
attach!.(
g,
coupling_seg_node,
rres_node => :readout_line,
pathlength(SchematicDrivenLayout.component(coupling_seg_node).path) / 2,
i=1,
location=1
)
# ... then fuse/route these to other nodes as usual
How do I attach components along a route in the schematic?
If you have an existing component created by route!(::SchematicGraph, ...)
, you can attach CoordinateSystemReferences
with the function attach!(r::RouteComponent, c::CoordSysRef, t::Coordinate; location::Int=0)
, and it works like attaching things to a single-segment Path
. Right now there's no way to attach a Component
along a RouteComponent
so that it becomes part of the schematic. For that, use a Path
with attach!(::SchematicGraph, ...)
.
What's with all the semicolons?
Semicolons are used in Julia in a few places related to key-value pairs:
In function definitions, separating positional arguments from keyword arguments.
- If there are no positional arguments, it's still necessary to start with a semicolon:
function f(; a=1, b=2)...
- If there are no positional arguments, it's still necessary to start with a semicolon:
In function calls, separating positional arguments from keyword arguments.
- This is optional, but may be used for clarity, especially when splatting keyword arguments when there are no positional arguments
To construct literal
NamedTuple
s:(; a=1, b=2)
.- The semicolon is optional, but if there is only one key/value pair, either a leading semicolon
(; a=1)
or trailing comma(a=1,)
must be used to distinguish it from the expressiona=1
wrapped in parentheses. (The leading semicolon is preferred for a couple reasons. A single-elementTuple
also uses a trailing comma; also, it's easy to accidentally remove the required trailing comma when removing all but one elements from the expression.) - An empty
NamedTuple
can also be constructed with(;)
. - You can also construct
NamedTuple
s programmatically by splatting an iterator yielding key-value pairs after the semicolon:(; a=1, my_namedtuple..., b=2)
.
- The semicolon is optional, but if there is only one key/value pair, either a leading semicolon
On the left-hand side of an assignment, to unpack/"destructure" a
NamedTuple
orstruct
(starting in Julia 1.7).(; a, b) = x
is equivalent to the assignmentsa = x.a
andb = x.b
For completeness, there are a couple unrelated uses of semicolons:
To separate statements without a line break, as in
a = x.a; b = x.b
To separate array literals for vertical concatenation, as in
A_2x3 = [1 2 3; 4 5 6]
- N semicolons concatenate along the Nth dimension, as in
A_3x2 = [1:3 ;; 4:6]
- N semicolons concatenate along the Nth dimension, as in
In SchematicDrivenLayout
specifically, we often work with the parameters
of a Component
as a NamedTuple
.
How do I add a schematic node so that it's at a fixed position on the chip?
One way to do that is to make a top-level parent component with a hook at the position you want. For example, you can use the built-in SchematicDrivenLayout.Spacer
component:
g = SchematicGraph("fixed_demo")
spacernode = add_node!(g, Spacer(p1=Point(6mm, 1mm)))
fuse!(g, spacernode => :p1_north, mycomp => :myhook)
Any "root" node (one that's not attached to any previously added non-route node by any chain of connections; this always includes the first node added to a graph) will have its origin at the global origin.
In many cases, it's useful to start with a "template" component containing multiple required fixed-position hooks. This is how ExampleChip
in the DemoQPU17 example fixes the positions of ports on the edge of the chip.
How do I attach one component to another if there's no hook where I need it?
If you need some offset relative to existing hooks, you can use the Spacer
(see above) with a p0
compass hook fused to one component and a p1
compass hook fused to the other.
For truly ad-hoc positioning, you can use fuse!
with an actual Hook
object rather than a Symbol
identifying the Hook
for one or both components. For example, this might be appropriate for labeling and annotation:
fuse!(
g,
mynode => PointHook(0.5mm, 0.5mm, 90°),
ArrowAnnotation{typeof(1.0nm)}(text="(0.5mm, 0.5mm) in mynode's coordinate system") =>
:tip
)
However, if you find yourself needing a consistent hook that doesn't already exist for MyComponent
, then it's generally better to update the component definition so that the hook is available by name through hooks(::MyComponent)
.
I edited a component's _geometry!
method but I'm still getting the old geometry. Can I get the new geometry without restarting Julia?
First, make sure the new code is being loaded. You can use Revise to automatically use updated code within any package loaded after Revise with import
or using
as well as any scripts loaded with includet
.
Most component types, including those defined using @compdef
, contain a _geometry
field that allows them to store their geometry so that it is only generated once. It is not marked as dirty or automatically regenerated when geometry methods change. Currently, to regenerate the geometry, you have to empty the geometry or instantiate a new component. (For composite components, there are also similar fields for their graph, schematic, and hooks.)