pyedb 0.59.0__py3-none-any.whl → 0.61.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.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (318) hide show
  1. pyedb/__init__.py +23 -1
  2. pyedb/common/__init__.py +21 -0
  3. pyedb/common/nets.py +22 -0
  4. pyedb/component_libraries/ansys_components.py +22 -0
  5. pyedb/configuration/__init__.py +21 -0
  6. pyedb/configuration/cfg_boundaries.py +1 -1
  7. pyedb/configuration/cfg_common.py +1 -1
  8. pyedb/configuration/cfg_components.py +36 -8
  9. pyedb/configuration/cfg_data.py +1 -1
  10. pyedb/configuration/cfg_general.py +1 -1
  11. pyedb/configuration/cfg_modeler.py +1 -1
  12. pyedb/configuration/cfg_nets.py +1 -1
  13. pyedb/configuration/cfg_operations.py +1 -1
  14. pyedb/configuration/cfg_package_definition.py +1 -1
  15. pyedb/configuration/cfg_padstacks.py +1 -1
  16. pyedb/configuration/cfg_pin_groups.py +1 -1
  17. pyedb/configuration/cfg_ports_sources.py +3 -2
  18. pyedb/configuration/cfg_s_parameter_models.py +1 -1
  19. pyedb/configuration/cfg_setup.py +5 -1
  20. pyedb/configuration/cfg_spice_models.py +1 -1
  21. pyedb/configuration/cfg_stackup.py +1 -1
  22. pyedb/configuration/cfg_terminals.py +22 -0
  23. pyedb/configuration/configuration.py +6 -5
  24. pyedb/dotnet/__init__.py +21 -0
  25. pyedb/dotnet/clr_module.py +22 -0
  26. pyedb/dotnet/database/Variables.py +1 -1
  27. pyedb/dotnet/database/__init__.py +22 -0
  28. pyedb/dotnet/database/cell/__init__.py +21 -0
  29. pyedb/dotnet/database/cell/connectable.py +1 -1
  30. pyedb/dotnet/database/cell/hierarchy/__init__.py +21 -0
  31. pyedb/dotnet/database/cell/hierarchy/component.py +9 -7
  32. pyedb/dotnet/database/cell/hierarchy/hierarchy_obj.py +1 -1
  33. pyedb/dotnet/database/cell/hierarchy/model.py +2 -29
  34. pyedb/dotnet/database/cell/hierarchy/netlist_model.py +1 -1
  35. pyedb/dotnet/database/cell/hierarchy/pin_pair_model.py +1 -1
  36. pyedb/dotnet/database/cell/hierarchy/s_parameter_model.py +11 -15
  37. pyedb/dotnet/database/cell/hierarchy/spice_model.py +14 -8
  38. pyedb/dotnet/database/cell/layout.py +5 -4
  39. pyedb/dotnet/database/cell/layout_obj.py +1 -1
  40. pyedb/dotnet/database/cell/primitive/__init__.py +22 -0
  41. pyedb/dotnet/database/cell/primitive/bondwire.py +1 -1
  42. pyedb/dotnet/database/cell/primitive/path.py +1 -1
  43. pyedb/dotnet/database/cell/primitive/primitive.py +1 -1
  44. pyedb/dotnet/database/cell/terminal/__init__.py +21 -0
  45. pyedb/dotnet/database/cell/terminal/bundle_terminal.py +1 -1
  46. pyedb/dotnet/database/cell/terminal/edge_terminal.py +1 -1
  47. pyedb/dotnet/database/cell/terminal/padstack_instance_terminal.py +1 -1
  48. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  49. pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
  50. pyedb/dotnet/database/cell/terminal/terminal.py +7 -2
  51. pyedb/dotnet/database/cell/voltage_regulator.py +1 -1
  52. pyedb/dotnet/database/components.py +6 -2
  53. pyedb/dotnet/database/definition/__init__.py +21 -0
  54. pyedb/dotnet/database/definition/component_def.py +1 -1
  55. pyedb/dotnet/database/definition/component_model.py +1 -1
  56. pyedb/dotnet/database/definition/definition_obj.py +1 -1
  57. pyedb/dotnet/database/definition/definitions.py +1 -1
  58. pyedb/dotnet/database/definition/package_def.py +1 -1
  59. pyedb/dotnet/database/dotnet/__init__.py +21 -0
  60. pyedb/dotnet/database/dotnet/database.py +1 -1
  61. pyedb/dotnet/database/dotnet/primitive.py +1 -1
  62. pyedb/dotnet/database/edb_data/__init__.py +21 -0
  63. pyedb/dotnet/database/edb_data/control_file.py +1 -1
  64. pyedb/dotnet/database/edb_data/design_options.py +1 -1
  65. pyedb/dotnet/database/edb_data/edbvalue.py +1 -1
  66. pyedb/dotnet/database/edb_data/hfss_extent_info.py +1 -1
  67. pyedb/dotnet/database/edb_data/layer_data.py +1 -1
  68. pyedb/dotnet/database/edb_data/nets_data.py +1 -1
  69. pyedb/dotnet/database/edb_data/padstacks_data.py +6 -4
  70. pyedb/dotnet/database/edb_data/ports.py +1 -1
  71. pyedb/dotnet/database/edb_data/primitives_data.py +1 -1
  72. pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +1 -1
  73. pyedb/dotnet/database/edb_data/simulation_configuration.py +1 -1
  74. pyedb/dotnet/database/edb_data/sources.py +1 -1
  75. pyedb/dotnet/database/edb_data/utilities.py +1 -1
  76. pyedb/dotnet/database/edb_data/variables.py +1 -1
  77. pyedb/dotnet/database/general.py +1 -1
  78. pyedb/dotnet/database/geometry/__init__.py +21 -0
  79. pyedb/dotnet/database/geometry/point_data.py +1 -1
  80. pyedb/dotnet/database/geometry/polygon_data.py +1 -1
  81. pyedb/dotnet/database/hfss.py +1 -1
  82. pyedb/dotnet/database/layout_obj_instance.py +1 -1
  83. pyedb/dotnet/database/layout_validation.py +1 -1
  84. pyedb/dotnet/database/materials.py +1 -1
  85. pyedb/dotnet/database/modeler.py +3 -2
  86. pyedb/dotnet/database/net_class.py +1 -1
  87. pyedb/dotnet/database/nets.py +1 -1
  88. pyedb/dotnet/database/padstack.py +188 -2
  89. pyedb/dotnet/database/sim_setup_data/__init__.py +22 -0
  90. pyedb/dotnet/database/sim_setup_data/data/__init__.py +22 -0
  91. pyedb/dotnet/database/sim_setup_data/data/adaptive_frequency_data.py +1 -1
  92. pyedb/dotnet/database/sim_setup_data/data/mesh_operation.py +1 -1
  93. pyedb/dotnet/database/sim_setup_data/data/settings.py +1 -1
  94. pyedb/dotnet/database/sim_setup_data/data/sim_setup_info.py +1 -1
  95. pyedb/dotnet/database/sim_setup_data/data/simulation_settings.py +1 -1
  96. pyedb/dotnet/database/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
  97. pyedb/dotnet/database/sim_setup_data/data/sweep_data.py +1 -1
  98. pyedb/dotnet/database/sim_setup_data/io/__init__.py +21 -0
  99. pyedb/dotnet/database/sim_setup_data/io/siwave.py +1 -1
  100. pyedb/dotnet/database/siwave.py +1 -1
  101. pyedb/dotnet/database/stackup.py +1 -1
  102. pyedb/dotnet/database/utilities/__init__.py +22 -0
  103. pyedb/dotnet/database/utilities/heatsink.py +23 -0
  104. pyedb/dotnet/database/utilities/hfss_simulation_setup.py +1 -1
  105. pyedb/dotnet/database/utilities/obj_base.py +1 -1
  106. pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
  107. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +22 -0
  108. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +22 -0
  109. pyedb/dotnet/database/utilities/value.py +1 -1
  110. pyedb/dotnet/edb.py +119 -123
  111. pyedb/edb_logger.py +1 -1
  112. pyedb/exceptions.py +22 -0
  113. pyedb/extensions/__init__.py +21 -0
  114. pyedb/extensions/create_cell_array.py +1 -1
  115. pyedb/extensions/via_design_backend.py +22 -0
  116. pyedb/generic/__init__.py +21 -0
  117. pyedb/generic/constants.py +1 -1
  118. pyedb/generic/data_handlers.py +22 -0
  119. pyedb/generic/design_types.py +1 -1
  120. pyedb/generic/filesystem.py +22 -0
  121. pyedb/generic/general_methods.py +22 -1
  122. pyedb/generic/grpc_warnings.py +22 -0
  123. pyedb/generic/plot.py +22 -0
  124. pyedb/generic/process.py +29 -2
  125. pyedb/generic/settings.py +1 -1
  126. pyedb/grpc/__init__.py +21 -0
  127. pyedb/grpc/database/__init__.py +21 -0
  128. pyedb/grpc/database/_typing.py +21 -0
  129. pyedb/grpc/database/components.py +9 -8
  130. pyedb/grpc/database/control_file.py +1 -1
  131. pyedb/grpc/database/definition/__init__.py +21 -0
  132. pyedb/grpc/database/definition/component_def.py +1 -1
  133. pyedb/grpc/database/definition/component_model.py +1 -1
  134. pyedb/grpc/database/definition/component_pin.py +1 -1
  135. pyedb/grpc/database/definition/materials.py +2 -2
  136. pyedb/grpc/database/definition/n_port_component_model.py +1 -1
  137. pyedb/grpc/database/definition/package_def.py +1 -1
  138. pyedb/grpc/database/definition/padstack_def.py +17 -10
  139. pyedb/grpc/database/definitions.py +1 -1
  140. pyedb/grpc/database/general.py +1 -1
  141. pyedb/grpc/database/geometry/__init__.py +21 -0
  142. pyedb/grpc/database/geometry/arc_data.py +1 -1
  143. pyedb/grpc/database/geometry/point_3d_data.py +1 -1
  144. pyedb/grpc/database/geometry/point_data.py +1 -1
  145. pyedb/grpc/database/geometry/polygon_data.py +1 -1
  146. pyedb/grpc/database/hfss.py +1 -1
  147. pyedb/grpc/database/hierarchy/__init__.py +21 -0
  148. pyedb/grpc/database/hierarchy/component.py +1 -1
  149. pyedb/grpc/database/hierarchy/model.py +1 -1
  150. pyedb/grpc/database/hierarchy/netlist_model.py +1 -1
  151. pyedb/grpc/database/hierarchy/pin_pair_model.py +1 -1
  152. pyedb/grpc/database/hierarchy/pingroup.py +1 -1
  153. pyedb/grpc/database/hierarchy/s_parameter_model.py +1 -1
  154. pyedb/grpc/database/hierarchy/spice_model.py +1 -1
  155. pyedb/grpc/database/layers/__init__.py +21 -0
  156. pyedb/grpc/database/layers/layer.py +22 -0
  157. pyedb/grpc/database/layers/stackup_layer.py +1 -1
  158. pyedb/grpc/database/layout/__init__.py +21 -0
  159. pyedb/grpc/database/layout/cell.py +1 -1
  160. pyedb/grpc/database/layout/layout.py +1 -1
  161. pyedb/grpc/database/layout/voltage_regulator.py +1 -1
  162. pyedb/grpc/database/layout_validation.py +1 -1
  163. pyedb/grpc/database/modeler.py +31 -9
  164. pyedb/grpc/database/net/__init__.py +21 -0
  165. pyedb/grpc/database/net/differential_pair.py +1 -1
  166. pyedb/grpc/database/net/extended_net.py +1 -1
  167. pyedb/grpc/database/net/net.py +1 -1
  168. pyedb/grpc/database/net/net_class.py +1 -1
  169. pyedb/grpc/database/nets.py +1 -1
  170. pyedb/grpc/database/padstacks.py +209 -9
  171. pyedb/grpc/database/ports/__init__.py +21 -0
  172. pyedb/grpc/database/ports/ports.py +1 -1
  173. pyedb/grpc/database/primitive/__init__.py +22 -0
  174. pyedb/grpc/database/primitive/bondwire.py +1 -1
  175. pyedb/grpc/database/primitive/circle.py +1 -1
  176. pyedb/grpc/database/primitive/padstack_instance.py +111 -16
  177. pyedb/grpc/database/primitive/path.py +1 -1
  178. pyedb/grpc/database/primitive/polygon.py +6 -4
  179. pyedb/grpc/database/primitive/primitive.py +1 -6
  180. pyedb/grpc/database/primitive/rectangle.py +1 -1
  181. pyedb/grpc/database/simulation_setup/__init__.py +21 -0
  182. pyedb/grpc/database/simulation_setup/adaptive_frequency.py +1 -1
  183. pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +1 -1
  184. pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +1 -1
  185. pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +1 -1
  186. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
  187. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +1 -1
  188. pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +1 -1
  189. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +1 -1
  190. pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +1 -1
  191. pyedb/grpc/database/simulation_setup/mesh_operation.py +1 -1
  192. pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +1 -1
  193. pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +1 -1
  194. pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +1 -1
  195. pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +1 -1
  196. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +22 -0
  197. pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +1 -1
  198. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +1 -1
  199. pyedb/grpc/database/simulation_setup/sweep_data.py +1 -1
  200. pyedb/grpc/database/siwave.py +1 -1
  201. pyedb/grpc/database/source_excitations.py +1 -1
  202. pyedb/grpc/database/stackup.py +1 -1
  203. pyedb/grpc/database/terminal/__init__.py +21 -0
  204. pyedb/grpc/database/terminal/bundle_terminal.py +1 -1
  205. pyedb/grpc/database/terminal/edge_terminal.py +1 -1
  206. pyedb/grpc/database/terminal/padstack_instance_terminal.py +1 -1
  207. pyedb/grpc/database/terminal/pingroup_terminal.py +1 -1
  208. pyedb/grpc/database/terminal/point_terminal.py +1 -1
  209. pyedb/grpc/database/terminal/terminal.py +1 -1
  210. pyedb/grpc/database/utility/__init__.py +22 -0
  211. pyedb/grpc/database/utility/constants.py +1 -1
  212. pyedb/grpc/database/utility/heat_sink.py +1 -1
  213. pyedb/grpc/database/utility/hfss_extent_info.py +1 -1
  214. pyedb/grpc/database/utility/layout_statistics.py +1 -1
  215. pyedb/grpc/database/utility/rlc.py +1 -1
  216. pyedb/grpc/database/utility/sources.py +1 -1
  217. pyedb/grpc/database/utility/sweep_data_distribution.py +1 -1
  218. pyedb/grpc/database/utility/value.py +1 -1
  219. pyedb/grpc/database/utility/xml_control_file.py +1 -1
  220. pyedb/grpc/edb.py +230 -990
  221. pyedb/grpc/edb_init.py +1 -1
  222. pyedb/grpc/rpc_session.py +17 -4
  223. pyedb/ipc2581/__init__.py +21 -0
  224. pyedb/ipc2581/bom/__init__.py +21 -0
  225. pyedb/ipc2581/bom/bom.py +1 -1
  226. pyedb/ipc2581/bom/bom_item.py +1 -1
  227. pyedb/ipc2581/bom/characteristics.py +1 -1
  228. pyedb/ipc2581/bom/refdes.py +1 -1
  229. pyedb/ipc2581/content/__init__.py +21 -0
  230. pyedb/ipc2581/content/color.py +1 -1
  231. pyedb/ipc2581/content/content.py +1 -1
  232. pyedb/ipc2581/content/dictionary_color.py +1 -1
  233. pyedb/ipc2581/content/dictionary_fill.py +1 -1
  234. pyedb/ipc2581/content/dictionary_line.py +1 -1
  235. pyedb/ipc2581/content/entry_color.py +1 -1
  236. pyedb/ipc2581/content/entry_line.py +1 -1
  237. pyedb/ipc2581/content/fill.py +1 -1
  238. pyedb/ipc2581/content/layer_ref.py +1 -1
  239. pyedb/ipc2581/content/standard_geometries_dictionary.py +1 -1
  240. pyedb/ipc2581/ecad/__init__.py +21 -0
  241. pyedb/ipc2581/ecad/cad_data/__init__.py +21 -0
  242. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +1 -1
  243. pyedb/ipc2581/ecad/cad_data/cad_data.py +1 -1
  244. pyedb/ipc2581/ecad/cad_data/component.py +1 -1
  245. pyedb/ipc2581/ecad/cad_data/drill.py +1 -1
  246. pyedb/ipc2581/ecad/cad_data/feature.py +1 -1
  247. pyedb/ipc2581/ecad/cad_data/layer.py +1 -1
  248. pyedb/ipc2581/ecad/cad_data/layer_feature.py +1 -1
  249. pyedb/ipc2581/ecad/cad_data/logical_net.py +1 -1
  250. pyedb/ipc2581/ecad/cad_data/outline.py +1 -1
  251. pyedb/ipc2581/ecad/cad_data/package.py +1 -1
  252. pyedb/ipc2581/ecad/cad_data/padstack_def.py +1 -1
  253. pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +1 -1
  254. pyedb/ipc2581/ecad/cad_data/padstack_instance.py +1 -1
  255. pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +1 -1
  256. pyedb/ipc2581/ecad/cad_data/path.py +1 -1
  257. pyedb/ipc2581/ecad/cad_data/phy_net.py +1 -1
  258. pyedb/ipc2581/ecad/cad_data/pin.py +1 -1
  259. pyedb/ipc2581/ecad/cad_data/polygon.py +1 -1
  260. pyedb/ipc2581/ecad/cad_data/profile.py +1 -1
  261. pyedb/ipc2581/ecad/cad_data/stackup.py +1 -1
  262. pyedb/ipc2581/ecad/cad_data/stackup_group.py +1 -1
  263. pyedb/ipc2581/ecad/cad_data/stackup_layer.py +1 -1
  264. pyedb/ipc2581/ecad/cad_data/step.py +1 -1
  265. pyedb/ipc2581/ecad/cad_header.py +1 -1
  266. pyedb/ipc2581/ecad/ecad.py +1 -1
  267. pyedb/ipc2581/ecad/spec.py +1 -1
  268. pyedb/ipc2581/history_record.py +1 -1
  269. pyedb/ipc2581/ipc2581.py +1 -1
  270. pyedb/ipc2581/logistic_header.py +1 -1
  271. pyedb/libraries/common.py +1 -1
  272. pyedb/libraries/rf_libraries/base_functions.py +1 -1
  273. pyedb/libraries/rf_libraries/planar_antennas.py +1 -1
  274. pyedb/misc/__init__.py +21 -0
  275. pyedb/misc/aedtlib_personalib_install.py +1 -1
  276. pyedb/misc/decorators.py +22 -0
  277. pyedb/misc/downloads.py +1 -1
  278. pyedb/misc/misc.py +1 -1
  279. pyedb/misc/siw_feature_config/__init__.py +21 -0
  280. pyedb/misc/siw_feature_config/emc/__init__.py +21 -0
  281. pyedb/misc/siw_feature_config/emc/component_tags.py +22 -0
  282. pyedb/misc/siw_feature_config/emc/net_tags.py +22 -0
  283. pyedb/misc/siw_feature_config/emc/tag_library.py +22 -0
  284. pyedb/misc/siw_feature_config/emc/xml_generic.py +22 -0
  285. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +1 -1
  286. pyedb/misc/siw_feature_config/xtalk_scan/fd_xtalk_scan_config.py +1 -1
  287. pyedb/misc/siw_feature_config/xtalk_scan/impedance_scan_config.py +1 -1
  288. pyedb/misc/siw_feature_config/xtalk_scan/net.py +1 -1
  289. pyedb/misc/siw_feature_config/xtalk_scan/pins.py +1 -1
  290. pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +1 -1
  291. pyedb/misc/siw_feature_config/xtalk_scan/td_xtalk_config.py +1 -1
  292. pyedb/misc/utilities.py +1 -1
  293. pyedb/modeler/geometry_operators.py +22 -0
  294. pyedb/siwave.py +22 -0
  295. pyedb/siwave_core/__init__.py +21 -0
  296. pyedb/siwave_core/cpa/__init__.py +21 -0
  297. pyedb/siwave_core/cpa/simulation_setup_data_model.py +22 -0
  298. pyedb/siwave_core/icepak.py +1 -1
  299. pyedb/siwave_core/product_properties.py +23 -0
  300. pyedb/workflow.py +22 -0
  301. pyedb/workflows/__init__.py +21 -0
  302. pyedb/workflows/job_manager/__init__.py +21 -0
  303. pyedb/workflows/job_manager/backend/__init__.py +21 -0
  304. pyedb/workflows/job_manager/backend/job_manager_handler.py +910 -0
  305. pyedb/workflows/job_manager/backend/job_submission.py +1169 -0
  306. pyedb/workflows/job_manager/backend/service.py +1663 -0
  307. pyedb/workflows/job_manager/backend/start_service.py +86 -0
  308. pyedb/workflows/job_manager/backend/submit_job_on_scheduler.py +168 -0
  309. pyedb/workflows/job_manager/backend/submit_local_job.py +166 -0
  310. pyedb/workflows/sipi/hfss_auto_configuration.py +1 -1
  311. pyedb/workflows/utilities/__init__.py +21 -0
  312. pyedb/workflows/utilities/cutout.py +1428 -0
  313. pyedb/workflows/utilities/hfss_log_parser.py +446 -0
  314. {pyedb-0.59.0.dist-info → pyedb-0.61.0.dist-info}/METADATA +7 -4
  315. pyedb-0.61.0.dist-info/RECORD +318 -0
  316. {pyedb-0.59.0.dist-info → pyedb-0.61.0.dist-info}/licenses/LICENSE +7 -7
  317. pyedb-0.59.0.dist-info/RECORD +0 -306
  318. {pyedb-0.59.0.dist-info → pyedb-0.61.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,446 @@
1
+ # Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from dataclasses import dataclass
27
+ import math
28
+ from pathlib import Path
29
+ import re
30
+ from typing import Any, Dict, List, Optional
31
+
32
+
33
+ def _to_hz(text: str) -> float:
34
+ """
35
+ Convert a human-readable frequency string to hertz.
36
+
37
+ :param text: Frequency expression such as ``'3 GHz'``, ``'100 kHz'``, ``'10MHz'``.
38
+ :type text: str
39
+ :return: Numerical value in Hz. Returns :py:const:`math.nan` if the string
40
+ cannot be parsed.
41
+ :rtype: float
42
+ """
43
+ m = re.match(r"(?P<val>[\d.]+)\s*(?P<unit>[kMG]?Hz)", text, re.I)
44
+ if not m:
45
+ return math.nan
46
+ val, unit = float(m["val"]), m["unit"].lower()
47
+ scale = {"hz": 1, "khz": 1e3, "mhz": 1e6, "ghz": 1e9}
48
+ return val * scale[unit]
49
+
50
+
51
+ def _to_sec(mm_ss: str) -> int:
52
+ """
53
+ Convert an ANSYS time stamp to seconds.
54
+
55
+ Accepts ``MM:SS``, ``H:MM:SS`` or ``HH:MM:SS``.
56
+
57
+ :param mm_ss: Time stamp extracted from the log.
58
+ :type mm_ss: str
59
+ :return: Total elapsed seconds.
60
+ :rtype: int
61
+ """
62
+ parts = mm_ss.strip().split(":")
63
+ if len(parts) == 2: # MM:SS
64
+ return int(parts[0]) * 60 + int(parts[1])
65
+ if len(parts) == 3: # H:MM:SS or HH:MM:SS
66
+ return int(parts[0]) * 3600 + int(parts[1]) * 60 + int(parts[2])
67
+ return 0
68
+
69
+
70
+ def _as_dict(obj: Any) -> Any:
71
+ """Recursively convert dataclasses / lists / primitives to plain Python types."""
72
+ if hasattr(obj, "__dataclass_fields__"):
73
+ return {f: _as_dict(getattr(obj, f)) for f in obj.__dataclass_fields__}
74
+ if isinstance(obj, list):
75
+ return [_as_dict(i) for i in obj]
76
+ if isinstance(obj, Path):
77
+ return str(obj)
78
+ return obj
79
+
80
+
81
+ @dataclass(slots=True)
82
+ class ProjectInfo:
83
+ """
84
+ Basic meta-data extracted from the header of an HFSS batch log.
85
+
86
+ :ivar str name: Project name (without extension).
87
+ :ivar ~pathlib.Path file: Full path to the project file.
88
+ :ivar str design: Active design name (may be empty).
89
+ :ivar str user: OS user that launched the solve.
90
+ :ivar str cmd_line: Exact command line used for the run.
91
+ """
92
+
93
+ name: str
94
+ file: Path
95
+ design: str = ""
96
+ user: str = ""
97
+ cmd_line: str = ""
98
+
99
+
100
+ @dataclass(slots=True)
101
+ class InitMesh:
102
+ """
103
+ Statistics reported during the initial tetrahedral meshing phase.
104
+
105
+ :ivar int tetrahedra: Number of tetrahedra created.
106
+ :ivar float memory_mb: Peak memory consumption in megabytes.
107
+ :ivar int real_time_sec: Wall clock time in seconds.
108
+ :ivar int cpu_time_sec: CPU time in seconds.
109
+ """
110
+
111
+ tetrahedra: int
112
+ memory_mb: float
113
+ real_time_sec: int
114
+ cpu_time_sec: int
115
+
116
+
117
+ @dataclass(slots=True)
118
+ class AdaptivePass:
119
+ """
120
+ Single adaptive solution pass (frequency, delta-S, memory, …).
121
+
122
+ :ivar int pass_nr: 1-based pass index.
123
+ :ivar float freq_hz: Target frequency in hertz.
124
+ :ivar int tetrahedra: Number of tetrahedra at *end* of pass.
125
+ :ivar int matrix_size: Order of the FEM matrix.
126
+ :ivar float memory_mb: Memory used in megabytes.
127
+ :ivar float delta_s: Maximum |ΔS| observed (``None`` until reported).
128
+ :ivar bool converged: ``True`` if this pass triggered convergence.
129
+ :ivar int elapsed_sec: Wall time spent in this pass.
130
+ """
131
+
132
+ pass_nr: int
133
+ freq_hz: float
134
+ tetrahedra: int
135
+ matrix_size: int
136
+ memory_mb: float
137
+ delta_s: Optional[float]
138
+ converged: bool
139
+ elapsed_sec: int
140
+
141
+
142
+ @dataclass(slots=True)
143
+ class Sweep:
144
+ """
145
+ Frequency-sweep summary block.
146
+
147
+ :ivar str type: Sweep algorithm: ``Interpolating``, ``Discrete`` or ``Fast``.
148
+ :ivar int frequencies: Total number of frequency points requested.
149
+ :ivar list[float] solved: List of frequencies (Hz) actually solved.
150
+ :ivar int elapsed_sec: Wall clock time for the entire sweep.
151
+ """
152
+
153
+ type: str
154
+ frequencies: int
155
+ solved: List[float]
156
+ elapsed_sec: int
157
+
158
+
159
+ class BlockParser:
160
+ """Base class for a single block parser."""
161
+
162
+ def __init__(self, lines: List[str]) -> None:
163
+ self.lines = lines
164
+
165
+ def parse(self) -> Any:
166
+ raise NotImplementedError
167
+
168
+
169
+ class ProjectBlockParser(BlockParser):
170
+ """
171
+ Extract project meta-data from the log header.
172
+
173
+ Example::
174
+
175
+ >>> block = ProjectBlockParser(lines)
176
+ >>> info = block.parse()
177
+ >>> info.name
178
+ 'Patch_Antenna'
179
+ """
180
+
181
+ def parse(self) -> ProjectInfo:
182
+ """
183
+ Parse the stored lines and return a :class:`ProjectInfo` instance.
184
+
185
+ :return: Populated data object.
186
+ :rtype: ProjectInfo
187
+ :raises ValueError: If mandatory fields (project name or file path)
188
+ cannot be located.
189
+ """
190
+ proj, design, user, cmd = "", "", "", ""
191
+ for line in self.lines:
192
+ if m := re.search(r"Project:(?P<proj>[^,]+),\s*Design:(?P<des>[^,]+)", line):
193
+ proj, design = m["proj"].strip(), m["des"].strip()
194
+ if m := re.search(r"Running as user\s*:\s*(?P<user>.+)", line):
195
+ user = m["user"].strip()
196
+ if m := re.search(r'Using command line:\s*(?P<cmd>".+")', line):
197
+ cmd = m["cmd"]
198
+ # file is the batch-solve argument
199
+ file = Path(re.search(r"Batch Solve/Save:\s*(?P<file>.+)", "\n".join(self.lines))["file"])
200
+ return ProjectInfo(name=proj, file=file, design=design, user=user, cmd_line=cmd)
201
+
202
+
203
+ class InitMeshBlockParser(BlockParser):
204
+ def parse(self) -> InitMesh:
205
+ tet = mem = rt = ct = None
206
+ for idx, line in enumerate(self.lines):
207
+ if "[PROFILE] Initial Meshing" in line:
208
+ # scan forward up to 10 lines for the pieces
209
+ for future in self.lines[idx : idx + 10]:
210
+ if m := re.search(r"Tetrahedra: (?P<tet>\d+)", future):
211
+ tet = int(m["tet"])
212
+ if m := re.search(r"Memory (?P<mem>[\d.]+) M", future):
213
+ mem = float(m["mem"])
214
+ if m := re.search(r"Real Time (?P<rt>[\d:]+)", future):
215
+ rt = _to_sec(m["rt"])
216
+ if m := re.search(r"CPU Time (?P<ct>[\d:]+)", future):
217
+ ct = _to_sec(m["ct"])
218
+ if all(v is not None for v in (tet, mem, rt, ct)):
219
+ return InitMesh(tetrahedra=tet, memory_mb=mem, real_time_sec=rt, cpu_time_sec=ct)
220
+ break
221
+ raise ValueError("Initial mesh block not found")
222
+
223
+
224
+ class AdaptiveBlockParser(BlockParser):
225
+ """
226
+ Build a list of :class:`AdaptivePass` objects from the adaptive section.
227
+ """
228
+
229
+ def parse(self) -> List[AdaptivePass]:
230
+ """
231
+ Parse every adaptive pass and determine which one triggered convergence.
232
+
233
+ :return: Ordered list of passes (pass_nr always increases).
234
+ :rtype: list[AdaptivePass]
235
+ """
236
+ passes: List[AdaptivePass] = []
237
+ current: Optional[AdaptivePass] = None
238
+ last_converge_pass: Optional[int] = None
239
+ adaptive_converged_line_found = False
240
+
241
+ for lineno, line in enumerate(self.lines, 1):
242
+ # ---- Check for "Adaptive Passes converged" literal string (check every line) ----
243
+ if "Adaptive Passes converged" in line:
244
+ adaptive_converged_line_found = True
245
+
246
+ # ---- new adaptive pass ----------------------------------
247
+ if m := re.search(r"Adaptive Pass (?P<n>\d+).*Frequency: (?P<f>[\d.kMGHz]+)", line, re.I):
248
+ current = AdaptivePass(
249
+ pass_nr=int(m["n"]),
250
+ freq_hz=_to_hz(m["f"]),
251
+ tetrahedra=0,
252
+ matrix_size=0,
253
+ memory_mb=0.0,
254
+ delta_s=None,
255
+ converged=False,
256
+ elapsed_sec=0,
257
+ )
258
+
259
+ if not current:
260
+ continue
261
+
262
+ # ---- collect details ------------------------------------
263
+ if m := re.search(r"Tetrahedra: (?P<tet>\d+)", line):
264
+ current.tetrahedra = int(m["tet"])
265
+ if m := re.search(r"Matrix size: (?P<sz>\d+)", line):
266
+ current.matrix_size = int(m["sz"])
267
+ if m := re.search(r"Memory (?P<mem>[\d.]+) M", line):
268
+ current.memory_mb = float(m["mem"])
269
+ if m := re.search(r"Max Mag\. Delta S:\s*(?P<ds>[\d.]+)", line):
270
+ current.delta_s = float(m["ds"])
271
+ if m := re.search(r"Elapsed time.*:\s*(?P<et>[\d:]+)", line):
272
+ current.elapsed_sec = _to_sec(m["et"])
273
+
274
+ # ---- store pass when [CONVERGE] appears -----------------
275
+ if m := re.search(r"\[CONVERGE].*pass number\D+(?P<n>\d+)", line, re.I):
276
+ passes.append(current)
277
+ last_converge_pass = int(m["n"])
278
+ current = None
279
+
280
+ # ---- final decision ----------------------------------------
281
+ if adaptive_converged_line_found and last_converge_pass is not None:
282
+ for p in passes:
283
+ p.converged = p.pass_nr == last_converge_pass
284
+ return passes
285
+
286
+
287
+ class SweepBlockParser(BlockParser):
288
+ """
289
+ Extract frequency-sweep summary (if present).
290
+ """
291
+
292
+ def parse(self) -> Optional[Sweep]:
293
+ """
294
+ Return sweep information or ``None`` if the log contains no sweep block.
295
+
296
+ :return: Sweep summary object.
297
+ :rtype: Sweep | None
298
+ """
299
+ sweep_type, freqs, solved, elapsed = "", 0, [], 0
300
+ for line in self.lines:
301
+ if m := re.search(r"Interpolating|Discrete|Fast", line):
302
+ sweep_type = m.group(0)
303
+ if m := re.search(r"(?P<n>\d+)\s*Frequencies", line):
304
+ freqs = int(m["n"])
305
+ if m := re.search(r"Frequency - (?P<f>[\d.kMGHz]+)", line, re.I):
306
+ solved.append(_to_hz(m["f"]))
307
+ if m := re.search(r"Elapsed time.*:\s*(?P<et>[\d:]+)", line):
308
+ elapsed = _to_sec(m["et"])
309
+ if freqs:
310
+ return Sweep(type=sweep_type or "Interpolating", frequencies=freqs, solved=solved, elapsed_sec=elapsed)
311
+ return None
312
+
313
+
314
+ class HFSSLogParser:
315
+ """
316
+ High-level façade that orchestrates all block parsers.
317
+
318
+ Typical usage::
319
+
320
+ >>> log = HFSSLogParser("/tmp/project.aedt.batchinfo.1234/hfss.log")
321
+ >>> data = log.parse()
322
+ >>> data.is_converged()
323
+ True
324
+ """
325
+
326
+ BLOCK_MAP: Dict[str, type[BlockParser]] = {
327
+ "project": ProjectBlockParser,
328
+ "init_mesh": InitMeshBlockParser,
329
+ "adaptive": AdaptiveBlockParser,
330
+ "sweep": SweepBlockParser,
331
+ }
332
+
333
+ def __init__(self, log_path: str | Path):
334
+ self.path = Path(log_path)
335
+
336
+ def parse(self) -> ParsedLog:
337
+ """
338
+ Execute all sub-parsers and return a unified object.
339
+
340
+ :return: Structured representation of the entire log.
341
+ :rtype: ParsedLog
342
+ :raises FileNotFoundError: If *log_path* does not exist.
343
+ :raises ValueError: If a mandatory block cannot be parsed.
344
+ """
345
+ text = self.path.read_text(encoding="utf-8", errors="ignore")
346
+ lines = text.splitlines()
347
+
348
+ project = ProjectBlockParser(lines).parse()
349
+ init_mesh = InitMeshBlockParser(lines).parse()
350
+ adaptive = AdaptiveBlockParser(lines).parse()
351
+ sweep = SweepBlockParser(lines).parse()
352
+
353
+ return ParsedLog(
354
+ project=project,
355
+ init_mesh=init_mesh,
356
+ adaptive=adaptive,
357
+ sweep=sweep,
358
+ )
359
+
360
+
361
+ @dataclass(slots=True)
362
+ class ParsedLog:
363
+ """
364
+ Root container returned by :meth:`HFSSLogParser.parse`.
365
+
366
+ :ivar ProjectInfo project: Project meta-data.
367
+ :ivar InitMesh init_mesh: Initial-mesh metrics.
368
+ :ivar list[AdaptivePass] adaptive: Adaptive passes in chronological order.
369
+ :ivar Sweep | None sweep: Frequency-sweep summary (``None`` if absent).
370
+ """
371
+
372
+ project: ProjectInfo
373
+ init_mesh: InitMesh
374
+ adaptive: List[AdaptivePass]
375
+ sweep: Optional[Sweep]
376
+
377
+ def to_dict(self) -> dict:
378
+ """
379
+ Deep-convert the entire object to JSON-serialisable primitives.
380
+
381
+ :return: Plain ``dict`` / ``list`` / scalar structure.
382
+ :rtype: dict[str, Any]
383
+ """
384
+ return _as_dict(self)
385
+
386
+ def is_converged(self) -> bool:
387
+ """
388
+ Return ``True`` if the adaptive solver declared convergence.
389
+
390
+ :rtype: bool
391
+ """
392
+ return self.adaptive[-1].converged if self.adaptive else False
393
+
394
+ def adaptive_passes(self) -> List[AdaptivePass]:
395
+ """Alias to keep API explicit."""
396
+ return self.adaptive
397
+
398
+ def memory_on_convergence(self) -> float:
399
+ """
400
+ Memory (MB) consumed by the *last* converged adaptive pass.
401
+
402
+ :return: Megabytes, or :py:const:`math.nan` if no pass converged.
403
+ :rtype: float
404
+ """
405
+ for p in reversed(self.adaptive):
406
+ if p.converged:
407
+ return p.memory_mb
408
+ return math.nan
409
+
410
+ def is_completed(self) -> bool:
411
+ """
412
+ Heuristic indicating a successful end-to-end solve.
413
+
414
+ A simulation is considered complete when **both** of the following
415
+ conditions are satisfied:
416
+
417
+ 1. At least one adaptive pass converged.
418
+ 2. A frequency-sweep block exists with elapsed time greater than zero.
419
+
420
+ :rtype: bool
421
+ """
422
+ return self.is_converged() and self.sweep is not None and self.sweep.elapsed_sec > 0
423
+
424
+ def errors(self) -> List[str]:
425
+ """
426
+ Extract only **error** lines (warnings are ignored).
427
+
428
+ ANSYS marks errors with ``[error]`` or ``*** ERROR ***``.
429
+
430
+ :return: List of stripped error lines (empty if none).
431
+ :rtype: list[str]
432
+ """
433
+ errs: List[str] = []
434
+ # we keep the raw lines inside the ProjectBlockParser – expose them
435
+ raw = self._raw_lines # added below
436
+ for line in raw:
437
+ if re.search(r"\[error\]|\*\*\* ERROR \*\*\*", line, re.I):
438
+ errs.append(line.strip())
439
+ return errs
440
+
441
+ @property
442
+ def _raw_lines(self) -> List[str]:
443
+ # cache lazily
444
+ if not hasattr(self, "__raw"):
445
+ self.__raw = self.project.file.with_suffix(".log").read_text(encoding="utf-8", errors="ignore").splitlines()
446
+ return self.__raw
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyedb
3
- Version: 0.59.0
3
+ Version: 0.61.0
4
4
  Summary: Higher-Level Pythonic Ansys Electronics Data Base
5
5
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
6
6
  Maintainer-email: PyEDB developers <simon.vandenbrouck@ansys.com>
@@ -22,7 +22,7 @@ Requires-Dist: ansys-pythonnet >= 3.1.0rc4
22
22
  Requires-Dist: dotnetcore2 ==3.1.23;platform_system=='Linux'
23
23
  Requires-Dist: numpy>=1.20.0,<3
24
24
  Requires-Dist: pandas>=1.1.0,<2.4
25
- Requires-Dist: pydantic>=2.6.4,<2.12
25
+ Requires-Dist: pydantic>=2.6.4,<2.13
26
26
  Requires-Dist: Rtree >= 1.2.0
27
27
  Requires-Dist: toml == 0.10.2
28
28
  Requires-Dist: shapely
@@ -31,15 +31,18 @@ Requires-Dist: ansys-edb-core>=0.2.0
31
31
  Requires-Dist: psutil
32
32
  Requires-Dist: defusedxml>=0.7,<8.0
33
33
  Requires-Dist: matplotlib>=3.5.0,<3.11
34
+ Requires-Dist: aiohttp>=3.8
35
+ Requires-Dist: python-socketio>=5.10
36
+ Requires-Dist: requests>=2.32,<3.0
34
37
  Requires-Dist: ansys-sphinx-theme>=1.0.0,<1.5 ; extra == "doc"
35
38
  Requires-Dist: imageio>=2.30.0,<2.38 ; extra == "doc"
36
39
  Requires-Dist: ipython>=8.13.0,<8.32 ; extra == "doc"
37
40
  Requires-Dist: jupyterlab>=4.0.0,<4.5 ; extra == "doc"
38
- Requires-Dist: jupytext>=1.16.0,<1.18 ; extra == "doc"
41
+ Requires-Dist: jupytext>=1.16.0,<1.19 ; extra == "doc"
39
42
  Requires-Dist: matplotlib>=3.5.0,<3.11 ; extra == "doc"
40
43
  Requires-Dist: nbsphinx>=0.9.0,<0.10 ; extra == "doc"
41
44
  Requires-Dist: nbconvert < 7.17 ; extra == "doc"
42
- Requires-Dist: numpydoc>=1.5.0,<1.9 ; extra == "doc"
45
+ Requires-Dist: numpydoc==1.5.0 ; extra == "doc"
43
46
  Requires-Dist: pypandoc>=1.10.0,<1.16 ; extra == "doc"
44
47
  Requires-Dist: recommonmark ; extra == "doc"
45
48
  Requires-Dist: Sphinx>=7.1.0,<8.2 ; extra == "doc"