snapshot 2025-04-21 01:01:17.676650

This commit is contained in:
Jan Petykiewicz 2025-04-21 01:01:17 -07:00
parent 43994667f4
commit e21979baf0
12 changed files with 1047 additions and 15 deletions

View File

@ -0,0 +1,488 @@
GET
https://www.speedscope.app/
[HTTP/2 304 70ms]
GET
https://www.speedscope.app/speedscope-GHPHNKXC.css
[HTTP/3 200 OK 0ms]
GET
https://www.speedscope.app/speedscope-YI5LLI47.js
[HTTP/3 200 0ms]
GET
https://www.speedscope.app/chunk-JFPBPGZ4.js
[HTTP/3 200 0ms]
GET
https://www.speedscope.app/source-map-5DQ363YZ.js
[HTTP/3 200 0ms]
GET
https://www.speedscope.app/chunk-FW4363Y4.js
[HTTP/3 200 0ms]
GET
https://www.speedscope.app/SourceCodePro-Regular.ttf-ILST5JV6.woff2
[HTTP/3 200 0ms]
GET
https://www.speedscope.app/demangle-B53S5JWH.js
[HTTP/3 200 0ms]
GET
https://www.speedscope.app/import-2JMDXOIJ.js
[HTTP/3 200 0ms]
speedscope v1.22.2 speedscope-YI5LLI47.js:185:25290
WebGL initialized. renderer: null, vendor: null, version: WebGL 1.0 speedscope-YI5LLI47.js:167:1925
GET
https://www.speedscope.app/favicon-16x16-VSI62OPJ.png
[HTTP/3 200 0ms]
Importing as speedscope json file import-2JMDXOIJ.js:4:35604
import: 0ms - timer ended speedscope-YI5LLI47.js:185:18554
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
draw graphics.ts:449
render rectangle-batch-renderer.ts:140
writeToAtlasIfNeeded row-atlas.ts:70
dt utils.ts:19
writeToAtlasIfNeeded row-atlas.ts:59
render flamechart-renderer.ts:323
renderRects flamechart-minimap-view.tsx:88
setViewport canvas-context.ts:72
renderBehind canvas-context.ts:85
renderRects flamechart-minimap-view.tsx:87
onBeforeFrame flamechart-minimap-view.tsx:223
onBeforeFrame canvas-context.ts:63
requestFrame canvas-context.ts:53
renderCanvas flamechart-minimap-view.tsx:228
overlayCanvasRef flamechart-minimap-view.tsx:419
Preact 76
a atom.ts:149
set atom.ts:120
set atom.ts:120
set profile-group.ts:62
setProfileGroup profile-group.ts:71
loadProfile application.tsx:225
loadFromFile application.tsx:234
onFileSelect application.tsx:466
Preact 23
speedscope-YI5LLI47.js:1:25317
WebGL warning: texImage: Requested size at this level is unsupported.
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
The resource at “https://www.speedscope.app/SourceCodePro-Regular.ttf-ILST5JV6.woff2” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. www.speedscope.app
Source map error: Error: URL constructor: is not a valid URL.
Stack in the worker:resolveSourceMapURL@resource://devtools/client/shared/source-map-loader/utils/fetchSourceMap.js:56:22
getOriginalURLs@resource://devtools/client/shared/source-map-loader/source-map.js:73:24
workerHandler/</<@resource://devtools/client/shared/worker-utils.js:115:52
workerHandler/<@resource://devtools/client/shared/worker-utils.js:113:13
Resource URL: wasm:https://www.speedscope.app/demangle-B53S5JWH.js%20line%201%20%3E%20WebAssembly.instantiate
Source Map URL: null
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
(Async: FrameRequestCallback)
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
speedscope-YI5LLI47.js:1:25317
WebGL warning: checkFramebufferStatus: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attachment has no width or height.
After reporting 32, no further warnings will be reported for this WebGL context.
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
52 speedscope-YI5LLI47.js:1:25317
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
(Async: FrameRequestCallback)
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseMove flamechart-pan-zoom-view.tsx:685
Preact 31
Uncaught Error: Assertion failed.
H graphics.ts:34
get framebuffer graphics.ts:1379
_updateRenderTargetAndViewport graphics.ts:574
clear graphics.ts:501
onBeforeFrame canvas-context.ts:60
requestFrame canvas-context.ts:53
renderCanvas flamechart-pan-zoom-view.tsx:526
onMouseLeave flamechart-pan-zoom-view.tsx:691
Preact 31
speedscope-YI5LLI47.js:1:25317

386
examples/connectivity.py Normal file
View File

@ -0,0 +1,386 @@
from collections.abc import Sequence
from collections import defaultdict
from pprint import pformat
import logging
import numpy
from numpy.typing import NDArray, ArrayLike
import pyclipper
from pyclipper import (
Pyclipper, PT_CLIP, PT_SUBJECT, CT_UNION, CT_INTERSECTION, PFT_NONZERO, PFT_EVENODD,
scale_to_clipper, scale_from_clipper, PyPolyNode,
)
from masque.file import oasis, gdsii
from masque import Pattern
from masque.shapes import Polygon
from masque.utils import poly_contains_points
logger = logging.getLogger(__name__)
layer_t = tuple[int, int]
contour_t = list[tuple[int, int]]
net_name_t = str | object
CLIPPER_SCALE_FACTOR = 2**24
def poly_contains_points2(
vertices: ArrayLike,
points: ArrayLike,
include_boundary: bool = True,
) -> NDArray[numpy.int_]:
"""
Tests whether the provided points are inside the implicitly closed polygon
described by the provided list of vertices.
Args:
vertices: Nx2 Arraylike of form [[x0, y0], [x1, y1], ...], describing an implicitly-
closed polygon. Note that this should include any offsets.
points: Nx2 ArrayLike of form [[x0, y0], [x1, y1], ...] containing the points to test.
include_boundary: True if points on the boundary should be count as inside the shape.
Default True.
Returns:
ndarray of booleans, [point0_is_in_shape, point1_is_in_shape, ...]
"""
points = numpy.asarray(points)
vertices = numpy.asarray(vertices)
if points.size == 0:
return numpy.zeros(0)
min_bounds = numpy.min(vertices, axis=0)[None, :]
max_bounds = numpy.max(vertices, axis=0)[None, :]
trivially_outside = ((points < min_bounds).any(axis=1)
| (points > max_bounds).any(axis=1))
nontrivial = ~trivially_outside
if trivially_outside.all():
inside = numpy.zeros_like(trivially_outside, dtype=bool)
return inside
ntpts = points[None, nontrivial, :] # nontrivial points, along axis 1 of ndarray
verts = vertices[:, None, :] # vertices, along axis 0
xydiff = ntpts - verts # Expands into (n_vertices, n_ntpts, 2)
y0_le = xydiff[:, :, 1] >= 0 # y_point >= y_vertex (axes 0, 1 for all points & vertices)
y1_le = numpy.roll(y0_le, -1, axis=0) # same thing for next vertex
upward = y0_le & ~y1_le # edge passes point y coord going upwards
downward = ~y0_le & y1_le # edge passes point y coord going downwards
dv = numpy.roll(verts, -1, axis=0) - verts
is_left = (dv[..., 0] * xydiff[..., 1] # >0 if left of dv, <0 if right, 0 if on the line
- dv[..., 1] * xydiff[..., 0])
winding_number = ((upward & (is_left > 0)).sum(axis=0)
- (downward & (is_left < 0)).sum(axis=0))
nontrivial_inside = winding_number != 0 # filter nontrivial points based on winding number
if include_boundary:
nontrivial_inside[(is_left == 0).any(axis=0)] = True # check if point lies on any edge
inside = nontrivial.copy()
inside[nontrivial] = nontrivial_inside
return inside
def union_nonzero(shapes: Sequence[ArrayLike]) -> PyPolyNode | None:
if not shapes:
return None
pc = Pyclipper()
pc.AddPaths(shapes, PT_CLIP, closed=True)
result = pc.Execute2(CT_UNION, PFT_NONZERO, PFT_NONZERO)
return result
def union_evenodd(shapes: Sequence[ArrayLike]) -> list[contour_t]:
if not shapes:
return []
pc = Pyclipper()
pc.AddPaths(shapes, PT_CLIP, closed=True)
return pc.Execute(CT_UNION, PFT_EVENODD, PFT_EVENODD)
def intersection_evenodd(
subject_shapes: Sequence[ArrayLike],
clip_shapes: Sequence[ArrayLike],
clip_closed: bool = True,
) -> list[contour_t]:
if not subject_shapes or not clip_shapes:
return []
pc = Pyclipper()
pc.AddPaths(subject_shapes, PT_SUBJECT, closed=True)
pc.AddPaths(clip_shapes, PT_CLIP, closed=clip_closed)
return pc.Execute(CT_INTERSECTION, PFT_EVENODD, PFT_EVENODD)
class NetsInfo:
nets: defaultdict[str, defaultdict[layer_t, list]]
net_aliases: defaultdict[str, list]
def __init__(self) -> None:
self.nets = defaultdict(lambda: defaultdict(list))
self.net_aliases = defaultdict(list)
def resolve_name(self, net_name: net_name_t) -> net_name_t:
while net_name in self.net_aliases:
net_name = self.net_aliases[net_name]
return net_name
def merge(self, net_a: net_name_t, net_b: net_name_t) -> None:
net_a = self.resolve_name(net_a)
net_b = self.resolve_name(net_b)
# Always keep named nets if the other is anonymous
if not isinstance(net_a, str) and isinstance(net_b, str):
keep_net, old_net = net_b, net_a
else:
keep_net, old_net = net_a, net_b
#logger.info(f'merging {old_net} into {keep_net}')
self.net_aliases[old_net] = keep_net
if old_net in self.nets:
for layer in self.nets[old_net]:
self.nets[keep_net][layer] += self.nets[old_net][layer]
del self.nets[old_net]
def get(self, net: net_name_t, layer: layer_t) -> list[contour_t]:
return self.nets[self.resolve_name(net)][layer]
def get_shorted_nets(self) -> list[set[str]]:
shorts = defaultdict(list)
for kk in self.net_aliases:
if isinstance(kk, str):
shorts[self.resolve_name(kk)].append(kk)
shorted_sets = [set([kk] + others)
for kk, others in shorts.items()]
return shorted_sets
def load_polys(layers: Sequence[tuple[int, int]]) -> dict[layer_t, list[NDArray[numpy.float64]]]:
polys = defaultdict(list)
for ss in topcell.shapes:
if ss.layer not in layers:
continue
if ss.repetition is None:
displacements = [(0, 0)]
else:
displacements = ss.repetition.displacements
for displacement in displacements:
polys[ss.layer].append(
ss.vertices + ss.offset + displacement
)
return dict(polys)
def union_polys(polys: list[ArrayLike]) -> list[PyPolyNode]:
scaled_polys = scale_to_clipper(polys, CLIPPER_SCALE_FACTOR)
for poly in scaled_polys:
if (numpy.abs(poly) % 1).any():
logger.warning('Warning: union_polys got non-integer coordinates; all values will be truncated.')
break
poly_tree = union_nonzero(scaled_polys)
# Partially flatten the tree, reclassifying all the "outer" (non-hole) nodes as new root nodes
unvisited_nodes = [poly_tree]
outer_nodes = []
while unvisited_nodes:
node = unvisited_nodes.pop() # node will be the tree parent node (a container), or a hole
for poly in node.Childs:
outer_nodes.append(poly)
for hole in poly.Childs:
unvisited_nodes.append(hole)
return outer_nodes
cells, props = oasis.readfile('connectivity.oas')
#cells, props = gdsii.readfile('connectivity.gds')
topcell = cells['top']
layer_info = {
((1, 0), (1, 2), (2, 0)), #M1 to M2
((1, 0), (1, 3), (3, 0)), #M1 to M3
((2, 0), (2, 3), (3, 0)), #M2 to M3
}
metal_layers = set()
via_layers = set()
for top, via, bot in layer_info:
metal_layers.add(top)
metal_layers.add(bot)
via_layers.add(via)
topcell = topcell.subset(
shapes_func=lambda ss: ss.layer in metal_layers | via_layers,
labels_func=lambda ll: ll.layer in metal_layers,
subpatterns_func=lambda ss: True,
)
topcell = topcell.flatten()
base_metal_polys = load_polys(metal_layers)
metal_polys = {layer: union_polys(base_metal_polys[layer])
for layer in metal_layers}
base_via_polys = load_polys(via_layers)
via_polys = {layer: union_polys(base_via_polys[layer])
for layer in via_layers}
## write out polys to gds
#pat = Pattern('metal_polys')
#for layer in metal_polys:
# for poly in metal_polys[layer]:
# pat.shapes.append(Polygon(layer=layer, vertices=scale_from_clipper(poly.Contour, CLIPPER_SCALE_FACTOR)))
# for hole in poly.Childs:
# pat.shapes.append(Polygon(layer=(layer[0], layer[1] + 10), vertices=scale_from_clipper(hole.Contour, CLIPPER_SCALE_FACTOR)))
#for layer in via_polys:
# for poly in via_polys[layer]:
# pat.shapes.append(Polygon(layer=layer, vertices=scale_from_clipper(poly.Contour, CLIPPER_SCALE_FACTOR)))
# for hole in poly.Childs:
# pat.shapes.append(Polygon(layer=(layer[0], layer[1] + 10), vertices=scale_from_clipper(hole.Contour, CLIPPER_SCALE_FACTOR)))
#gdsii.writefile(pat, '_polys.gds', 1e-9, 1e-6)
net_info = NetsInfo()
def label_nets(
net_info: NetsInfo,
polys: Sequence[PyPolyNode],
point_xys: ArrayLike,
point_names: Sequence[str],
):
for poly in polys:
poly_contour = scale_from_clipper(poly.Contour, CLIPPER_SCALE_FACTOR)
inside = poly_contains_points2(poly_contour, point_xys)
for hole in poly.Childs:
hole_contour = scale_from_clipper(hole.Contour, CLIPPER_SCALE_FACTOR)
inside &= ~poly_contains_points2(hole_contour, point_xys)
inside_nets = sorted([net_name for net_name, ii in zip(point_names, inside) if ii])
if not inside.any():
# No labels in this net, so it's anonymous
name = object()
net_info.nets[name][layer].append(poly)
continue
net_info.get(inside_nets[0], layer).append(poly)
if inside.sum() == 1:
# No short on this layer, continue
continue
logger.warning(f'Nets {inside_nets} are shorted on layer {layer} in poly:\n {pformat(poly)}')
first_net, *defunct_nets = inside_nets
for defunct_net in defunct_nets:
net_info.merge(first_net, defunct_net)
contours = []
def tree2oriented(polys: Sequence[PyPolyNode]) -> list[ArrayLike]:
contours = []
for poly in polys:
contours.append(poly.Contour)
contours += [hole.Contour for hole in poly.Childs]
return union_evenodd(contours)
for layer in metal_layers:
labels = sorted([ll for ll in topcell.labels if ll.layer == layer], key=lambda ll: ll.string)
point_xys = [ll.offset for ll in labels]
point_names = [ll.string for ll in labels]
label_nets(net_info, metal_polys[layer], point_xys, point_names)
#
# Take EVENODD union within each net
# & stay in EVENODD-friendly representation
#
for net in net_info.nets.values():
for layer in net:
net[layer] = tree2oriented(net[layer])
for layer in via_polys:
via_polys[layer] = tree2oriented(via_polys[layer])
## write out nets to gds
#pat = Pattern('nets')
#for name, net in net_info.nets.items():
# sub = Pattern(str(name))
# for layer in net:
# print('aaaaaa', layer)
# for poly in net[layer]:
# sub.shapes.append(Polygon(layer=layer, vertices=scale_from_clipper(poly, CLIPPER_SCALE_FACTOR)))
# pat.addsp(sub)
#gdsii.writefile(pat, '_nets.gds', 1e-9, 1e-6)
#
# Merge nets based on via connectivity
#
merge_pairs = set()
for top_layer, via_layer, bot_layer in layer_info:
vias = via_polys[via_layer]
if not vias:
continue
#TODO deal with polygons that have holes (loops?)
for top_name in net_info.nets.keys():
top_polys = net_info.nets[top_name][top_layer]
if not top_polys:
continue
for bot_name in net_info.nets.keys():
if bot_name == top_name:
continue
name_pair = tuple(sorted((top_name, bot_name), key=lambda s: id(s)))
if name_pair in merge_pairs:
continue
bot_polys = net_info.nets[bot_name][bot_layer]
if not bot_polys:
continue
via_top = intersection_evenodd(top_polys, vias)
overlap = intersection_evenodd(via_top, bot_polys)
if not overlap:
continue
if isinstance(bot_name, str) and isinstance(top_name, str):
logger.warning(f'Nets {top_name} and {bot_name} are shorted with via layer {via_layer} at:\n {pformat(scale_from_clipper(overlap[0], CLIPPER_SCALE_FACTOR))}')
merge_pairs.add(name_pair)
for net_a, net_b in merge_pairs:
net_info.merge(net_a, net_b)
print('merged pairs')
print(pformat(merge_pairs))
print('\nFinal nets:')
print([kk for kk in net_info.nets if isinstance(kk, str)])
print('\nNet sets:')
for short in net_info.get_shorted_nets():
print('(' + ','.join(sorted(list(short))) + ')')

38
examples/euler_bend.py Normal file
View File

@ -0,0 +1,38 @@
import numpy
from numpy import pi
def centerline(switchover_angle: float):
theta_max = numpy.sqrt(2 * switchover_angle)
def gen_curve(theta_max: float):
xx = []
yy = []
for theta in numpy.linspace(0, theta_max, 100):
qq = numpy.linspace(0, theta, 1000)
xx.append(numpy.trapz( cos(qq * qq / 2), qq))
yy.append(numpy.trapz(-sin(qq * qq / 2), qq))
xy_part = numpy.stack((xx, yy), axis=1)
return xy_part
AA = 1
xy_part = AA * gen_curve(theta_max)
rmin = AA / theta_max
xy = [xy_part]
if switchover_angle < pi / 4:
half_angle = pi / 4 - switchover_angle
qq = numpy.linspace(half_angle * 2, 0, 10) + switchover_angle
xc = rmin * numpy.cos(qq)
yc = rmin * numpy.sin(qq) + xy_part[-1, 1]
xc += xy_part[-1, 0] - xc[0]
yc += xy_part[-1, 1] - yc[0]
xy.append(numpy.stack((xy, yc), axis=1))
endpoint_xy = xy[-1][-1, :]
second_curve = xy_part[:, ::-1] + endpoint_xy - xy_part[-1, ::-1]
# Remove 2x-duplicate points
xy = xy[(numpy.circshift(xy, 1, axis=0) != xy).any(axis=1)]
return xy

View File

@ -31,6 +31,7 @@ from pprint import pformat
import numpy
from numpy.typing import ArrayLike, NDArray
from numpy.testing import assert_equal
import pyarrow
from pyarrow.cffi import ffi
@ -44,7 +45,7 @@ from ..library import LazyLibrary, Library, ILibrary, ILibraryView
logger = logging.getLogger(__name__)
clib = ffi.dlopen('/home/jan/projects/klamath-rs/target/debug/libklamath_rs_ext.so')
clib = ffi.dlopen('/home/jan/projects/klamath-rs/target/release/libklamath_rs_ext.so')
ffi.cdef('void read_path(char* path, struct ArrowArray* array, struct ArrowSchema* schema);')
@ -127,10 +128,25 @@ def read_arrow(
"""
library_info = _read_header(libarr)
layer_names_np = libarr['layers'].values.to_numpy().view('i2').reshape((-1, 2))
layer_tups = [tuple(pair) for pair in layer_names_np]
bnd = libarr['cells'].values.field('boundaries')
layer_inds = bnd.values.field('layer').to_numpy()
boundary = dict(
offsets = bnd.offsets.to_numpy(),
xy_arr = bnd.values.field('xy').values.to_numpy().reshape((-1, 2)),
xy_off = bnd.values.field('xy').offsets.to_numpy() // 2,
layer_tups = layer_tups,
layer_inds = layer_inds,
prop_off = bnd.values.field('properties').offsets.to_numpy(),
prop_key = bnd.values.field('properties').values.field('key').to_numpy(),
prop_val = bnd.values.field('properties').values.field('value').to_pylist(),
)
mlib = Library()
for cell in libarr['cells']:
for cc, cell in enumerate(libarr['cells']):
name = libarr['cell_names'][cell['id'].as_py()].as_py()
pat = read_cell(cell, libarr['cell_names'], raw_mode=raw_mode)
pat = read_cell(cc, cell, libarr['cell_names'], raw_mode=raw_mode, boundary=boundary)
mlib[name] = pat
return mlib, library_info
@ -149,8 +165,10 @@ def _read_header(libarr: pyarrow.Array) -> dict[str, Any]:
def read_cell(
cc: int,
cellarr: pyarrow.Array,
cell_names: pyarrow.Array,
boundary: dict[str, NDArray],
raw_mode: bool = True,
) -> Pattern:
"""
@ -190,22 +208,32 @@ def read_cell(
ref = Ref(**args)
pat.refs[target].append(ref)
for bnd in cellarr['boundaries']:
layer = (bnd['layer'].as_py(), bnd['dtype'].as_py())
args = dict(
vertices = bnd['xy'].values.to_numpy().reshape((-1, 2))[:-1],
raw = raw_mode,
offset = numpy.zeros(2),
)
bnd_off = boundary['offsets']
bnd_xy_val = boundary['xy_arr']
bnd_xy_off = boundary['xy_off']
layer_tups = boundary['layer_tups']
layer_inds = boundary['layer_inds']
prop_off = boundary['prop_off']
prop_key = boundary['prop_key']
prop_val = boundary['prop_val']
slc = slice(bnd_off[cc], bnd_off[cc + 1] + 1)
bnd_offs = bnd_xy_off[slc]
prop_offs = prop_off[slc]
zeros = numpy.zeros((len(bnd_offs) - 1, 2))
for bb in range(len(bnd_offs) - 1):
layer = layer_tups[layer_inds[bb]]
vertices = bnd_xy_val[bnd_offs[bb]:bnd_offs[bb + 1] - 1] # -1 to drop closing point
if (props := bnd['properties']).is_valid:
args['annotations'] = _properties_to_annotations(props)
prop_ii, prop_ff = prop_offs[bb], prop_offs[bb + 1]
if prop_ii < prop_ff:
ann = {prop_key[off]: prop_val[off] for off in range(prop_ii, prop_ff)}
args = dict(annotations = ann)
poly = Polygon(**args)
poly = Polygon(vertices=vertices, offset=zeros[bb], raw=raw_mode)
pat.shapes[layer].append(poly)
for gpath in cellarr['paths']:
layer = (gpath['layer'].as_py(), gpath['dtype'].as_py())
layer = (gpath['layer'].as_py(),)
args = dict(
vertices = gpath['xy'].values.to_numpy().reshape((-1, 2)),
offset = numpy.zeros(2),
@ -236,7 +264,7 @@ def read_cell(
pat.shapes[layer].append(mpath)
for gtext in cellarr['texts']:
layer = (gtext['layer'].as_py(), gtext['dtype'].as_py())
layer = (gtext['layer'].as_py(),)
args = dict(
offset = (gtext['x'].as_py(), gtext['y'].as_py()),
string = gtext['string'].as_py(),

3
masque/test/__init__.py Normal file
View File

@ -0,0 +1,3 @@
"""
Tests (run with `python3 -m pytest -rxPXs | tee results.txt`)
"""

31
masque/test/conftest.py Normal file
View File

@ -0,0 +1,31 @@
"""
Test fixtures
"""
# ruff: noqa: ARG001
from typing import Any
import numpy
from numpy.typing import NDArray
import pytest # type: ignore
FixtureRequest = Any
PRNG = numpy.random.RandomState(12345)
@pytest.fixture(scope='module',
params=[(5, 5, 1),
(5, 1, 5),
(5, 5, 5),
# (7, 7, 7),
])
def shape(request: FixtureRequest) -> tuple[int, ...]:
return (3, *request.param)
@pytest.fixture(scope='module', params=[1.0, 1.5])
def epsilon_bg(request: FixtureRequest) -> float:
return request.param

35
masque/test/test_fdfd.py Normal file
View File

@ -0,0 +1,35 @@
# ruff: noqa: ARG001
import dataclasses
import pytest # type: ignore
import numpy
from numpy import pi
from numpy.typing import NDArray
#from numpy.testing import assert_allclose, assert_array_equal
from .. import Pattern, Arc
def test_Arc_arclen() -> None:
max_arclen = 1000
wedge = Arc(radii=( 50, 50), angles=(-pi/4, pi/4), width=100)
arc = Arc(radii=(100, 100), angles=(-pi/4, pi/4), width=1)
verts_wedge = wedge.to_polygons(max_arclen=max_arclen)[0].vertices
verts_arc = arc.to_polygons(max_arclen=max_arclen)[0].vertices
dxy_wedge = numpy.roll(verts_wedge, 1, axis=0) - verts_wedge
dxy_arc = numpy.roll(verts_arc, 1, axis=0) - verts_arc
dl_wedge = numpy.sqrt((dxy_wedge * dxy_wedge).sum(axis=1))
dl_arc = numpy.sqrt((dxy_arc * dxy_arc).sum(axis=1))
assert dl_wedge.max() < max_arclen
assert dl_arc.max() < max_arclen
print(verts_wedge.shape[0])
print(verts_arc.shape[0])
print(dl_wedge, dl_arc)
Pattern(shapes={(0, 0): [wedge, arc]}).visualize()
assert False

View File

@ -46,6 +46,21 @@ def bezier(
return qq
def bezier2(
nodes: ArrayLike,
tt: ArrayLike,
) -> NDArray[numpy.float64]:
nodes = numpy.asarray(nodes)
tt = numpy.asarray(tt)[:, None, None]
nn = nodes.shape[0]
qq = nodes[None, :, :] * numpy.ones(tt.size)[:, None, None]
for kk in range(1, nn):
gg = nn - kk
qq[:, :gg, :] = (1 - tt) * qq[:, :gg, :] + tt * qq[:, 1:gg + 1, :]
#for ii in range(nn - kk):
# qq[:, ii] = (1 - tt[:, None]) * qq[:, ii] + tt[:, None] * qq[:, ii + 1]
return qq[:, 0, :]
def euler_bend(
switchover_angle: float,

5
perftest.py Normal file
View File

@ -0,0 +1,5 @@
import time
from masque.file.gdsii_arrow import readfile
#time.sleep(5)
lib, props = readfile('/home/jan/Downloads/sg13g2_io.gds')

1
test.ssc Normal file

File diff suppressed because one or more lines are too long

1
test3.ssc Normal file

File diff suppressed because one or more lines are too long

1
test_slow.ssc Normal file

File diff suppressed because one or more lines are too long