gplugins 0.10.2__tar.gz → 0.12.0__tar.gz

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.
Files changed (235) hide show
  1. {gplugins-0.10.2 → gplugins-0.12.0}/PKG-INFO +9 -7
  2. {gplugins-0.10.2 → gplugins-0.12.0}/README.md +1 -1
  3. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/__init__.py +1 -1
  4. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/add_simulation_markers.py +1 -0
  5. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/async_helpers.py +5 -3
  6. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/disable_print.py +1 -0
  7. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/get_component_with_net_layers.py +3 -3
  8. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/optical_constants.py +1 -0
  9. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/parse_layer_stack.py +1 -0
  10. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/devsim/get_simulation_xsection.py +2 -3
  11. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/femwell/solve_thermal.py +6 -6
  12. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/get_simulation.py +1 -0
  13. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/get_simulation_grating_farfield.py +1 -0
  14. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/write_sparameters_grating.py +1 -0
  15. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/parse_component.py +20 -19
  16. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/parse_gds.py +2 -1
  17. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/dataprep/regions.py +3 -6
  18. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/samples/drc_errors.py +24 -19
  19. gplugins-0.12.0/gplugins/klayout/netlist_graph.py +137 -0
  20. gplugins-0.12.0/gplugins/klayout/netlist_spice_reader.py +117 -0
  21. gplugins-0.12.0/gplugins/klayout/plot_nets.py +100 -0
  22. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_netlist_spice_reader.py +11 -6
  23. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_plot_nets.py +5 -6
  24. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/write_sparameters_lumerical.py +1 -0
  25. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/write_sparameters_lumerical_components.py +1 -0
  26. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/find_modes.py +1 -0
  27. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/find_modes_cross_section.py +1 -0
  28. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/neff_convergence_test.py +1 -0
  29. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/path_length_analysis/path_length_analysis.py +2 -2
  30. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/implant_tables.py +1 -0
  31. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/pysrim.py +1 -3
  32. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/silicon.py +1 -0
  33. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/models.py +173 -13
  34. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/read.py +1 -0
  35. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/tests/test_mzi.py +1 -0
  36. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/tests/test_mzi_lattice.py +1 -0
  37. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/component.py +8 -8
  38. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/get_simulation_grating_coupler.py +1 -0
  39. {gplugins-0.10.2 → gplugins-0.12.0}/pyproject.toml +9 -7
  40. gplugins-0.10.2/gplugins/klayout/netlist_spice_reader.py +0 -16
  41. gplugins-0.10.2/gplugins/klayout/plot_nets.py +0 -188
  42. {gplugins-0.10.2 → gplugins-0.12.0}/LICENSE +0 -0
  43. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/__init__.py +0 -0
  44. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/base_models/__init__.py +0 -0
  45. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/base_models/component.py +0 -0
  46. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/base_models/simulation.py +0 -0
  47. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/config.py +0 -0
  48. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/types.py +0 -0
  49. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/__init__.py +0 -0
  50. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/cache.py +0 -0
  51. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/convert_sparameters.py +0 -0
  52. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/get_capacitance.py +0 -0
  53. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/get_component_with_local_layers.py +0 -0
  54. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/get_effective_indices.py +0 -0
  55. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/get_scattering.py +0 -0
  56. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/get_sparameters_path.py +0 -0
  57. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/plot.py +0 -0
  58. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/plot_csv.py +0 -0
  59. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/port_symmetries.py +0 -0
  60. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/common/utils/tests/test_get_component_with_new_port_layers.py +0 -0
  61. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/dagster/Makefile +0 -0
  62. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/dagster/__init__.py +0 -0
  63. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/dagster/workflow.py +0 -0
  64. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/devsim/__init__.py +0 -0
  65. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/devsim/doping.py +0 -0
  66. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/devsim/get_simulation.py +0 -0
  67. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/devsim/get_solver.py +0 -0
  68. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/devsim/test_devsim.py +0 -0
  69. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/elmer/__init__.py +0 -0
  70. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/elmer/electrostatic.sif.j2 +0 -0
  71. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/elmer/get_capacitance.py +0 -0
  72. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/elmer/tests/test_elmer.py +0 -0
  73. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/fdtdz/__init__.py +0 -0
  74. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/fdtdz/get_epsilon_fdtdz.py +0 -0
  75. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/fdtdz/get_ports_fdtdz.py +0 -0
  76. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/fdtdz/get_sparameters_fdtdz.py +0 -0
  77. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/femwell/__init__.py +0 -0
  78. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/femwell/mode_solver.py +0 -0
  79. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/femwell/test_mode_solver.py +0 -0
  80. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/__init__.py +0 -0
  81. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/get_material.py +0 -0
  82. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/get_meep_geometry.py +0 -0
  83. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/get_port_eigenmode.py +0 -0
  84. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/get_simulation_grating_fiber.py +0 -0
  85. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/meep_adjoint_optimization.py +0 -0
  86. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_eigenmode.py +0 -0
  87. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_materials.py +0 -0
  88. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_sparameterNxN/test_sparameterNxN_crossing.csv +0 -0
  89. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_sparameterNxN/test_sparameterNxN_straight.csv +0 -0
  90. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameterNxN_crossing.csv +0 -0
  91. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameterNxN_straight.csv +0 -0
  92. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameterNxN_symmetries_straight.csv +0 -0
  93. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameter_straight_mpi.csv +0 -0
  94. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameter_straight_mpi_pool.csv +0 -0
  95. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameters_crossing_symmetric.csv +0 -0
  96. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameters_straight.csv +0 -0
  97. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameters_straight_batch.csv +0 -0
  98. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameters_straight_mpi.csv +0 -0
  99. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameters_straight_mpi_pool.csv +0 -0
  100. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep/test_sparameters_straight_symmetric.csv +0 -0
  101. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/test_write_sparameters_meep.py +0 -0
  102. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/write_sparameters_meep.py +0 -0
  103. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/write_sparameters_meep_batch.py +0 -0
  104. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmeep/write_sparameters_meep_mpi.py +0 -0
  105. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/__init__.py +0 -0
  106. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/define_polysurfaces.py +0 -0
  107. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/get_mesh.py +0 -0
  108. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/tests/test_custom_names.py +0 -0
  109. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/tests/test_meshing_2D.py +0 -0
  110. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/tests/test_meshing_3D.py +0 -0
  111. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/uz_xsection_mesh.py +0 -0
  112. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/xy_xsection_mesh.py +0 -0
  113. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/gmsh/xyz_mesh.py +0 -0
  114. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/__init__.py +0 -0
  115. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/dataprep/__init__.py +0 -0
  116. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/__init__.py +0 -0
  117. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/check_duplicated_cells.py +0 -0
  118. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/check_exclusion.py +0 -0
  119. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/check_inclusion.py +0 -0
  120. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/check_space.py +0 -0
  121. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/check_width.py +0 -0
  122. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/count_drc.py +0 -0
  123. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/write_connectivity.py +0 -0
  124. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/drc/write_drc.py +0 -0
  125. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/get_density.py +0 -0
  126. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/get_netlist.py +0 -0
  127. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_dataprep_regions.py +0 -0
  128. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_density.py +0 -0
  129. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_drc_exclusion.py +0 -0
  130. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_drc_inclusion.py +0 -0
  131. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_drc_space.py +0 -0
  132. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_drc_width.py +0 -0
  133. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_geometry_write_connectivity.py +0 -0
  134. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/klayout/tests/test_global_density.py +0 -0
  135. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/__init__.py +0 -0
  136. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/interconnect.py +0 -0
  137. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/read.py +0 -0
  138. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/settings.py +0 -0
  139. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/lumerical/tests/test_lumerical_read_sparameters.py +0 -0
  140. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/__init__.py +0 -0
  141. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/inorganic.py +0 -0
  142. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/optical/__init__.py +0 -0
  143. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/optical/optical_mat.py +0 -0
  144. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/optical/refractive_index_info.py +0 -0
  145. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/semiconductor/__init__.py +0 -0
  146. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/materials/semiconductor/semiconductor_mat.py +0 -0
  147. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/meow/__init__.py +0 -0
  148. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/meow/meow_eme.py +0 -0
  149. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/meow/test_meow_simulation.py +0 -0
  150. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/__init__.py +0 -0
  151. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/coupler.py +0 -0
  152. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/find_coupling_vs_gap.py +0 -0
  153. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/find_mode_dispersion.py +0 -0
  154. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/find_neff_ng_dw_dh.py +0 -0
  155. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/find_neff_vs_width.py +0 -0
  156. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/get_mode_solver_coupler.py +0 -0
  157. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/get_mode_solver_cross_section.py +0 -0
  158. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/get_mode_solver_rib.py +0 -0
  159. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/modes/neff_vs_width_nitride.csv +0 -0
  160. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/modes/neff_vs_width_rib.csv +0 -0
  161. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/modes/neff_vs_width_strip.csv +0 -0
  162. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/neff_vs_width.csv +0 -0
  163. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/overlap.py +0 -0
  164. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_dw_dh/test_dw_dh.csv +0 -0
  165. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_dw_dh/test_dw_dh.obtained.csv +0 -0
  166. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_dw_dh/test_dw_dh_dispersion.csv +0 -0
  167. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_dw_dh.py +0 -0
  168. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_find_modes.py +0 -0
  169. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_find_modes_dispersion.py +0 -0
  170. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_neff_vs_width/test_neff_vs_width.csv +0 -0
  171. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_neff_vs_width/test_neff_vs_width.obtained.csv +0 -0
  172. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/tests/test_neff_vs_width.py +0 -0
  173. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/types.py +0 -0
  174. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/modes/waveguide.py +0 -0
  175. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/palace/__init__.py +0 -0
  176. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/palace/driven.json +0 -0
  177. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/palace/electrostatic.json +0 -0
  178. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/palace/get_capacitance.py +0 -0
  179. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/palace/get_scattering.py +0 -0
  180. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/palace/tests/test_palace.py +0 -0
  181. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/path_length_analysis/__init__.py +0 -0
  182. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/path_length_analysis/test_pathlength_extraction.py +0 -0
  183. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/photonic_circuit_models/__init__.py +0 -0
  184. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/photonic_circuit_models/coupler.py +0 -0
  185. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/photonic_circuit_models/fsr.py +0 -0
  186. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/photonic_circuit_models/heater.py +0 -0
  187. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/photonic_circuit_models/mzi.py +0 -0
  188. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/photonic_circuit_models/ring.py +0 -0
  189. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/__init__.py +0 -0
  190. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/diffusion.py +0 -0
  191. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/skew/antimony_si_skew.csv +0 -0
  192. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/skew/arsenic_si_skew.csv +0 -0
  193. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/skew/boron_si_skew.csv +0 -0
  194. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/process/skew/phosphorus_si_skew.csv +0 -0
  195. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/__init__.py +0 -0
  196. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/build_model.py +0 -0
  197. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/integrations/__init__.py +0 -0
  198. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/integrations/femwell_waveguide_model.py +0 -0
  199. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/integrations/meep_FDTD_model.py +0 -0
  200. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/integrations/meow_eme_model.py +0 -0
  201. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/interpolators.py +0 -0
  202. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/mlp.py +0 -0
  203. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/parameter.py +0 -0
  204. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/plot_model.py +0 -0
  205. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/tests/test_mzi_lattice/test_mzi_lattice.obtained.yml +0 -0
  206. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/tests/test_mzi_lattice/test_mzi_lattice.yml +0 -0
  207. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/sax/tests/test_parameters.py +0 -0
  208. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/schematic_editor/__init__.py +0 -0
  209. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/schematic_editor/circuitviz.py +0 -0
  210. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/schematic_editor/schematic_editor.py +0 -0
  211. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/__init__.py +0 -0
  212. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/get_results.py +0 -0
  213. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/materials.py +0 -0
  214. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/modes.py +0 -0
  215. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_component_modeler.py +0 -0
  216. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_materials.py +0 -0
  217. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_modes/test_sweep_width.csv +0 -0
  218. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_modes/test_sweep_width.obtained.csv +0 -0
  219. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_modes_coupler.py +0 -0
  220. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_modes_waveguide.py +0 -0
  221. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_plot_simulation_grating_coupler.py +0 -0
  222. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/test_write_sparameters.py +0 -0
  223. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/tests_sparameters/sim_ref.yaml +0 -0
  224. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/tests_sparameters/test_simulation.py +0 -0
  225. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/tests_sparameters/test_write_sparameters.py +0 -0
  226. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/tests/tests_sparameters/test_write_sparameters_grating_coupler.py +0 -0
  227. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/types.py +0 -0
  228. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/util.py +0 -0
  229. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/tidy3d/write_sparameters_grating_coupler.py +0 -0
  230. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/vlsir/__init__.py +0 -0
  231. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/vlsir/export_netlist.py +0 -0
  232. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/vlsir/tests/resources/pads_correct.cir +0 -0
  233. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/vlsir/tests/resources/pads_correct.scs +0 -0
  234. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/vlsir/tests/resources/pads_correct.sp +0 -0
  235. {gplugins-0.10.2 → gplugins-0.12.0}/gplugins/vlsir/tests/test_vlsir.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gplugins
3
- Version: 0.10.2
3
+ Version: 0.12.0
4
4
  Summary: gdsfactory plugins
5
5
  Keywords: python
6
6
  Author-email: gdsfactory <contact@gdsfactory.com>
@@ -46,12 +46,14 @@ Requires-Dist: shapely ; extra == "gmsh"
46
46
  Requires-Dist: meshwell>=1.0.7,<=1.1 ; extra == "gmsh"
47
47
  Requires-Dist: klayout ; extra == "klayout"
48
48
  Requires-Dist: pyvis<=0.3.1 ; extra == "klayout"
49
- Requires-Dist: jax==0.4.23 ; extra == "meow"
50
- Requires-Dist: jaxlib==0.4.23 ; extra == "meow"
51
- Requires-Dist: meow-sim>=0.9.0,<0.10.2 ; extra == "meow"
49
+ Requires-Dist: jax>=0.4.26 ; extra == "meow"
50
+ Requires-Dist: jaxlib>=0.4.26 ; extra == "meow"
51
+ Requires-Dist: flax>=0.8.2 ; extra == "meow"
52
+ Requires-Dist: meow-sim>=0.9.0,<0.12.0 ; extra == "meow"
52
53
  Requires-Dist: tidy3d==2.5.2 ; extra == "meow"
53
- Requires-Dist: jax<=0.4.23 ; extra == "sax"
54
- Requires-Dist: jaxlib<=0.4.23 ; extra == "sax"
54
+ Requires-Dist: jax>=0.4.26 ; extra == "sax"
55
+ Requires-Dist: jaxlib>=0.4.26 ; extra == "sax"
56
+ Requires-Dist: flax>=0.8.2 ; extra == "sax"
55
57
  Requires-Dist: sax>=0.12.1,<0.13.0 ; extra == "sax"
56
58
  Requires-Dist: scikit-learn ; extra == "sax"
57
59
  Requires-Dist: pyvis<=0.3.1 ; extra == "sax"
@@ -75,7 +77,7 @@ Provides-Extra: schematic
75
77
  Provides-Extra: tidy3d
76
78
  Provides-Extra: vlsir
77
79
 
78
- # gplugins 0.10.2
80
+ # gplugins 0.12.0
79
81
 
80
82
  [![docs](https://github.com/gdsfactory/gplugins/actions/workflows/pages.yml/badge.svg)](https://gdsfactory.github.io/gplugins/)
81
83
  [![PyPI](https://img.shields.io/pypi/v/gplugins)](https://pypi.org/project/gplugins/)
@@ -1,4 +1,4 @@
1
- # gplugins 0.10.2
1
+ # gplugins 0.12.0
2
2
 
3
3
  [![docs](https://github.com/gdsfactory/gplugins/actions/workflows/pages.yml/badge.svg)](https://gdsfactory.github.io/gplugins/)
4
4
  [![PyPI](https://img.shields.io/pypi/v/gplugins)](https://pypi.org/project/gplugins/)
@@ -1,6 +1,6 @@
1
1
  """gplugins - gdsfactory plugins"""
2
2
 
3
- __version__ = "0.10.2"
3
+ __version__ = "0.12.0"
4
4
 
5
5
  from gplugins.common.utils import plot, port_symmetries
6
6
  from gplugins.common.utils.get_effective_indices import get_effective_indices
@@ -1,4 +1,5 @@
1
1
  """Returns component with simulation markers."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import warnings
@@ -18,9 +18,11 @@ async def handle_return(
18
18
  append: bool = False,
19
19
  ) -> None:
20
20
  """Reads through a :class:`StreamReader` and tees content to ``out_stream`` and ``log_file``."""
21
- with open(
22
- log_file, "a" if append else "w", encoding="utf-8", buffering=1
23
- ) if log_file else nullcontext(None) as f:
21
+ with (
22
+ open(log_file, "a" if append else "w", encoding="utf-8", buffering=1)
23
+ if log_file
24
+ else nullcontext(None) as f
25
+ ):
24
26
  while True:
25
27
  # Without this sleep, the program won't exit
26
28
  await asyncio.sleep(0)
@@ -1,4 +1,5 @@
1
1
  """Disable print statements for overly verbose simulators."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import os
@@ -88,9 +88,9 @@ def get_component_with_net_layers(
88
88
  new_layers_init[0] + i,
89
89
  new_layers_init[1] + j,
90
90
  )
91
- layer_stack.layers[
92
- f"{old_layername}{delimiter}{portname}"
93
- ] = new_layer
91
+ layer_stack.layers[f"{old_layername}{delimiter}{portname}"] = (
92
+ new_layer
93
+ )
94
94
  net_component.add_polygon(polygon, layer=new_layer_number)
95
95
  # Otherwise put the polygon back on the same layer
96
96
  else:
@@ -1,4 +1,5 @@
1
1
  """Useful optical constant manipulations."""
2
+
2
3
  import numpy as np
3
4
 
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Preprocessing involving only the LayerStack."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import numpy as np
@@ -8,7 +8,6 @@ From Chrostowski, L., & Hochberg, M. (2015). Silicon Photonics Design: From Devi
8
8
 
9
9
  """
10
10
 
11
-
12
11
  from __future__ import annotations
13
12
 
14
13
  import warnings
@@ -57,8 +56,8 @@ def dn_carriers(wavelength: float, dN: float, dP: float) -> float:
57
56
  else:
58
57
  wavelength *= 1e-6
59
58
  return (
60
- -3.64 * 1e-10 * wavelength**2 * dN
61
- - 3.51 * 1e-6 * wavelength**2 * np.power(dP, 0.8)
59
+ -3.64 * 1e-10 * wavelength** 2 * dN
60
+ - 3.51 * 1e-6 * wavelength** 2 * np.power(dP, 0.8)
62
61
  )
63
62
 
64
63
 
@@ -45,16 +45,16 @@ def get_thermal_conductivities(basis):
45
45
  # adding the layer to the thermal_conductivities dict. Check for that
46
46
  # case
47
47
  if domain in thermal_conductivities:
48
- thermal_conductivity[
49
- basis.get_dofs(elements=domain)
50
- ] = thermal_conductivities[domain]
48
+ thermal_conductivity[basis.get_dofs(elements=domain)] = (
49
+ thermal_conductivities[domain]
50
+ )
51
51
  else:
52
52
  for material, labels in materials_dict.items():
53
53
  if domain in labels:
54
54
  # Assign the right values
55
- thermal_conductivity[
56
- basis.get_dofs(elements=domain)
57
- ] = thermal_conductivities[material]
55
+ thermal_conductivity[basis.get_dofs(elements=domain)] = (
56
+ thermal_conductivities[material]
57
+ )
58
58
  break
59
59
 
60
60
  thermal_conductivity *= 1e-12 # 1e-12 -> conversion from 1/m^2 -> 1/um^2
@@ -1,4 +1,5 @@
1
1
  """Returns simulation from component."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import inspect
@@ -7,6 +7,7 @@
7
7
  - add tests
8
8
 
9
9
  """
10
+
10
11
  from __future__ import annotations
11
12
 
12
13
  from typing import Any
@@ -6,6 +6,7 @@ MFD:
6
6
  - 9.2 for Oband
7
7
 
8
8
  """
9
+
9
10
  from __future__ import annotations
10
11
 
11
12
  import hashlib
@@ -1,4 +1,5 @@
1
1
  """Preprocessing involving both the GDS and the LayerStack, or the resulting simulation polygons."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import numpy as np
@@ -75,15 +76,15 @@ def process_buffers(layer_polygons_dict: dict, layer_stack: LayerStack):
75
76
  layer_stack.layers[layername].thickness * zs[z_ind + 1]
76
77
  - layer_stack.layers[layername].thickness * z
77
78
  )
78
- extended_layer_stack_layers[
79
- f"{layername}_{poly_ind}_{z}"
80
- ] = LayerLevel(
81
- layer=layer_stack.layers[layername].layer,
82
- thickness=new_thickness,
83
- zmin=new_zmin,
84
- material=layer_stack.layers[layername].material,
85
- info=layer_stack.layers[layername].info,
86
- mesh_order=layer_stack.layers[layername].mesh_order,
79
+ extended_layer_stack_layers[f"{layername}_{poly_ind}_{z}"] = (
80
+ LayerLevel(
81
+ layer=layer_stack.layers[layername].layer,
82
+ thickness=new_thickness,
83
+ zmin=new_zmin,
84
+ material=layer_stack.layers[layername].material,
85
+ info=layer_stack.layers[layername].info,
86
+ mesh_order=layer_stack.layers[layername].mesh_order,
87
+ )
87
88
  )
88
89
  extended_layer_polygons_dict[f"{layername}_{poly_ind}_{z}"] = (
89
90
  f"{layername}",
@@ -91,16 +92,16 @@ def process_buffers(layer_polygons_dict: dict, layer_stack: LayerStack):
91
92
  polygon.buffer(width_buffer),
92
93
  polygon.buffer(width_buffers[z_ind + 1]),
93
94
  )
94
- extended_layer_stack_layers[
95
- f"{layername}_{poly_ind}_{zs[-1]}"
96
- ] = LayerLevel(
97
- layer=layer_stack.layers[layername].layer,
98
- thickness=0,
99
- zmin=layer_stack.layers[layername].zmin
100
- + layer_stack.layers[layername].thickness,
101
- material=layer_stack.layers[layername].material,
102
- info=layer_stack.layers[layername].info,
103
- mesh_order=layer_stack.layers[layername].mesh_order,
95
+ extended_layer_stack_layers[f"{layername}_{poly_ind}_{zs[-1]}"] = (
96
+ LayerLevel(
97
+ layer=layer_stack.layers[layername].layer,
98
+ thickness=0,
99
+ zmin=layer_stack.layers[layername].zmin
100
+ + layer_stack.layers[layername].thickness,
101
+ material=layer_stack.layers[layername].material,
102
+ info=layer_stack.layers[layername].info,
103
+ mesh_order=layer_stack.layers[layername].mesh_order,
104
+ )
104
105
  )
105
106
  return extended_layer_polygons_dict, LayerStack(layers=extended_layer_stack_layers)
106
107
 
@@ -1,4 +1,5 @@
1
1
  """Preprocessing involving mostly the GDS polygons."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import gdsfactory as gf
@@ -39,7 +40,7 @@ def fuse_polygons(
39
40
  ]
40
41
 
41
42
  return shapely.ops.unary_union(shapely_polygons).simplify(
42
- simplify_tol, preserve_topology=True
43
+ simplify_tol, preserve_topology=False
43
44
  )
44
45
 
45
46
 
@@ -95,6 +95,7 @@ class RegionCollection:
95
95
  self.layout = lib.cell_by_name(cell_name) if cell_name else lib.top_cell()
96
96
  self.lib = lib
97
97
  self.regions = {}
98
+ self.cell = lib[lib.top_cell().cell_index()]
98
99
 
99
100
  def __getitem__(self, layer: tuple[int, int]) -> Region:
100
101
  _assert_is_layer(layer)
@@ -142,13 +143,9 @@ class RegionCollection:
142
143
  else:
143
144
  c.write(gdspath)
144
145
 
145
- def plot(self, **kwargs):
146
+ def plot(self) -> kf.KCell:
146
147
  """Plot regions."""
147
- gdspath = GDSDIR_TEMP / "out.gds"
148
- self.write_gds(gdspath=gdspath, **kwargs)
149
- gf.clear_cache()
150
- c = gf.import_gds(gdspath)
151
- return c.plot()
148
+ return self.cell
152
149
 
153
150
  def get_kcell(
154
151
  self, keep_original: bool = True, cellname: str = "Unnamed"
@@ -1,22 +1,23 @@
1
1
  """Write GDS with sample errors."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import gdsfactory as gf
6
+ import numpy as np
5
7
  from gdsfactory.component import Component
6
- from gdsfactory.typings import Float2, Layer
8
+ from gdsfactory.typings import Layer
7
9
 
8
10
  layer = (1, 0)
9
11
 
10
12
 
11
13
  @gf.cell
12
- def width_min(size: Float2 = (0.1, 0.1)) -> Component:
13
- return gf.components.rectangle(size=size, layer=layer)
14
+ def width_min(width: float = 0.1) -> Component:
15
+ return gf.components.rectangle(size=(width, width), layer=layer)
14
16
 
15
17
 
16
18
  @gf.cell
17
- def area_min() -> Component:
18
- size = (0.2, 0.2)
19
- return gf.components.rectangle(size=size, layer=layer)
19
+ def area_min(width: float = 0.2) -> Component:
20
+ return gf.components.rectangle(size=(width, width), layer=layer)
20
21
 
21
22
 
22
23
  @gf.cell
@@ -46,8 +47,13 @@ def enclosing(
46
47
  enclosing: float = 0.1, layer1: Layer = (40, 0), layer2: Layer = (41, 0)
47
48
  ) -> Component:
48
49
  """Layer1 must be enclosed by layer2 by value.
49
-
50
50
  checks if layer1 encloses (is bigger than) layer2 by value
51
+
52
+ Args:
53
+ enclosing: value to enclose layer1 by layer2.
54
+ layer1: layer to enclose.
55
+ layer2: layer to enclose by.
56
+
51
57
  """
52
58
  w1 = 1
53
59
  w2 = w1 + enclosing
@@ -69,18 +75,17 @@ def snapping_error(gap: float = 1e-3) -> Component:
69
75
 
70
76
 
71
77
  @gf.cell
72
- def errors() -> Component:
73
- """Write a GDS with sample errors."""
74
- components = [width_min(), gap_min(), separation(), enclosing()]
75
- c = gf.pack(components, spacing=1.5)
76
- return gf.add_padding_container(c[0], layers=((64, 0),), default=5)
77
-
78
-
79
- @gf.cell
80
- def errors2() -> Component:
78
+ def errors(n: int = 20) -> Component:
81
79
  """Write a GDS with sample errors."""
82
- components = 2 * [width_min(), gap_min(), separation(), enclosing()]
83
- c = gf.pack(components, spacing=1.5)
80
+ wmin = 0.1
81
+ # components = [width_min(), gap_min(), separation(), enclosing()]
82
+ cs = []
83
+ cs += [width_min(wmin * np.random.rand()) for _ in range(n)]
84
+ cs += [gap_min(gap=0.1 * np.random.rand()) for _ in range(n)]
85
+ cs += [separation(gap=0.1 * np.random.rand()) for _ in range(n)]
86
+ cs += [enclosing(enclosing=0.1 * np.random.rand()) for _ in range(n)]
87
+
88
+ c = gf.pack(cs, spacing=1.5)
84
89
  return gf.add_padding_container(c[0], layers=((64, 0),), default=5)
85
90
 
86
91
 
@@ -92,6 +97,6 @@ if __name__ == "__main__":
92
97
  # c = snapping_error()
93
98
  # c.write_gds("snap.gds")
94
99
 
95
- c = errors2()
100
+ c = errors()
96
101
  c.write_gds("errors.gds")
97
102
  c.show(show_ports=True)
@@ -0,0 +1,137 @@
1
+ import itertools
2
+ from pathlib import Path
3
+
4
+ import klayout.db as kdb
5
+ import networkx as nx
6
+ from gdsfactory.config import logger
7
+ from gdsfactory.typings import PathType
8
+
9
+ from gplugins.klayout.netlist_spice_reader import (
10
+ CalibreSpiceReader,
11
+ NetlistSpiceReaderDelegateWithStrings,
12
+ )
13
+
14
+
15
+ def _get_device_name(device: kdb.Device) -> str:
16
+ """Get a unique name for a ``Device`` instance."""
17
+ return f"{device.device_class().name}_{device.expanded_name()}"
18
+
19
+
20
+ def netlist_to_networkx(
21
+ netlist: kdb.Netlist,
22
+ include_labels: bool = True,
23
+ top_cell: str | None = None,
24
+ spice_reader_instance: NetlistSpiceReaderDelegateWithStrings | None = None,
25
+ ) -> nx.Graph:
26
+ """Convert a KLayout DB `Netlist` to a networkx graph.
27
+
28
+ Args:
29
+ netlist: The KLayout DB `Netlist` to convert to a NetworkX `Graph`.
30
+ include_labels: Whether to include net labels in the graph connected to corresponding cells.
31
+ top_cell: The name of the top cell to consider for the NetworkX graph. Defaults to all top cells.
32
+ spice_reader_instance: The KLayout Spice reader that was used for parsing SPICE netlists.
33
+ Used for fetching string parameter values from a stored mapping.
34
+
35
+ Returns:
36
+ A networkx `Graph` representing the connectivity of the `Netlist`.
37
+ """
38
+ G = nx.Graph()
39
+ netlist.flatten()
40
+
41
+ top_circuits = list(
42
+ itertools.islice(netlist.each_circuit_top_down(), netlist.top_circuit_count())
43
+ )
44
+
45
+ if top_cell:
46
+ try:
47
+ top_circuits = (
48
+ next(
49
+ c for c in top_circuits if c.name.casefold() == top_cell.casefold()
50
+ ),
51
+ )
52
+ except StopIteration as e:
53
+ available_top_cells = [cell.name for cell in top_circuits]
54
+ raise ValueError(
55
+ f"{top_cell=!r} not found in the netlist. Available top cells: {available_top_cells!r}"
56
+ ) from e
57
+
58
+ all_used_nets = set()
59
+ for circuit in top_circuits:
60
+ for device in circuit.each_device():
61
+ # Gather properties of Device class
62
+ device_class = device.device_class()
63
+ parameter_definitions = device_class.parameter_definitions()
64
+ terminal_definitions = device_class.terminal_definitions()
65
+
66
+ # Gather values for specific Device instance
67
+ parameters = {
68
+ parameter.name: (
69
+ spice_reader_instance.integer_to_string_map.get(
70
+ int(device.parameter(parameter.name)),
71
+ device.parameter(parameter.name),
72
+ )
73
+ if spice_reader_instance
74
+ else device.parameter(parameter.name)
75
+ )
76
+ for parameter in parameter_definitions
77
+ }
78
+ nets = [
79
+ device.net_for_terminal(terminal.name)
80
+ for terminal in terminal_definitions
81
+ ]
82
+ device_name = _get_device_name(device)
83
+
84
+ # Create NetworkX representation
85
+ G.add_node(device_name, **parameters)
86
+ for net in nets:
87
+ net_name = net.expanded_name()
88
+ G.add_edge(device_name, net_name)
89
+ all_used_nets.add(net_name)
90
+
91
+ if not include_labels:
92
+ for node in all_used_nets:
93
+ connections = list(G.neighbors(node))
94
+ G.add_edges_from(itertools.combinations(connections, r=2))
95
+ G.remove_node(node)
96
+
97
+ return G
98
+
99
+
100
+ def networkx_from_spice(
101
+ filepath: PathType,
102
+ include_labels: bool = True,
103
+ top_cell: str | None = None,
104
+ spice_reader: type[NetlistSpiceReaderDelegateWithStrings] = CalibreSpiceReader,
105
+ **kwargs,
106
+ ) -> nx.Graph:
107
+ """Returns a networkx Graph from a SPICE netlist file or KLayout LayoutToNetlist.
108
+ Args:
109
+ filepath: Path to the KLayout LayoutToNetlist file or a SPICE netlist.
110
+ File extensions should be `.l2n` and `.spice`, respectively.
111
+ include_labels: Whether to include labels in the graph connected to corresponding cells.
112
+ top_cell: The name of the top cell to consider for the NetworkX graph. Defaults to all top cells.
113
+ spice_reader: The KLayout Spice reader to use for parsing SPICE netlists.
114
+ """
115
+ spice_reader_instance = None
116
+ match Path(filepath).suffix:
117
+ case ".l2n" | ".txt":
118
+ l2n = kdb.LayoutToNetlist()
119
+ l2n.read(str(filepath))
120
+ netlist = l2n.netlist()
121
+ case ".cir" | ".sp" | ".spi" | ".spice":
122
+ reader = kdb.NetlistSpiceReader(spice_reader_instance := spice_reader())
123
+ netlist = kdb.Netlist()
124
+ netlist.read(str(filepath), reader)
125
+ case _:
126
+ logger.warning("Assuming file is KLayout native LayoutToNetlist file")
127
+ l2n = kdb.LayoutToNetlist()
128
+ l2n.read(str(filepath))
129
+ netlist = l2n.netlist()
130
+
131
+ # Creating a graph for the connectivity
132
+ return netlist_to_networkx(
133
+ netlist,
134
+ include_labels=include_labels,
135
+ top_cell=top_cell,
136
+ spice_reader_instance=spice_reader_instance,
137
+ )
@@ -0,0 +1,117 @@
1
+ import hashlib
2
+ import re
3
+ from abc import ABC, abstractmethod
4
+ from collections.abc import MutableMapping, Sequence
5
+ from typing import Any
6
+
7
+ import klayout.db as kdb
8
+
9
+
10
+ class NetlistSpiceReaderDelegateWithStrings(kdb.NetlistSpiceReaderDelegate, ABC):
11
+ """A KLayout SPICE reader delegate that supports string variables for ``Device`` through a hash map."""
12
+
13
+ @property
14
+ @abstractmethod
15
+ def integer_to_string_map(self) -> MutableMapping[int, str]:
16
+ pass
17
+
18
+
19
+ class NoCommentReader(kdb.NetlistSpiceReaderDelegate):
20
+ """KLayout Spice reader without comments after $. This allows checking the netlist for HSPICE."""
21
+
22
+ n_nodes: int = 0
23
+
24
+ def parse_element(self, s: str, element: str) -> kdb.ParseElementData:
25
+ if "$" in s:
26
+ s, *_ = s.split("$") # Don't take comments into account
27
+ parsed = super().parse_element(s, element)
28
+ # ensure uniqueness
29
+ parsed.model_name = parsed.model_name + f"_{self.n_nodes}"
30
+ self.n_nodes += 1
31
+ return parsed
32
+
33
+
34
+ class CalibreSpiceReader(NetlistSpiceReaderDelegateWithStrings):
35
+ """KLayout Spice reader for Calibre LVS extraction output.
36
+
37
+ Considers parameter values for generic `X` devices that start with `WG`.
38
+ Ignores comments after $ excluding location given with ``$X=number $Y=number``."""
39
+
40
+ n_nodes: int = 0
41
+ calibre_location_pattern: str = r"\$X=(-?\d+) \$Y=(-?\d+)"
42
+ integer_to_string_map: MutableMapping[int, str] = {}
43
+
44
+ def wants_subcircuit(self, name: str):
45
+ """Model all SPICE models that start with `WG` as devices in order to support parameters."""
46
+ return "WG" in name or super().wants_subcircuit(name)
47
+
48
+ def parse_element(self, s: str, element: str) -> kdb.ParseElementData:
49
+ x_value, y_value = None, None
50
+ if "$" in s:
51
+ if location_matches := re.search(self.calibre_location_pattern, s):
52
+ x_value, y_value = (int(e) / 1000 for e in location_matches.group(1, 2))
53
+
54
+ # Use default KLayout parser for rest of the SPICE
55
+ s, *_ = s.split("$")
56
+
57
+ parsed = super().parse_element(s, element)
58
+ parsed.parameters |= {"x": x_value, "y": y_value}
59
+
60
+ # ensure uniqueness
61
+ parsed.model_name = parsed.model_name
62
+ self.n_nodes += 1
63
+ return parsed
64
+
65
+ @staticmethod
66
+ def hash_str_to_int(s: str) -> int:
67
+ return int(hashlib.shake_128(s.encode()).hexdigest(4), 16)
68
+
69
+ def element(
70
+ self,
71
+ circuit: kdb.Circuit,
72
+ element: str,
73
+ name: str,
74
+ model: str,
75
+ value: Any,
76
+ nets: Sequence[kdb.Net],
77
+ parameters: dict[str, int | float | str],
78
+ ):
79
+ # Handle non-'X' elements with standard KLayout processing
80
+ if element != "X":
81
+ # Other devices with standard KLayout
82
+ return super().element(
83
+ circuit, element, name, model, value, nets, parameters
84
+ )
85
+ clx = circuit.netlist().device_class_by_name(model)
86
+
87
+ # Create Device class on first occurrence
88
+ if not clx:
89
+ clx = kdb.DeviceClass()
90
+ clx.name = model
91
+ for key, value in parameters.items():
92
+ clx.add_parameter(kdb.DeviceParameterDefinition(key))
93
+ # map string variables to integers
94
+ if (
95
+ isinstance(value, str)
96
+ and value not in self.integer_to_string_map.values()
97
+ ):
98
+ hashed_value = CalibreSpiceReader.hash_str_to_int(value)
99
+ self.integer_to_string_map[hashed_value] = value
100
+
101
+ for i in range(len(nets)):
102
+ clx.add_terminal(kdb.DeviceTerminalDefinition(str(i)))
103
+ circuit.netlist().add(clx)
104
+
105
+ device = circuit.create_device(clx, name)
106
+ for i, net in enumerate(nets):
107
+ device.connect_terminal(i, net)
108
+
109
+ for key, value in parameters.items():
110
+ device.set_parameter(
111
+ key,
112
+ (
113
+ CalibreSpiceReader.hash_str_to_int(value)
114
+ if isinstance(value, str)
115
+ else value
116
+ ),
117
+ )