# DRC Reference: DRC expressions

DRC expression objects represent abstract recipes for the Layer#drc universal DRC function. For example, when using a universal DRC expression like this:

    out = in.drc(width < 2.0)

"width < 2.0" forms a DRC expression object. DRC expression objects have methods which manipulate or evaluate the results of this expression. In addition, DRC expressions have a result type, which is either polygon, edge or edge pair. The result type is defined by the expression generating it. In the example above, "width < 2.0" is a DRC width check which renders edge pairs. To obtain polygons from these edge pairs, use the "polygons" method:

    out = in.drc((width < 2.0).polygons)

The following documentation will list the methods available for DRC expression objects.

## "!" - Logical not

Usage:

- ! expression

This operator will evaluate the expression after. If this expression renders an empty result, the operator will return the primary shape. Otherwise it will return an empty result.

This operator can be used together with predicates such a "rectangles" to invert their meaning. For example, this code selects all primary shapes which are not rectangles:

    out = in.drc(! rectangles)
    out = in.drc(! primary.rectangles)   # equivalent

## "&" - Boolean AND between the results of two expressions

Usage:

- expression & expression

The & operator will compute the boolean AND between the results of two expressions. The expression types need to be edge or polygon.

The following example computes the partial edges where width is less than 0.3 micrometers and space is less than 0.2 micrometers:

    out = in.drc((width < 0.3).edges & (space < 0.2).edges)

## "+" - Boolean OR between the results of two expressions

Usage:

- expression + expression

The + operator will join the results of two expressions.

## "-" - Boolean NOT between the results of two expressions

Usage:

- expression - expression

The - operator will compute the difference between the results of two expressions. The NOT operation is defined for polygons, edges and polygons subtracted from edges (first argument edge, second argument polygon).

The following example will produce edge markers where the width of is less then 0.3 micron but not inside polygons on the "waive" layer:

    out = in.drc((width < 0.3).edges - secondary(waive))

## "^" - Boolean XOR between the results of two expressions

Usage:

- expression - expression

The ^ operator will compute the XOR (symmetric difference) between the results of two expressions. The XOR operation is defined for polygons and edges. Both expressions must be of the same type.

## "angle" - Selects edges based on their angle

Usage:

- expression.angle (in condition)

This operation selects edges by their angle, measured against the horizontal axis in the mathematical sense.

For this measurement edges are considered without their direction and straight lines. A horizontal edge has an angle of zero degree. A vertical one has an angle of 90 degee. The angle range is from -90 (exclusive) to 90 degree (inclusive).

If the input shapes are not polygons or edge pairs, they are converted to edges before the angle test is made.

For example, the following code selects all edges from the primary shape which are 45 degree (up) or 135 degree (down). The "+" will join the results:

    out = in.drc((angle == 45) + (angle == 135))
    out = in.drc((primary.angle == 45) + (primary.angle == 135))    # equivalent

Note that angle checks usually imply the need to rotation variant formation as cells which are placed unrotated and rotated by 90 degree cannot be considered identical. This imposes a performance penalty in hierarchical mode. If possible, consider using DRC#rectilinear for example to detect shapes with non-manhattan geometry instead of using angle checks.

The "angle" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.angle".

## "area" - Selects the primary shape if the area is meeting the condition

Usage:

- expression.area (in condition)

This operation is used in conditions to select shapes based on their area. It is applicable on polygon expressions. The result will be the input polygons if the area condition is met.

See Layer#drc for more details about comparison specs.

The following example will select all polygons with an area less than 2.0 square micrometers:

    out = in.drc(area < 2.0)
    out = in.drc(primary.area < 2.0)   # equivalent

The area method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.area".

## "bbox_height" - Selects the primary shape if its bounding box height is meeting the condition

Usage:

- expression.bbox_height (in condition)

This operation acts similar to DRC#bbox_min, but takes the height of the shape's bounding box. In general, it's more advisable to use DRC#bbox_min or DRC#bbox_max because bbox_height implies a certain orientation. This can imply variant formation in hierarchical contexts: cells rotated by 90 degree have to be treated differently from ones not rotated. This usually results in a larger computation effort and larger result files.

The "bbox_height" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.bbox_height".

## "bbox_max" - Selects the primary shape if its bounding box larger dimension is meeting the condition

Usage:

- expression.bbox_max (in condition)

This operation acts similar to DRC#bbox_min, but takes the larger dimension of the shape's bounding box.

The "bbox_max" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.bbox_max".

## "bbox_min" - Selects the primary shape if its bounding box smaller dimension is meeting the condition

Usage:

- expression.bbox_min (in condition)

This operation is used in conditions to select shapes based on smaller dimension of their bounding boxes. It is applicable on polygon expressions. The result will be the input polygons if the bounding box condition is met.

See Layer#drc for more details about comparison specs.

The following example will select all polygons whose bounding box smaller dimension is larger than 200 nm:

    out = in.drc(bbox_min > 200.nm)
    out = in.drc(primary.bbox_min > 200.nm)   # equivalent

The "bbox_min" method is available as a plain function or as a method on DRC# expressions. The plain function is equivalent to "primary.bbox_min".

## "bbox_width" - Selects the primary shape if its bounding box width is meeting the condition

Usage:

- expression.bbox_width (in condition)

This operation acts similar to DRC#bbox_min, but takes the width of the shape's bounding box. In general, it's more advisable to use DRC#bbox_min or DRC#bbox_max because bbox_width implies a certain orientation. This can imply variant formation in hierarchical contexts: cells rotated by 90 degree have to be treated differently from ones not rotated. This usually results in a larger computation effort and larger result files.

The "bbox_width" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.bbox_width".

## "centers" - Returns the part at the center of each edge of the input

Usage:

- expression.centers(length)
- expression.end_segments(length, fraction)

This method acts on edge expressions and delivers a specific part of each edge. See layer#centers for details about this functionality.

## "corners (in condition)" - Applies smoothing

Usage:

- expression.corners
- expression.corners(as_dots)
- expression.corners(as_boxes)

This operation acts on polygons and selects the corners of the polygons. It can be put into a condition to select corners by their angles. The angle of a corner is positive for a turn to the left if walking a polygon counterclockwise and negative for the turn to the right. Angles take values between -180 and 180 degree.

When using "as_dots" for the argument, the operation will return single-point edges at the selected corners. With "as_boxes" (the default), small (2x2 DBU) rectangles will be produced at each selected corner.

The following example selects all corners:

    out = in.drc(corners)
    out = in.drc(primary.corners)    # equivalent

The following example selects all inner corners:

    out = in.drc(corners < 0)
    out = in.drc(primary.corners < 0)    # equivalent

The "corners" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.corners".

## "count" - Selects a expression result based on the number of (local) shapes

Usage:

- expression.count (in condition)

This operation is used in conditions to select expression results based on their count. "count" is used as a method on a expression. It will evaluate the expression locally and return the original result if the shape count in the result is matching the condition.

See Layer#drc for more details about comparison specs.

Note that the expression is evaluated locally: for each primary shape, the expression is evaluated and the count of the resulting edge, edge pair or polygon set is taken. As the primary input will always have a single item (the local shape), using "count" on primary does not really make sense. It can be used on derived expressions however.

The following example selects triangles:

    out = in.drc(if_any(corners.count == 3))

Note "if_any" which selects the primary shape if the argument evaluates to a non-empty result. Without "if_any" three corners are returned for each triangle.

## "edges" - Converts the input shapes into edges

Usage:

- expression.edges

Polygons will be separated into edges forming their contours. Edge pairs will be decomposed into individual edges.

Contrary most other operations, "edges" does not have a plain function equivalent as this is reserved for the function generating an edges layer. To generate the edges of the primary shapes, use "primary" explicit as the source for the edges:

    out = in.drc(primary.edges)

## "end_segments" - Returns the part at the end of each edge of the input

Usage:

- expression.end_segments(length)
- expression.end_segments(length, fraction)

This method acts on edge expressions and delivers a specific part of each edge. See layer#end_segments for details about this functionality.

## "extended" - Returns polygons describing an area along the edges of the input

Usage:

- expression.extended([:begin => b,] [:end => e,] [:out => o,] [:in => i], [:joined => true])
- expression.extended(b, e, o, i)

This method acts on edge expressions. It will create a polygon for each edge tracing the edge with certain offsets to the edge. "o" is the offset applied to the outer side of the edge, "i" is the offset applied to the inner side of the edge. "b" is the offset applied at the beginning and "e" is the offset applied at the end.

## "extended_in" - Returns polygons describing an area along the edges of the input

Usage:

- expression.extended_in(d)

This method acts on edge expressions. Polygons are generated for each edge describing the edge drawn with a certain width extending into the "inside" (the right side when looking from start to end). This method is basically equivalent to the extended method: "extended(0, 0, 0, dist)". A version extending to the outside is extended_out.

## "extended_out" - Returns polygons describing an area along the edges of the input

Usage:

- expression.extended_out(d)

This method acts on edge expressions. Polygons are generated for each edge describing the edge drawn with a certain width extending into the "outside" (the left side when looking from start to end). This method is basically equivalent to the extended method: "extended(0, 0, dist, 0)". A version extending to the inside is extended_in.

## "extent_refs" - Returns partial references to the boundings boxes of the polygons

Usage:

- expression.extent_refs([ options ])

The extent_refs operation acts on polygons and has the same effect than Layer#extent_refs. It takes the same arguments. It is available as a method on DRC expressions or as plain function, in which case it acts on the primary shapes.

## "extents" - Returns the bounding box of each input object

Usage:

- expression.extents([ enlargement ])

This method provides the same functionality as Layer#extents and takes the same arguments. It returns the bounding boxes of the input objects. It acts on edge edge pair and polygon expressions.

The "extents" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.extents".

## "first_edges" - Returns the first edges of edge pairs

Usage:

- expression.extents([ enlargement ])

This method acts on edge pair expressions and returns the first edges of the edge pairs delivered by the expression.

## "holes" - Selects all holes from the input polygons

Usage:

- expression.holes

This operation can be used as a plain function in which case it acts on primary shapes or can be used as method on another DRC expression. The following example selects all holes with an area larger than 2 square micrometers:

    out = in.drc(holes.area > 2.um)
    out = in.drc(primary.holes.area > 2.um)   # equivalent

## "hulls" - Selects all hulls from the input polygons

Usage:

- expression.hulls

The hulls are the outer contours of the input polygons. By selecting hulls only, all holes will be closed.

This operation can be used as a plain function in which case it acts on primary shapes or can be used as method on another DRC expression. The following example closes all holes:

    out = in.drc(hulls)
    out = in.drc(primary.hulls)   # equivalent

## "length" - Selects edges based on their length

Usage:

- expression.length (in condition)

This operation will select those edges which are meeting the length criterion. Non-edge shapes (polygons, edge pairs) will be converted to edges before.

For example, this code selects all edges from the primary shape which are longer or equal than 1 micrometer:

    out = in.drc(length >= 1.um)
    out = in.drc(primary.length >= 1.um)   # equivalent

The "length" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.length".

## "merged" - Returns the merged input polygons, optionally selecting multi-overlap

Usage:

- expression.merged
- expression.merged(min_count)

This operation will act on polygons. Without a min_count argument, the merged polygons will be returned.

With a min_count argument, the result will include only those parts where more than the given number of polygons overlap. As the primary input is merged already, it will always contribute as one.

The "merged" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.merged".

## "middle" - Returns the centers of polygon bounding boxes

Usage:

- expression.middle([ options ])

The middle operation acts on polygons and has the same effect than Layer#middle. It takes the same arguments. It is available as a method on DRC expressions or as plain function, in which case it acts on the primary shapes.

## "odd_polygons" - Selects all polygons which are non-orientable

Usage:

- expression.odd_polygons

Non-orientable polygons are for example "8"-shape polygons. Such polygons are usually considered harmful as their definition of covered area is depending on the wrap count rule in place.

This operation can be used as a plain function in which case it acts on primary shapes or can be used as method on another DRC expression.

## "perimeter" - Selects the primary shape if the perimeter is meeting the condition

Usage:

- expression.perimeter (in condition)

This operation is used in conditions to select shapes based on their perimeter. It is applicable on polygon expressions. The result will be the input polygons if the perimeter condition is met.

See Layer#drc for more details about comparison specs.

The following example will select all polygons with a perimeter less than 10 micrometers:

    out = in.drc(perimeter < 10.0)
    out = in.drc(primary.perimeter < 10.0)   # equivalent

The perimeter method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.perimeter".

## "polygons" - Converts the input shapes into polygons

Usage:

- expression.polygons([ enlargement ])

Generates polygons from the input shapes. Polygons stay polygons. Edges and edge pairs are converted to polygons. For this, the enlargement parameter will specify the edge thickness or augmentation applied to edge pairs. With the default enlargement of zero edges will not be converted to valid polygons and degenerated edge pairs will not become valid polygons as well.

Contrary most other operations, "polygons" does not have a plain function equivalent as this is reserved for the function generating a polygon layer.

This method is useful for generating polygons from DRC violation markers as shown in the following example:

    out = in.drc((width < 0.5.um).polygons)

## "rectangles" - Selects all polygons which are rectangles

Usage:

- expression.rectangles

This operation can be used as a plain function in which case it acts on primary shapes or can be used as method on another DRC expression. The following example selects all rectangles:

    out = in.drc(rectangles)
    out = in.drc(primary.rectangles)    # equivalent

## "rectilinear" - Selects all polygons which are rectilinear

Usage:

- expression.rectilinear

Rectilinear polygons only have vertical and horizontal edges. Such polygons are also called manhattan polygons.

This operation can be used as a plain function in which case it acts on primary shapes or can be used as method on another DRC expression. The following example selects all manhattan polygons:

    out = in.drc(rectilinear)
    out = in.drc(primary.rectilinear)    # equivalent

## "rounded_corners" - Applies corner rounding

Usage:

- expression.rounded_corners(inner, outer, n)

This operation acts on polygons and applies corner rounding the the given inner and outer corner radius and the number of points n per full circle. See Layer#rounded_corners for more details.

The "rounded_corners" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.rounded_corners".

## "second_edges" - Returns the second edges of edge pairs

Usage:

- expression.extents([ enlargement ])

This method acts on edge pair expressions and returns the second edges of the edge pairs delivered by the expression.

## "sized" - Returns the sized version of the input

Usage:

- expression.sized(d [, mode])
- expression.sized(dx, dy [, mode]))

This method provides the same functionality as Layer#sized and takes the same arguments. It acts on polygon expressions.

The "sized" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.sized".

## "smoothed" - Applies smoothing

Usage:

- expression.smoothed(d)

This operation acts on polygons and applies polygon smoothing with the tolerance d. See Layer#smoothed for more details.

The "smoothed" method is available as a plain function or as a method on DRC expressions. The plain function is equivalent to "primary.smoothed".

## "start_segments" - Returns the part at the beginning of each edge of the input

Usage:

- expression.start_segments(length)
- expression.start_segments(length, fraction)

This method acts on edge expressions and delivers a specific part of each edge. See layer#start_segments for details about this functionality.

## "|" - Boolean OR between the results of two expressions

Usage:

- expression | expression

The | operator will compute the boolean OR between the results of two expressions. '+' is basically a synonym. Both expressions must render the same type.