Circuit rendering skins
When rendering a Circuit, an Experiment or a Processor, you can select a skin which will change how the components are displayed.
>>> import perceval as pcvl
>>> c = pcvl.Circuit(4).add(0, pcvl.BS.H()).add(2, pcvl.BS.H())
>>> pcvl.pdisplay(c, skin = pcvl.SymbSkin(compact_display = True))

Perceval provides two skins for an easy usage:
SymbSkin
: a sober black and white skinPhysSkin
: a more colorful “real-life” skin (default one)
Both share the same init signature,
with an optional boolean kwarg compact_display
that makes the circuit components smaller and closer to each other.
Skin classes can be selected to be used across several perceval runs using the DisplayConfig.
>>> from perceval.rendering import DisplayConfig, SymbSkin
>>> DisplayConfig.select_skin(SymbSkin) # SymbSkin will be used by default by pdisplay if no other skin is defined.
>>> DisplayConfig.save() # Will save the current DisplayConfig into your Perceval persistent configuration.
Note that since the DisplayConfig class stores a skin class and not an instance, the compact_display attribute needs to be given again each time.
It’s also possible to hack an existing skin to fit your needs or even create a new one by subclassing the ASkin
abstract class,
though it will not be easy to save it.
Perceval also provides a DebugSkin
that builds on PhysSkin
,
but that also displays the heralded modes of an Experiment, and highlights whether phase shifters are defined or not.
As its name suggests, this skin should only be used when debugging as it is not made for a pretty and readable display.
Skin code reference
All skins follow the ASkin
interface, except for the __init__()
where subclasses already have their own style:
- class perceval.rendering.circuit.abstract_skin.ASkin(photonic_style, style_subcircuit, compact_display=False)
- A skin is required in the use of pdisplay for the following formats:
Format.HTML
Format.MPLOT
Format.LATEX
- A skin has three major responsibilities:
measuring the display size of a component / composite circuit
providing shape functions to draw individual components
exposing style data (stroke style, colors, etc.)
- Parameters:
photonic_style (
dict
) – photonic mode style, containing stroke specifications {“stroke”: color_str, “stroke_width”: int}style_subcircuit (
dict
) – subcircuit style specifications {“width”: int, “stroke_style”: {“stroke”: color_str, “stroke_width”: int}, “fill”: color_str}compact_display (
bool
) – whether to display some large components in a more compact way, to use less screen space
- abstract default_shape(c, canvas, mode_style)
Define a fallback shape for unknown components
- Parameters:
c – the component to draw
canvas – the canvas on which to draw
mode_style – the style for all modes
- abstract get_shape(c)
Returns a callable able to draw the shape of a given component on a canvas
- Parameters:
c – the component to draw
- Return type:
callable
- abstract get_width(c)
Returns the width of a component
- Parameters:
c – the component to measure
- Return type:
int
- measure(c)
Returns the measure (in arbitrary unit (AU) where the space between two modes = 1 AU) of a single component treated as a block (meaning that a composite circuit will not be measured recursively. Use get_size() instead)
- Return type:
tuple
[int
,int
]