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.
- pyedb/__init__.py +23 -1
- pyedb/common/__init__.py +21 -0
- pyedb/common/nets.py +22 -0
- pyedb/component_libraries/ansys_components.py +22 -0
- pyedb/configuration/__init__.py +21 -0
- pyedb/configuration/cfg_boundaries.py +1 -1
- pyedb/configuration/cfg_common.py +1 -1
- pyedb/configuration/cfg_components.py +36 -8
- pyedb/configuration/cfg_data.py +1 -1
- pyedb/configuration/cfg_general.py +1 -1
- pyedb/configuration/cfg_modeler.py +1 -1
- pyedb/configuration/cfg_nets.py +1 -1
- pyedb/configuration/cfg_operations.py +1 -1
- pyedb/configuration/cfg_package_definition.py +1 -1
- pyedb/configuration/cfg_padstacks.py +1 -1
- pyedb/configuration/cfg_pin_groups.py +1 -1
- pyedb/configuration/cfg_ports_sources.py +3 -2
- pyedb/configuration/cfg_s_parameter_models.py +1 -1
- pyedb/configuration/cfg_setup.py +5 -1
- pyedb/configuration/cfg_spice_models.py +1 -1
- pyedb/configuration/cfg_stackup.py +1 -1
- pyedb/configuration/cfg_terminals.py +22 -0
- pyedb/configuration/configuration.py +6 -5
- pyedb/dotnet/__init__.py +21 -0
- pyedb/dotnet/clr_module.py +22 -0
- pyedb/dotnet/database/Variables.py +1 -1
- pyedb/dotnet/database/__init__.py +22 -0
- pyedb/dotnet/database/cell/__init__.py +21 -0
- pyedb/dotnet/database/cell/connectable.py +1 -1
- pyedb/dotnet/database/cell/hierarchy/__init__.py +21 -0
- pyedb/dotnet/database/cell/hierarchy/component.py +9 -7
- pyedb/dotnet/database/cell/hierarchy/hierarchy_obj.py +1 -1
- pyedb/dotnet/database/cell/hierarchy/model.py +2 -29
- pyedb/dotnet/database/cell/hierarchy/netlist_model.py +1 -1
- pyedb/dotnet/database/cell/hierarchy/pin_pair_model.py +1 -1
- pyedb/dotnet/database/cell/hierarchy/s_parameter_model.py +11 -15
- pyedb/dotnet/database/cell/hierarchy/spice_model.py +14 -8
- pyedb/dotnet/database/cell/layout.py +5 -4
- pyedb/dotnet/database/cell/layout_obj.py +1 -1
- pyedb/dotnet/database/cell/primitive/__init__.py +22 -0
- pyedb/dotnet/database/cell/primitive/bondwire.py +1 -1
- pyedb/dotnet/database/cell/primitive/path.py +1 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +1 -1
- pyedb/dotnet/database/cell/terminal/__init__.py +21 -0
- pyedb/dotnet/database/cell/terminal/bundle_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/edge_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/padstack_instance_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +7 -2
- pyedb/dotnet/database/cell/voltage_regulator.py +1 -1
- pyedb/dotnet/database/components.py +6 -2
- pyedb/dotnet/database/definition/__init__.py +21 -0
- pyedb/dotnet/database/definition/component_def.py +1 -1
- pyedb/dotnet/database/definition/component_model.py +1 -1
- pyedb/dotnet/database/definition/definition_obj.py +1 -1
- pyedb/dotnet/database/definition/definitions.py +1 -1
- pyedb/dotnet/database/definition/package_def.py +1 -1
- pyedb/dotnet/database/dotnet/__init__.py +21 -0
- pyedb/dotnet/database/dotnet/database.py +1 -1
- pyedb/dotnet/database/dotnet/primitive.py +1 -1
- pyedb/dotnet/database/edb_data/__init__.py +21 -0
- pyedb/dotnet/database/edb_data/control_file.py +1 -1
- pyedb/dotnet/database/edb_data/design_options.py +1 -1
- pyedb/dotnet/database/edb_data/edbvalue.py +1 -1
- pyedb/dotnet/database/edb_data/hfss_extent_info.py +1 -1
- pyedb/dotnet/database/edb_data/layer_data.py +1 -1
- pyedb/dotnet/database/edb_data/nets_data.py +1 -1
- pyedb/dotnet/database/edb_data/padstacks_data.py +6 -4
- pyedb/dotnet/database/edb_data/ports.py +1 -1
- pyedb/dotnet/database/edb_data/primitives_data.py +1 -1
- pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +1 -1
- pyedb/dotnet/database/edb_data/simulation_configuration.py +1 -1
- pyedb/dotnet/database/edb_data/sources.py +1 -1
- pyedb/dotnet/database/edb_data/utilities.py +1 -1
- pyedb/dotnet/database/edb_data/variables.py +1 -1
- pyedb/dotnet/database/general.py +1 -1
- pyedb/dotnet/database/geometry/__init__.py +21 -0
- pyedb/dotnet/database/geometry/point_data.py +1 -1
- pyedb/dotnet/database/geometry/polygon_data.py +1 -1
- pyedb/dotnet/database/hfss.py +1 -1
- pyedb/dotnet/database/layout_obj_instance.py +1 -1
- pyedb/dotnet/database/layout_validation.py +1 -1
- pyedb/dotnet/database/materials.py +1 -1
- pyedb/dotnet/database/modeler.py +3 -2
- pyedb/dotnet/database/net_class.py +1 -1
- pyedb/dotnet/database/nets.py +1 -1
- pyedb/dotnet/database/padstack.py +188 -2
- pyedb/dotnet/database/sim_setup_data/__init__.py +22 -0
- pyedb/dotnet/database/sim_setup_data/data/__init__.py +22 -0
- pyedb/dotnet/database/sim_setup_data/data/adaptive_frequency_data.py +1 -1
- pyedb/dotnet/database/sim_setup_data/data/mesh_operation.py +1 -1
- pyedb/dotnet/database/sim_setup_data/data/settings.py +1 -1
- pyedb/dotnet/database/sim_setup_data/data/sim_setup_info.py +1 -1
- pyedb/dotnet/database/sim_setup_data/data/simulation_settings.py +1 -1
- pyedb/dotnet/database/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
- pyedb/dotnet/database/sim_setup_data/data/sweep_data.py +1 -1
- pyedb/dotnet/database/sim_setup_data/io/__init__.py +21 -0
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +1 -1
- pyedb/dotnet/database/siwave.py +1 -1
- pyedb/dotnet/database/stackup.py +1 -1
- pyedb/dotnet/database/utilities/__init__.py +22 -0
- pyedb/dotnet/database/utilities/heatsink.py +23 -0
- pyedb/dotnet/database/utilities/hfss_simulation_setup.py +1 -1
- pyedb/dotnet/database/utilities/obj_base.py +1 -1
- pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +22 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +22 -0
- pyedb/dotnet/database/utilities/value.py +1 -1
- pyedb/dotnet/edb.py +119 -123
- pyedb/edb_logger.py +1 -1
- pyedb/exceptions.py +22 -0
- pyedb/extensions/__init__.py +21 -0
- pyedb/extensions/create_cell_array.py +1 -1
- pyedb/extensions/via_design_backend.py +22 -0
- pyedb/generic/__init__.py +21 -0
- pyedb/generic/constants.py +1 -1
- pyedb/generic/data_handlers.py +22 -0
- pyedb/generic/design_types.py +1 -1
- pyedb/generic/filesystem.py +22 -0
- pyedb/generic/general_methods.py +22 -1
- pyedb/generic/grpc_warnings.py +22 -0
- pyedb/generic/plot.py +22 -0
- pyedb/generic/process.py +29 -2
- pyedb/generic/settings.py +1 -1
- pyedb/grpc/__init__.py +21 -0
- pyedb/grpc/database/__init__.py +21 -0
- pyedb/grpc/database/_typing.py +21 -0
- pyedb/grpc/database/components.py +9 -8
- pyedb/grpc/database/control_file.py +1 -1
- pyedb/grpc/database/definition/__init__.py +21 -0
- pyedb/grpc/database/definition/component_def.py +1 -1
- pyedb/grpc/database/definition/component_model.py +1 -1
- pyedb/grpc/database/definition/component_pin.py +1 -1
- pyedb/grpc/database/definition/materials.py +2 -2
- pyedb/grpc/database/definition/n_port_component_model.py +1 -1
- pyedb/grpc/database/definition/package_def.py +1 -1
- pyedb/grpc/database/definition/padstack_def.py +17 -10
- pyedb/grpc/database/definitions.py +1 -1
- pyedb/grpc/database/general.py +1 -1
- pyedb/grpc/database/geometry/__init__.py +21 -0
- pyedb/grpc/database/geometry/arc_data.py +1 -1
- pyedb/grpc/database/geometry/point_3d_data.py +1 -1
- pyedb/grpc/database/geometry/point_data.py +1 -1
- pyedb/grpc/database/geometry/polygon_data.py +1 -1
- pyedb/grpc/database/hfss.py +1 -1
- pyedb/grpc/database/hierarchy/__init__.py +21 -0
- pyedb/grpc/database/hierarchy/component.py +1 -1
- pyedb/grpc/database/hierarchy/model.py +1 -1
- pyedb/grpc/database/hierarchy/netlist_model.py +1 -1
- pyedb/grpc/database/hierarchy/pin_pair_model.py +1 -1
- pyedb/grpc/database/hierarchy/pingroup.py +1 -1
- pyedb/grpc/database/hierarchy/s_parameter_model.py +1 -1
- pyedb/grpc/database/hierarchy/spice_model.py +1 -1
- pyedb/grpc/database/layers/__init__.py +21 -0
- pyedb/grpc/database/layers/layer.py +22 -0
- pyedb/grpc/database/layers/stackup_layer.py +1 -1
- pyedb/grpc/database/layout/__init__.py +21 -0
- pyedb/grpc/database/layout/cell.py +1 -1
- pyedb/grpc/database/layout/layout.py +1 -1
- pyedb/grpc/database/layout/voltage_regulator.py +1 -1
- pyedb/grpc/database/layout_validation.py +1 -1
- pyedb/grpc/database/modeler.py +31 -9
- pyedb/grpc/database/net/__init__.py +21 -0
- pyedb/grpc/database/net/differential_pair.py +1 -1
- pyedb/grpc/database/net/extended_net.py +1 -1
- pyedb/grpc/database/net/net.py +1 -1
- pyedb/grpc/database/net/net_class.py +1 -1
- pyedb/grpc/database/nets.py +1 -1
- pyedb/grpc/database/padstacks.py +209 -9
- pyedb/grpc/database/ports/__init__.py +21 -0
- pyedb/grpc/database/ports/ports.py +1 -1
- pyedb/grpc/database/primitive/__init__.py +22 -0
- pyedb/grpc/database/primitive/bondwire.py +1 -1
- pyedb/grpc/database/primitive/circle.py +1 -1
- pyedb/grpc/database/primitive/padstack_instance.py +111 -16
- pyedb/grpc/database/primitive/path.py +1 -1
- pyedb/grpc/database/primitive/polygon.py +6 -4
- pyedb/grpc/database/primitive/primitive.py +1 -6
- pyedb/grpc/database/primitive/rectangle.py +1 -1
- pyedb/grpc/database/simulation_setup/__init__.py +21 -0
- pyedb/grpc/database/simulation_setup/adaptive_frequency.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/mesh_operation.py +1 -1
- pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +1 -1
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +22 -0
- pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +1 -1
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +1 -1
- pyedb/grpc/database/simulation_setup/sweep_data.py +1 -1
- pyedb/grpc/database/siwave.py +1 -1
- pyedb/grpc/database/source_excitations.py +1 -1
- pyedb/grpc/database/stackup.py +1 -1
- pyedb/grpc/database/terminal/__init__.py +21 -0
- pyedb/grpc/database/terminal/bundle_terminal.py +1 -1
- pyedb/grpc/database/terminal/edge_terminal.py +1 -1
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +1 -1
- pyedb/grpc/database/terminal/pingroup_terminal.py +1 -1
- pyedb/grpc/database/terminal/point_terminal.py +1 -1
- pyedb/grpc/database/terminal/terminal.py +1 -1
- pyedb/grpc/database/utility/__init__.py +22 -0
- pyedb/grpc/database/utility/constants.py +1 -1
- pyedb/grpc/database/utility/heat_sink.py +1 -1
- pyedb/grpc/database/utility/hfss_extent_info.py +1 -1
- pyedb/grpc/database/utility/layout_statistics.py +1 -1
- pyedb/grpc/database/utility/rlc.py +1 -1
- pyedb/grpc/database/utility/sources.py +1 -1
- pyedb/grpc/database/utility/sweep_data_distribution.py +1 -1
- pyedb/grpc/database/utility/value.py +1 -1
- pyedb/grpc/database/utility/xml_control_file.py +1 -1
- pyedb/grpc/edb.py +230 -990
- pyedb/grpc/edb_init.py +1 -1
- pyedb/grpc/rpc_session.py +17 -4
- pyedb/ipc2581/__init__.py +21 -0
- pyedb/ipc2581/bom/__init__.py +21 -0
- pyedb/ipc2581/bom/bom.py +1 -1
- pyedb/ipc2581/bom/bom_item.py +1 -1
- pyedb/ipc2581/bom/characteristics.py +1 -1
- pyedb/ipc2581/bom/refdes.py +1 -1
- pyedb/ipc2581/content/__init__.py +21 -0
- pyedb/ipc2581/content/color.py +1 -1
- pyedb/ipc2581/content/content.py +1 -1
- pyedb/ipc2581/content/dictionary_color.py +1 -1
- pyedb/ipc2581/content/dictionary_fill.py +1 -1
- pyedb/ipc2581/content/dictionary_line.py +1 -1
- pyedb/ipc2581/content/entry_color.py +1 -1
- pyedb/ipc2581/content/entry_line.py +1 -1
- pyedb/ipc2581/content/fill.py +1 -1
- pyedb/ipc2581/content/layer_ref.py +1 -1
- pyedb/ipc2581/content/standard_geometries_dictionary.py +1 -1
- pyedb/ipc2581/ecad/__init__.py +21 -0
- pyedb/ipc2581/ecad/cad_data/__init__.py +21 -0
- pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +1 -1
- pyedb/ipc2581/ecad/cad_data/cad_data.py +1 -1
- pyedb/ipc2581/ecad/cad_data/component.py +1 -1
- pyedb/ipc2581/ecad/cad_data/drill.py +1 -1
- pyedb/ipc2581/ecad/cad_data/feature.py +1 -1
- pyedb/ipc2581/ecad/cad_data/layer.py +1 -1
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +1 -1
- pyedb/ipc2581/ecad/cad_data/logical_net.py +1 -1
- pyedb/ipc2581/ecad/cad_data/outline.py +1 -1
- pyedb/ipc2581/ecad/cad_data/package.py +1 -1
- pyedb/ipc2581/ecad/cad_data/padstack_def.py +1 -1
- pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +1 -1
- pyedb/ipc2581/ecad/cad_data/padstack_instance.py +1 -1
- pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +1 -1
- pyedb/ipc2581/ecad/cad_data/path.py +1 -1
- pyedb/ipc2581/ecad/cad_data/phy_net.py +1 -1
- pyedb/ipc2581/ecad/cad_data/pin.py +1 -1
- pyedb/ipc2581/ecad/cad_data/polygon.py +1 -1
- pyedb/ipc2581/ecad/cad_data/profile.py +1 -1
- pyedb/ipc2581/ecad/cad_data/stackup.py +1 -1
- pyedb/ipc2581/ecad/cad_data/stackup_group.py +1 -1
- pyedb/ipc2581/ecad/cad_data/stackup_layer.py +1 -1
- pyedb/ipc2581/ecad/cad_data/step.py +1 -1
- pyedb/ipc2581/ecad/cad_header.py +1 -1
- pyedb/ipc2581/ecad/ecad.py +1 -1
- pyedb/ipc2581/ecad/spec.py +1 -1
- pyedb/ipc2581/history_record.py +1 -1
- pyedb/ipc2581/ipc2581.py +1 -1
- pyedb/ipc2581/logistic_header.py +1 -1
- pyedb/libraries/common.py +1 -1
- pyedb/libraries/rf_libraries/base_functions.py +1 -1
- pyedb/libraries/rf_libraries/planar_antennas.py +1 -1
- pyedb/misc/__init__.py +21 -0
- pyedb/misc/aedtlib_personalib_install.py +1 -1
- pyedb/misc/decorators.py +22 -0
- pyedb/misc/downloads.py +1 -1
- pyedb/misc/misc.py +1 -1
- pyedb/misc/siw_feature_config/__init__.py +21 -0
- pyedb/misc/siw_feature_config/emc/__init__.py +21 -0
- pyedb/misc/siw_feature_config/emc/component_tags.py +22 -0
- pyedb/misc/siw_feature_config/emc/net_tags.py +22 -0
- pyedb/misc/siw_feature_config/emc/tag_library.py +22 -0
- pyedb/misc/siw_feature_config/emc/xml_generic.py +22 -0
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +1 -1
- pyedb/misc/siw_feature_config/xtalk_scan/fd_xtalk_scan_config.py +1 -1
- pyedb/misc/siw_feature_config/xtalk_scan/impedance_scan_config.py +1 -1
- pyedb/misc/siw_feature_config/xtalk_scan/net.py +1 -1
- pyedb/misc/siw_feature_config/xtalk_scan/pins.py +1 -1
- pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +1 -1
- pyedb/misc/siw_feature_config/xtalk_scan/td_xtalk_config.py +1 -1
- pyedb/misc/utilities.py +1 -1
- pyedb/modeler/geometry_operators.py +22 -0
- pyedb/siwave.py +22 -0
- pyedb/siwave_core/__init__.py +21 -0
- pyedb/siwave_core/cpa/__init__.py +21 -0
- pyedb/siwave_core/cpa/simulation_setup_data_model.py +22 -0
- pyedb/siwave_core/icepak.py +1 -1
- pyedb/siwave_core/product_properties.py +23 -0
- pyedb/workflow.py +22 -0
- pyedb/workflows/__init__.py +21 -0
- pyedb/workflows/job_manager/__init__.py +21 -0
- pyedb/workflows/job_manager/backend/__init__.py +21 -0
- pyedb/workflows/job_manager/backend/job_manager_handler.py +910 -0
- pyedb/workflows/job_manager/backend/job_submission.py +1169 -0
- pyedb/workflows/job_manager/backend/service.py +1663 -0
- pyedb/workflows/job_manager/backend/start_service.py +86 -0
- pyedb/workflows/job_manager/backend/submit_job_on_scheduler.py +168 -0
- pyedb/workflows/job_manager/backend/submit_local_job.py +166 -0
- pyedb/workflows/sipi/hfss_auto_configuration.py +1 -1
- pyedb/workflows/utilities/__init__.py +21 -0
- pyedb/workflows/utilities/cutout.py +1428 -0
- pyedb/workflows/utilities/hfss_log_parser.py +446 -0
- {pyedb-0.59.0.dist-info → pyedb-0.61.0.dist-info}/METADATA +7 -4
- pyedb-0.61.0.dist-info/RECORD +318 -0
- {pyedb-0.59.0.dist-info → pyedb-0.61.0.dist-info}/licenses/LICENSE +7 -7
- pyedb-0.59.0.dist-info/RECORD +0 -306
- {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.
|
|
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.
|
|
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.
|
|
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
|
|
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"
|