prefab 1.2.0__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prefab/__init__.py +1 -1
- prefab/__main__.py +29 -24
- prefab/compare.py +49 -61
- prefab/device.py +163 -418
- prefab/geometry.py +102 -136
- prefab/models.py +19 -48
- prefab/predict.py +281 -249
- prefab/py.typed +0 -0
- prefab/read.py +57 -303
- prefab/shapes.py +357 -187
- {prefab-1.2.0.dist-info → prefab-1.4.0.dist-info}/METADATA +21 -35
- prefab-1.4.0.dist-info/RECORD +15 -0
- prefab-1.2.0.dist-info/RECORD +0 -14
- {prefab-1.2.0.dist-info → prefab-1.4.0.dist-info}/WHEEL +0 -0
- {prefab-1.2.0.dist-info → prefab-1.4.0.dist-info}/entry_points.txt +0 -0
- {prefab-1.2.0.dist-info → prefab-1.4.0.dist-info}/licenses/LICENSE +0 -0
prefab/__init__.py
CHANGED
prefab/__main__.py
CHANGED
|
@@ -17,9 +17,9 @@ def store_jwt(jwt, refresh_token):
|
|
|
17
17
|
toml.dump({"access_token": jwt, "refresh_token": refresh_token}, toml_file)
|
|
18
18
|
print(
|
|
19
19
|
f"Token successfully stored in {prefab_file_path}.\n\n"
|
|
20
|
-
"🎉 Welcome to PreFab
|
|
20
|
+
"🎉 Welcome to PreFab.\n"
|
|
21
21
|
"See our examples at https://docs.prefabphotonics.com/examples to start.\n"
|
|
22
|
-
"Reach out to us at hi@prefabphotonics.com
|
|
22
|
+
"Reach out to us at hi@prefabphotonics.com for support."
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
|
|
@@ -35,6 +35,10 @@ class GracefulHTTPServer(HTTPServer):
|
|
|
35
35
|
class CallbackHandler(BaseHTTPRequestHandler):
|
|
36
36
|
"""A request handler for the HTTP server that handles the JWT-auth callback."""
|
|
37
37
|
|
|
38
|
+
def log_message(self, format, *args):
|
|
39
|
+
"""Suppress HTTP request logging."""
|
|
40
|
+
pass
|
|
41
|
+
|
|
38
42
|
def do_GET(self):
|
|
39
43
|
if self.path.startswith("/callback"):
|
|
40
44
|
query_params = self.path.split("?")[1]
|
|
@@ -47,25 +51,12 @@ class CallbackHandler(BaseHTTPRequestHandler):
|
|
|
47
51
|
if jwt_token and refresh_token:
|
|
48
52
|
print("Token verified.")
|
|
49
53
|
store_jwt(jwt_token, refresh_token)
|
|
50
|
-
self.
|
|
51
|
-
self.send_header(
|
|
54
|
+
self.send_response(302)
|
|
55
|
+
self.send_header(
|
|
56
|
+
"Location",
|
|
57
|
+
"https://www.prefabphotonics.com/auth/token-flow/success",
|
|
58
|
+
)
|
|
52
59
|
self.end_headers()
|
|
53
|
-
redirect_html = b"""
|
|
54
|
-
<html>
|
|
55
|
-
<head>
|
|
56
|
-
<meta http-equiv="refresh" content="0;url=https://www.prefabphotonics.com/token-success">
|
|
57
|
-
<style>
|
|
58
|
-
body {
|
|
59
|
-
background-color: #0A0A0A;
|
|
60
|
-
color: #ffffff;
|
|
61
|
-
}
|
|
62
|
-
</style>
|
|
63
|
-
</head>
|
|
64
|
-
<body>
|
|
65
|
-
</body>
|
|
66
|
-
</html>
|
|
67
|
-
"""
|
|
68
|
-
self.wfile.write(redirect_html)
|
|
69
60
|
threading.Thread(target=self.server.shutdown).start()
|
|
70
61
|
else:
|
|
71
62
|
self.send_error(400, "Bad Request: Missing tokens in callback URL.")
|
|
@@ -78,15 +69,29 @@ def main():
|
|
|
78
69
|
parser.add_argument(
|
|
79
70
|
"--port", help="Port number for the HTTP server", type=int, default=8000
|
|
80
71
|
)
|
|
72
|
+
parser.add_argument(
|
|
73
|
+
"--timeout", help="Timeout in seconds for authentication", type=int, default=300
|
|
74
|
+
)
|
|
81
75
|
args = parser.parse_args()
|
|
82
76
|
|
|
83
77
|
if args.command == "setup":
|
|
84
|
-
webbrowser.open("https://www.prefabphotonics.com/token-flow")
|
|
78
|
+
webbrowser.open("https://www.prefabphotonics.com/auth/token-flow")
|
|
85
79
|
httpd = GracefulHTTPServer(("localhost", args.port), CallbackHandler)
|
|
86
80
|
print("Started token authentication flow on the web browser...")
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
|
|
82
|
+
def timeout_handler():
|
|
83
|
+
print("\nAuthentication timed out. Please run 'prefab setup' again.")
|
|
84
|
+
httpd.shutdown()
|
|
85
|
+
|
|
86
|
+
timer = threading.Timer(args.timeout, timeout_handler)
|
|
87
|
+
timer.start()
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
with suppress(KeyboardInterrupt):
|
|
91
|
+
httpd.serve_forever()
|
|
92
|
+
finally:
|
|
93
|
+
timer.cancel()
|
|
94
|
+
httpd.server_close()
|
|
90
95
|
else:
|
|
91
96
|
print(f"Command {args.command} not recognized.")
|
|
92
97
|
|
prefab/compare.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Similarity metrics for comparing device structures.
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
This module provides various metrics for quantifying the similarity between two Device
|
|
5
|
+
objects, including general-purpose metrics (MSE) and binary-specific metrics (IoU,
|
|
6
|
+
Hamming distance, Dice coefficient).
|
|
7
|
+
"""
|
|
4
8
|
|
|
5
9
|
import numpy as np
|
|
6
10
|
|
|
@@ -9,8 +13,10 @@ from .device import Device
|
|
|
9
13
|
|
|
10
14
|
def mean_squared_error(device_a: Device, device_b: Device) -> float:
|
|
11
15
|
"""
|
|
12
|
-
Calculate the mean squared error (MSE) between two devices.
|
|
13
|
-
|
|
16
|
+
Calculate the mean squared error (MSE) between two devices.
|
|
17
|
+
|
|
18
|
+
MSE quantifies the average squared difference between corresponding pixels. Lower
|
|
19
|
+
values indicate greater similarity, with 0 representing identical devices.
|
|
14
20
|
|
|
15
21
|
Parameters
|
|
16
22
|
----------
|
|
@@ -22,105 +28,87 @@ def mean_squared_error(device_a: Device, device_b: Device) -> float:
|
|
|
22
28
|
Returns
|
|
23
29
|
-------
|
|
24
30
|
float
|
|
25
|
-
The mean squared error
|
|
31
|
+
The mean squared error. Range: [0, ∞), where 0 indicates identical devices.
|
|
26
32
|
"""
|
|
27
33
|
return float(np.mean((device_a.device_array - device_b.device_array) ** 2))
|
|
28
34
|
|
|
29
35
|
|
|
30
36
|
def intersection_over_union(device_a: Device, device_b: Device) -> float:
|
|
31
37
|
"""
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
Calculate the Intersection over Union (IoU) between two binary devices.
|
|
39
|
+
|
|
40
|
+
Also known as the Jaccard index. IoU measures the overlap between two binary masks
|
|
41
|
+
as the ratio of their intersection to their union. Higher values indicate greater
|
|
42
|
+
similarity.
|
|
34
43
|
|
|
35
44
|
Parameters
|
|
36
45
|
----------
|
|
37
46
|
device_a : Device
|
|
38
|
-
The first device (binarized).
|
|
47
|
+
The first device (should be binarized for meaningful results).
|
|
39
48
|
device_b : Device
|
|
40
|
-
The second device (binarized).
|
|
49
|
+
The second device (should be binarized for meaningful results).
|
|
41
50
|
|
|
42
51
|
Returns
|
|
43
52
|
-------
|
|
44
53
|
float
|
|
45
|
-
The
|
|
46
|
-
|
|
47
|
-
Warnings
|
|
48
|
-
--------
|
|
49
|
-
UserWarning
|
|
50
|
-
If one or both devices are not binarized.
|
|
54
|
+
The IoU score. Range: [0, 1], where 1 indicates perfect overlap.
|
|
51
55
|
"""
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
) / np.sum(np.logical_or(device_a.device_array, device_b.device_array))
|
|
56
|
+
intersection_sum = float(
|
|
57
|
+
np.sum(np.logical_and(device_a.device_array, device_b.device_array))
|
|
58
|
+
)
|
|
59
|
+
union_sum = float(
|
|
60
|
+
np.sum(np.logical_or(device_a.device_array, device_b.device_array))
|
|
61
|
+
)
|
|
62
|
+
return intersection_sum / union_sum
|
|
60
63
|
|
|
61
64
|
|
|
62
65
|
def hamming_distance(device_a: Device, device_b: Device) -> int:
|
|
63
66
|
"""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
Calculate the Hamming distance between two binary devices.
|
|
68
|
+
|
|
69
|
+
The Hamming distance is the count of positions where corresponding pixels differ.
|
|
70
|
+
Lower values indicate greater similarity, with 0 representing identical devices.
|
|
67
71
|
|
|
68
72
|
Parameters
|
|
69
73
|
----------
|
|
70
74
|
device_a : Device
|
|
71
|
-
The first device (binarized).
|
|
75
|
+
The first device (should be binarized for meaningful results).
|
|
72
76
|
device_b : Device
|
|
73
|
-
The second device (binarized).
|
|
77
|
+
The second device (should be binarized for meaningful results).
|
|
74
78
|
|
|
75
79
|
Returns
|
|
76
80
|
-------
|
|
77
81
|
int
|
|
78
|
-
The
|
|
79
|
-
|
|
80
|
-
Warnings
|
|
81
|
-
--------
|
|
82
|
-
UserWarning
|
|
83
|
-
If one or both devices are not binarized.
|
|
82
|
+
The number of differing pixels. Range: [0, total_pixels], where 0 indicates
|
|
83
|
+
identical devices.
|
|
84
84
|
"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"One or both devices are not binarized.", UserWarning, stacklevel=2
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
return int(np.sum(device_a.device_array != device_b.device_array))
|
|
85
|
+
diff_array = device_a.device_array != device_b.device_array
|
|
86
|
+
return int(np.sum(diff_array))
|
|
91
87
|
|
|
92
88
|
|
|
93
89
|
def dice_coefficient(device_a: Device, device_b: Device) -> float:
|
|
94
90
|
"""
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
Calculate the Dice coefficient between two binary devices.
|
|
92
|
+
|
|
93
|
+
Also known as the Sørensen-Dice coefficient or F1 score. The Dice coefficient
|
|
94
|
+
measures similarity as twice the intersection divided by the sum of the sizes of
|
|
95
|
+
both sets. Higher values indicate greater similarity.
|
|
98
96
|
|
|
99
97
|
Parameters
|
|
100
98
|
----------
|
|
101
99
|
device_a : Device
|
|
102
|
-
The first device (binarized).
|
|
100
|
+
The first device (should be binarized for meaningful results).
|
|
103
101
|
device_b : Device
|
|
104
|
-
The second device (binarized).
|
|
102
|
+
The second device (should be binarized for meaningful results).
|
|
105
103
|
|
|
106
104
|
Returns
|
|
107
105
|
-------
|
|
108
106
|
float
|
|
109
|
-
The Dice coefficient
|
|
110
|
-
|
|
111
|
-
Warnings
|
|
112
|
-
--------
|
|
113
|
-
UserWarning
|
|
114
|
-
If one or both devices are not binarized.
|
|
107
|
+
The Dice coefficient. Range: [0, 1], where 1 indicates perfect overlap.
|
|
115
108
|
"""
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
"One or both devices are not binarized.", UserWarning, stacklevel=2
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
intersection = 2.0 * np.sum(
|
|
122
|
-
np.logical_and(device_a.device_array, device_b.device_array)
|
|
109
|
+
intersection_sum = float(
|
|
110
|
+
np.sum(np.logical_and(device_a.device_array, device_b.device_array))
|
|
123
111
|
)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return
|
|
112
|
+
size_a_sum = float(np.sum(device_a.device_array))
|
|
113
|
+
size_b_sum = float(np.sum(device_b.device_array))
|
|
114
|
+
return (2.0 * intersection_sum) / (size_a_sum + size_b_sum)
|