prefab 0.5.2__py3-none-any.whl → 1.1.7__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 CHANGED
@@ -1,51 +1,24 @@
1
1
  """
2
- The PreFab module provides functionality for predicting and processing photonics
3
- device layouts, and utilities for interacting with GDSII files.
2
+ The prefab module predicts and corrects nanofabrication variations in photonic devices.
4
3
 
5
4
  Usage:
6
5
  import prefab as pf
7
6
  """
8
7
 
9
- # I/O utilities
10
- # Function to load/save device images and gds files
11
- from prefab.io import (
12
- device_to_cell, # Convert a device layout to a gdstk cell
13
- load_device_gds, # Load device from a GDSII file
14
- load_device_img, # Load device from an image file
15
- )
8
+ __version__ = "1.1.7"
16
9
 
17
- # Prediction and Correction
18
- # Functions to predict and correct device layouts
19
- from prefab.predictor import (
20
- correct, # Correct a device layout
21
- predict, # Predict a device layout
22
- )
10
+ from . import compare, geometry, predict, read, shapes
11
+ from .device import BufferSpec, Device
12
+ from .models import models
23
13
 
24
- # Import image processing utilities
25
- # Functions to modify and manipulate device images
26
- from prefab.processor import (
27
- binarize, # Soft binarization of grayscale images
28
- binarize_hard, # Hard binarization of grayscale images
29
- calculate_prediction_uncertainty, # Computes prediction uncertainty for device images
30
- generate_device_contour, # Generates contour of device images
31
- mse, # Computes mean squared error between two images
32
- remove_padding, # Trims excess padding from device images
33
- ternarize, # Ternarization of grayscale images
34
- zero_boundary, # Applies zero boundary to device images
35
- )
36
-
37
- __all__ = (
38
- "device_to_cell",
39
- "load_device_gds",
40
- "load_device_img",
41
- "correct",
14
+ __all__ = [
15
+ "Device",
16
+ "BufferSpec",
17
+ "geometry",
42
18
  "predict",
43
- "binarize",
44
- "binarize_hard",
45
- "calculate_prediction_uncertainty",
46
- "generate_device_contour",
47
- "mse",
48
- "remove_padding",
49
- "ternarize",
50
- "zero_boundary",
51
- )
19
+ "read",
20
+ "shapes",
21
+ "compare",
22
+ "models",
23
+ "__version__",
24
+ ]
prefab/__main__.py CHANGED
@@ -1,21 +1,26 @@
1
- """Main entry point for the Prefab CLI."""
1
+ """Provides the main entry point for the Prefab authentication CLI."""
2
+
2
3
  import argparse
3
4
  import os
4
5
  import threading
5
6
  import webbrowser
7
+ from contextlib import suppress
6
8
  from http.server import BaseHTTPRequestHandler, HTTPServer
7
9
 
8
10
  import toml
9
11
 
10
12
 
11
- def store_jwt_securely(jwt, refresh_token):
12
- """
13
- Store the JWT and refresh token securely in a TOML file.
14
- """
13
+ def store_jwt(jwt, refresh_token):
14
+ """Store the JWT and refresh token in a TOML file."""
15
15
  prefab_file_path = os.path.expanduser("~/.prefab.toml")
16
16
  with open(prefab_file_path, "w", encoding="utf-8") as toml_file:
17
17
  toml.dump({"access_token": jwt, "refresh_token": refresh_token}, toml_file)
18
- print(f"Token successfully stored in {prefab_file_path}")
18
+ print(
19
+ f"Token successfully stored in {prefab_file_path}.\n\n"
20
+ "🎉 Welcome to PreFab!.\n"
21
+ "See our examples at https://docs.prefabphotonics.com/examples to start.\n"
22
+ "Reach out to us at hi@prefabphotonics.com if you have any questions."
23
+ )
19
24
 
20
25
 
21
26
  class GracefulHTTPServer(HTTPServer):
@@ -28,9 +33,7 @@ class GracefulHTTPServer(HTTPServer):
28
33
 
29
34
 
30
35
  class CallbackHandler(BaseHTTPRequestHandler):
31
- """
32
- A request handler for the HTTP server that handles the OAuth callback.
33
- """
36
+ """A request handler for the HTTP server that handles the JWT-auth callback."""
34
37
 
35
38
  def do_GET(self):
36
39
  if self.path.startswith("/callback"):
@@ -42,8 +45,8 @@ class CallbackHandler(BaseHTTPRequestHandler):
42
45
  jwt_token = params.get("token")
43
46
  refresh_token = params.get("refresh_token")
44
47
  if jwt_token and refresh_token:
45
- print("Token verified!")
46
- store_jwt_securely(jwt_token, refresh_token)
48
+ print("Token verified.")
49
+ store_jwt(jwt_token, refresh_token)
47
50
  self.send_response_only(200, "OK")
48
51
  self.send_header("Content-type", "text/html")
49
52
  self.end_headers()
@@ -56,22 +59,20 @@ class CallbackHandler(BaseHTTPRequestHandler):
56
59
 
57
60
 
58
61
  def main():
59
- parser = argparse.ArgumentParser(description="Prefab CLI")
62
+ """Main function for the Prefab authentication CLI."""
63
+ parser = argparse.ArgumentParser(description="PreFab Auth CLI")
60
64
  parser.add_argument("command", help="The command to run", choices=["setup"])
61
65
  parser.add_argument(
62
66
  "--port", help="Port number for the HTTP server", type=int, default=8000
63
67
  )
64
-
65
68
  args = parser.parse_args()
66
69
 
67
70
  if args.command == "setup":
68
71
  webbrowser.open("https://www.prefabphotonics.com/token-flow")
69
72
  httpd = GracefulHTTPServer(("localhost", args.port), CallbackHandler)
70
73
  print("Started token authentication flow on the web browser...")
71
- try:
74
+ with suppress(KeyboardInterrupt):
72
75
  httpd.serve_forever()
73
- except KeyboardInterrupt:
74
- pass
75
76
  httpd.server_close()
76
77
  else:
77
78
  print(f"Command {args.command} not recognized.")
prefab/compare.py ADDED
@@ -0,0 +1,126 @@
1
+ """Functions to measure the structural similarity between devices."""
2
+
3
+ import warnings
4
+
5
+ import numpy as np
6
+
7
+ from .device import Device
8
+
9
+
10
+ def mean_squared_error(device_a: Device, device_b: Device) -> float:
11
+ """
12
+ Calculate the mean squared error (MSE) between two devices. A lower value indicates
13
+ more similarity.
14
+
15
+ Parameters
16
+ ----------
17
+ device_a : Device
18
+ The first device.
19
+ device_b : Device
20
+ The second device.
21
+
22
+ Returns
23
+ -------
24
+ float
25
+ The mean squared error between two devices.
26
+ """
27
+ return float(np.mean((device_a.device_array - device_b.device_array) ** 2))
28
+
29
+
30
+ def intersection_over_union(device_a: Device, device_b: Device) -> float:
31
+ """
32
+ Calculates the Intersection over Union (IoU) between two binary devices. A value
33
+ closer to 1 indicates more similarity (more overlap).
34
+
35
+ Parameters
36
+ ----------
37
+ device_a : Device
38
+ The first device (binarized).
39
+ device_b : Device
40
+ The second device (binarized).
41
+
42
+ Returns
43
+ -------
44
+ float
45
+ The Intersection over Union between two devices.
46
+
47
+ Warnings
48
+ --------
49
+ UserWarning
50
+ If one or both devices are not binarized.
51
+ """
52
+ if not device_a.is_binary or not device_b.is_binary:
53
+ warnings.warn(
54
+ "One or both devices are not binarized.", UserWarning, stacklevel=2
55
+ )
56
+
57
+ return np.sum(
58
+ np.logical_and(device_a.device_array, device_b.device_array)
59
+ ) / np.sum(np.logical_or(device_a.device_array, device_b.device_array))
60
+
61
+
62
+ def hamming_distance(device_a: Device, device_b: Device) -> int:
63
+ """
64
+ Calculates the Hamming distance between two binary devices. A lower value indicates
65
+ more similarity. The Hamming distance is calculated as the number of positions at
66
+ which the corresponding pixels are different.
67
+
68
+ Parameters
69
+ ----------
70
+ device_a : Device
71
+ The first device (binarized).
72
+ device_b : Device
73
+ The second device (binarized).
74
+
75
+ Returns
76
+ -------
77
+ int
78
+ The Hamming distance between two devices.
79
+
80
+ Warnings
81
+ --------
82
+ UserWarning
83
+ If one or both devices are not binarized.
84
+ """
85
+ if not device_a.is_binary or not device_b.is_binary:
86
+ warnings.warn(
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))
91
+
92
+
93
+ def dice_coefficient(device_a: Device, device_b: Device) -> float:
94
+ """
95
+ Calculates the Dice coefficient between two binary devices. A value closer to 1
96
+ indicates more similarity. The Dice coefficient is calculated as twice the number of
97
+ pixels in common divided by the total number of pixels in the two devices.
98
+
99
+ Parameters
100
+ ----------
101
+ device_a : Device
102
+ The first device (binarized).
103
+ device_b : Device
104
+ The second device (binarized).
105
+
106
+ Returns
107
+ -------
108
+ float
109
+ The Dice coefficient between two devices.
110
+
111
+ Warnings
112
+ --------
113
+ UserWarning
114
+ If one or both devices are not binarized.
115
+ """
116
+ if not device_a.is_binary or not device_b.is_binary:
117
+ warnings.warn(
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)
123
+ )
124
+ size_a = np.sum(device_a.device_array)
125
+ size_b = np.sum(device_b.device_array)
126
+ return intersection / (size_a + size_b)