diff --git a/.github/labeler.yml b/.github/labeler.yml index 954fa3db203..f0ccc72fd79 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -13,3 +13,10 @@ testing: - _unittest/conftest.py - _unittest_ironpython/run_unittests.py - _unittest_ironpython/run_unittests_batchmode.cmd +# TODO : Remove once EDB is extracted from PyAEDT +edb: +- examples/00-EDB/** +- examples/01-HFSS3DLayout/EDB_in_3DLayout.py +- examples/05-Q3D/Q3D_from_EDB.py +- pyaedt/edb_core/** +- pyaedt/edb.py diff --git a/.github/labels.yml b/.github/labels.yml index db55cba8545..413e3847c51 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -29,3 +29,7 @@ - name: testing description: Anything related to testing color: 5802B8 + +- name: edb + description: Anything related to the EDB API + color: C4C25D diff --git a/.github/workflows/full_documentation.yml b/.github/workflows/full_documentation.yml index 9803b95be47..4f80360f4f5 100644 --- a/.github/workflows/full_documentation.yml +++ b/.github/workflows/full_documentation.yml @@ -73,10 +73,10 @@ jobs: testenv\Scripts\Activate.ps1 sphinx-build -j auto --color -b html -a doc/source doc/_build/html - - name: Create PDF Documentations - run: | - testenv\Scripts\Activate.ps1 - .\doc\make.bat pdf +# - name: Create PDF Documentations +# run: | +# testenv\Scripts\Activate.ps1 +# .\doc\make.bat pdf - name: Upload HTML documentation artifact uses: actions/upload-artifact@v3 @@ -92,20 +92,20 @@ jobs: path: doc/_build/html/EDBAPI retention-days: 7 - - name: Upload PDF documentation artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-pdf - path: doc/_build/pdf - retention-days: 7 - - - name: Release - uses: softprops/action-gh-release@v1 - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - with: - generate_release_notes: true - files: | - doc/_build/pdf +# - name: Upload PDF documentation artifact +# uses: actions/upload-artifact@v3 +# with: +# name: documentation-pdf +# path: doc/_build/pdf +# retention-days: 7 + +# - name: Release +# uses: softprops/action-gh-release@v1 +# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') +# with: +# generate_release_notes: true +# files: | +# doc/_build/pdf doc-deploy-stable: name: Deploy stable documentation diff --git a/_unittest/test_00_EDB.py b/_unittest/test_00_EDB.py index 061d2ce9d30..66fd114c5ad 100644 --- a/_unittest/test_00_EDB.py +++ b/_unittest/test_00_EDB.py @@ -2480,6 +2480,11 @@ def test_130_create_padstack_instance(self): assert pad_instance3.dcir_equipotential_region pad_instance3.dcir_equipotential_region = False assert not pad_instance3.dcir_equipotential_region + + trace = edb.modeler.create_trace([[0, 0], [0, 10e-3]], "1_Top", "0.1mm", "trace_with_via_fence") + edb.padstacks.create_padstack("via_0") + trace.create_via_fence("1mm", "1mm", "via_0") + edb.close() def test_131_assign_hfss_extent_non_multiple_with_simconfig(self): @@ -2903,6 +2908,7 @@ def test_147_find_dc_shorts(self): assert dc_shorts edbapp.nets.nets["DDR4_A0"].name = "DDR4$A0" edbapp.layout_validation.illegal_net_names(True) + edbapp.layout_validation.illegal_rlc_values(True) # assert len(dc_shorts) == 20 assert ["LVDS_CH09_N", "GND"] in dc_shorts diff --git a/_unittest/test_08_Primitives3D.py b/_unittest/test_08_Primitives3D.py index 7b1c7c47975..d23a7fe61ec 100644 --- a/_unittest/test_08_Primitives3D.py +++ b/_unittest/test_08_Primitives3D.py @@ -681,6 +681,8 @@ def test_43_fillet_and_undo(self): assert o.edges[0].fillet() self.aedtapp._odesign.Undo() assert o.edges[0].fillet() + r = self.create_rectangle(name="MyRect") + assert not r.edges[0].fillet() def test_44_create_polyline_basic_segments(self): prim3D = self.aedtapp.modeler @@ -1789,3 +1791,43 @@ def test_85_insert_layoutcomponent(self): assert comp2.layout_component.display_mode == 1 comp2.layout_component.layers["Trace"] = [True, True, 90] assert comp2.layout_component.update_visibility() + + def test_87_set_mesh_fusion_settings(self): + self.aedtapp.insert_design("MeshFusionSettings") + box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 20, 30]) + obj_3dcomp = self.aedtapp.modeler.replace_3dcomponent( + object_list=[box1.name], + ) + box2 = self.aedtapp.modeler.create_box([0, 0, 0], [100, 20, 30]) + obj2_3dcomp = self.aedtapp.modeler.replace_3dcomponent( + object_list=[box2.name], + ) + assert self.aedtapp.set_mesh_fusion_settings(component=obj2_3dcomp.name, volume_padding=None, priority=None) + + assert self.aedtapp.set_mesh_fusion_settings( + component=[obj_3dcomp.name, obj2_3dcomp.name, "Dummy"], volume_padding=None, priority=None + ) + + assert self.aedtapp.set_mesh_fusion_settings( + component=[obj_3dcomp.name, obj2_3dcomp.name], + volume_padding=[[0, 5, 0, 0, 0, 1], [0, 0, 0, 2, 0, 0]], + priority=None, + ) + assert not self.aedtapp.set_mesh_fusion_settings( + component=[obj_3dcomp.name, obj2_3dcomp.name], volume_padding=[[0, 0, 0, 2, 0, 0]], priority=None + ) + + assert self.aedtapp.set_mesh_fusion_settings( + component=[obj_3dcomp.name, obj2_3dcomp.name], volume_padding=None, priority=[obj2_3dcomp.name, "Dummy"] + ) + + assert self.aedtapp.set_mesh_fusion_settings( + component=[obj_3dcomp.name, obj2_3dcomp.name], + volume_padding=[[0, 5, 0, 0, 0, 1], [10, 0, 0, 2, 0, 0]], + priority=[obj_3dcomp.name], + ) + assert self.aedtapp.set_mesh_fusion_settings( + component=None, + volume_padding=None, + priority=None, + ) diff --git a/doc/source/Getting_started/Installation.rst b/doc/source/Getting_started/Installation.rst index 6371f08d164..e0569085fb0 100644 --- a/doc/source/Getting_started/Installation.rst +++ b/doc/source/Getting_started/Installation.rst @@ -45,8 +45,8 @@ Starting from 2023R2, a Ribbon button is available in Automation Tab as in the e Build Toolkits with PyAEDT ~~~~~~~~~~~~~~~~~~~~~~~~~~ You can create and install external toolkits. -The template provides a framework to create your own toolkits using PyAEDT. -The template can be found at `Template `_. +The Antenna Wizard toolkit provides an example for modeling antennas using Ansys Electronics Desktop (AEDT). +The Antenna Wizard can be found at `Antenna Wizard `_. .. image:: ../Resources/template_ribbon.png :width: 800 @@ -97,67 +97,6 @@ For example, on Windows with Python 3.7, install PyAEDT and all its dependencies pip install --no-cache-dir --no-index --find-links=file:////PyAEDT-v-wheelhouse-Windows-3.7 pyaedt -Install from a batch file -~~~~~~~~~~~~~~~~~~~~~~~~~ -If you are running on Windows, you can download -:download:`PyAEDT Environment with IDE bat file <../Resources/pyaedt_with_IDE.bat>` -and run this batch file on your local machine. Using this approach -provides you with a complete integrated development environment (IDE) -for writing PyAEDT scripts in Windows with a simple batch file. - -This batch file executes these steps: - -1. Creates a Python virtual environment in your ``%APPDATA%`` folder. To accomplish - this, it uses CPython in the selected version of AEDT available on your machine. -2. Installs PyAEDT. -3. Optionally installs `Spyder `_ with -s flag. -4. Installs `Jupyter Lab `_. -5. Creates a symbolic link from your PyAEDT installation to AEDT ``PersonalLib`` so - that scripts can also be run within AEDT. -6. Updates PyAEDT. -7. Install PyAEDT toolkit in AEDT to enable PyAEDT Console and PyAEDT Run Script. -8. Runs the tool that you choose (Spyder, Jupyter Lab, or a simple console). - -.. image:: ../Resources/toolkits.png - :width: 800 - :alt: PyAEDT toolkit installed after batch run - -Steps 1 through 5 are executed only the first time that you run the batch file or when ``-f`` is used: - -.. code:: - - pyaedt_with_IDE.bat --force-install - - pyaedt_with_IDE.bat -f - -Step 6 is executed only when running the command with the ``-update`` option: - -.. code:: - - pyaedt_with_IDE.bat --update - - pyaedt_with_IDE.bat -u - -Optionally, you can decide to pass a Python path. This path is then used to create a virtual environment: - -.. code:: - - pyaedt_with_IDE.bat -f -p - - -In addition, it is possible to install the PyAEDT package and all its dependencies provided in the wheelhouse by -executing the batch file mentioned earlier. You must use the Wheelhouse 3.7 package if no Python path is provided. -Otherwise, you must download and use the correct wheelhouse: - -.. code:: - - pyaedt_with_IDE.bat-w PyAEDT-v-wheelhouse-Windows-3.7 - - pyaedt_with_IDE.bat -p -w PyAEDT-v-wheelhouse-Windows-3.8 - pyaedt_with_IDE.bat -p -w PyAEDT-v-wheelhouse-Windows-3.7 - pyaedt_with_IDE.bat -p -w PyAEDT-v-wheelhouse-Windows-3.9 - - Use IronPython in AEDT ~~~~~~~~~~~~~~~~~~~~~~ PyAEDT is designed to work in CPython 3.7+ and supports many advanced processing packages like diff --git a/doc/source/Resources/pyaedt_with_IDE.bat b/doc/source/Resources/pyaedt_with_IDE.bat deleted file mode 100644 index 15841b86f4f..00000000000 --- a/doc/source/Resources/pyaedt_with_IDE.bat +++ /dev/null @@ -1,152 +0,0 @@ -@echo off -set current_dir=%~dp0 -setlocal enabledelayedexpansion -set argCount=0 -for %%x in (%*) do ( - set /a argCount+=1 - set "argVec[!argCount!]=%%~x" -) - -set args=%1 %2 %3 %4 %5 %6 -set update_pyaedt=n -set install_pyaedt=n -set install_spyder=n - -for /L %%i in (1,1,%argCount%) do ( - if [!argVec[%%i]!]==[-f] set install_pyaedt=y - if [!argVec[%%i]!]==[--force-install] set install_pyaedt=y - if [!argVec[%%i]!]==[-u] set update_pyaedt=y - if [!argVec[%%i]!]==[--update] set update_pyaedt=y - if [!argVec[%%i]!]==[-p] ( - set /A usepython=%%i+1 - ) - if [!argVec[%%i]!]==[-w] ( - set /A usewheel=%%i+1 - ) - if [!argVec[%%i]!]==[-s] set install_spyder=y - -) -if NOT [%usepython%]==[] ( - set pythonpyaedt="!argVec[%usepython%]!" - echo Python Path has been specified. -) -if NOT [%usewheel%]==[] ( - set wheelpyaedt="!argVec[%usewheel%]!" - if [%usepython%]==[] ( - echo ---------------------------------------------------------------------- - echo WheelHouse has been specified. Make sure you are using version 3_7. - echo ---------------------------------------------------------------------- - - ) ELSE ( - echo ---------------------------------------------------------------------------------------------- - echo WheelHouse has been spefified. Make sure you are using the same version of Python interpreter. - echo ---------------------------------------------------------------------------------------------- - - ) -) - - -set env_vars=ANSYSEM_ROOT232 ANSYSEM_ROOT231 ANSYSEM_ROOT222 ANSYSEM_ROOT221 ANSYSEM_ROOT212 -set /A choice_index=1 -for %%c in (%env_vars%) do ( - set env_var_name=%%c - if defined !env_var_name! ( - set root_var[!choice_index!]=!env_var_name! - set version=!env_var_name:ANSYSEM_ROOT=! - set versions[!choice_index!]=!version! - set version_pretty=20!version:~0,2! R!version:~2,1! - echo [!choice_index!] !version_pretty! - set /A choice_index=!choice_index!+1 - ) -) -REM If choice_index wasn't incremented then it means none of the variables are installed -if [%choice_index%]==1 ( - echo AEDT 2021 R2 or later must be installed. - pause - EXIT /B -) - -set /p chosen_index="Select Version to Install PyAEDT for (number in bracket): " -if [%chosen_index%] == [] set chosen_index=1 - -set chosen_root=!root_var[%chosen_index%]! -set version=!versions[%chosen_index%]! -echo Selected %version% at !%chosen_root%!. - -set aedt_path=potato -if [%specified_python%]==[y] ( - aedt_path=!argVec[%python_path_index%]! -) else ( - set aedt_path=!%chosen_root%!\commonfiles\CPython\3_7\winx64\Release\python - echo Built-in Python is !aedt_path!. -) -set aedt_path=!aedt_path:"=! - -echo %aedt_path% - - - -set pyaedt_install_dir=%APPDATA%\pyaedt_env_ide\v%version% -echo %pyaedt_install_dir% -if NOT exist "%pyaedt_install_dir%" ( - set install_pyaedt=y -) -setlocal enableDelayedExpansion - -if [%install_pyaedt%]==[y] ( - if exist "%pyaedt_install_dir%" ( - echo Removing existing PyAEDT environment. - @RD /S /Q "%pyaedt_install_dir%" - ) - echo Installing PyAEDT environment in "%pyaedt_install_dir%". - - cd "%APPDATA%" - - if [%pythonpyaedt%] == [] ( - "%aedt_path%\python.exe" -m venv "%pyaedt_install_dir%" --system-site-packages - ) ELSE ( - "%pythonpyaedt%\python.exe" -m venv "%pyaedt_install_dir%" - ) - call "%pyaedt_install_dir%\Scripts\activate.bat" - if NOT [%wheelpyaedt%]==[] ( - echo Installing PyAEDT from local wheels %arg1%. - pip install --no-cache-dir --no-index --find-links=%wheelpyaedt% pyaedt - ) ELSE ( - IF EXIST %current_dir%.git ( - echo Installing PyAEDT from local clone "%current_dir%". - ) ELSE ( - echo Installing PyAEDT from pip. - ) - - python -m pip install --upgrade pip - pip --default-timeout=1000 install wheel - - IF EXIST %current_dir%.git ( - pushd %current_dir% - pip install . - popd - ) ELSE ( - pip --default-timeout=1000 install pyaedt - ) - - pip --default-timeout=1000 install jupyterlab -I - if [%install_spyder%]==[y] pip --default-timeout=1000 install spyder - pip --default-timeout=1000 install ipython -U - pip --default-timeout=1000 install ipyvtklink - ) - if [%pythonpyaedt%]==[] ( - if %version% geq 231 pip uninstall -y pywin32 - ) - - call python "%pyaedt_install_dir%\Lib\site-packages\pyaedt\misc\aedtlib_personalib_install.py" --version=%version% -) -if [%update_pyaedt%]==[y] ( - echo Updating PyAEDT. - "%pyaedt_install_dir%\Scripts\pip" install pythonnet -U - "%pyaedt_install_dir%\Scripts\pip" install pyaedt --no-deps -U - call "%pyaedt_install_dir%\Scripts\python" "%pyaedt_install_dir%\Lib\site-packages\pyaedt\misc\aedtlib_personalib_install.py" --version=%version% - -) - - -cmd /k "%pyaedt_install_dir%\Scripts\activate.bat" diff --git a/doc/source/conf.py b/doc/source/conf.py index f4e03a5fb1f..0b335cb0883 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -130,7 +130,7 @@ def setup(app): # Intersphinx mapping intersphinx_mapping = { - "python": ("https://docs.python.org/3", None), + "python": ("https://docs.python.org/3.11", None), "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), "numpy": ("https://numpy.org/devdocs", None), "matplotlib": ("https://matplotlib.org/stable", None), @@ -379,4 +379,4 @@ def setup(app): author, "manual", ), -] \ No newline at end of file +] diff --git a/examples/02-HFSS/Waveguide_Filter.py b/examples/02-HFSS/Waveguide_Filter.py index 42ed095620e..edae3bcad21 100644 --- a/examples/02-HFSS/Waveguide_Filter.py +++ b/examples/02-HFSS/Waveguide_Filter.py @@ -199,8 +199,7 @@ def place_iris(zpos, dz, n): ############################################################################### # Generate S-Parameter Plots -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -################################################################################# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ # The following commands fetch solution data from HFSS for plotting directly # from the Python interpreter. # Caution: The syntax for expressions must be identical to that used @@ -209,7 +208,27 @@ def place_iris(zpos, dz, n): traces_to_plot = hfss.get_traces_for_plot(second_element_filter="P1*") report = hfss.post.create_report(traces_to_plot) # Creates a report in HFSS solution = report.get_solution_data() + plt = solution.plot(solution.expressions) # Matplotlib axes object. +############################################################################### +# Generate E field plot +# ~~~~~~~~~~~~~~~~~~~~~ +# The following command generates a field plot in HFSS and uses PyVista +# to plot the field in Jupyter. + +plot=hfss.post.plot_field(quantity="Mag_E", + objects_list=["Global:XZ"], + plot_type="CutPlane", + setup_name=hfss.nominal_adaptive, + intrinsics={"Freq":"9.8GHz", "Phase":"0deg"}, + export_path=hfss.working_directory, + show=False) + +############################################################################### +# Save and close the desktop +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The following command saves the project to a file and closes the desktop. + hfss.save_project() hfss.release_desktop() diff --git a/examples/06-Multiphysics/MRI.py b/examples/06-Multiphysics/MRI.py index 01790e3641b..f943c1b749c 100644 --- a/examples/06-Multiphysics/MRI.py +++ b/examples/06-Multiphysics/MRI.py @@ -99,11 +99,20 @@ # Draw Point1 at origin of the implant coordinate system hfss.sar_setup(-1, Average_SAR_method=1, TissueMass=1, MaterialDensity=1, ) -hfss.post.create_fieldplot_cutplane("implant:YZ", "Average_SAR", filter_objects=["implant_box"]) +hfss.post.create_fieldplot_cutplane(objlist="implant:YZ", + quantityName="Average_SAR", + filter_objects=["implant_box"]) hfss.modeler.set_working_coordinate_system("implant") hfss.modeler.create_point([0, 0, 0], name="Point1") +hfss.post.plot_field(quantity="Average_SAR", + object_list="implant:YZ", + plot_type="CutPlane", + show_legend=False, + filter_objects=["implant_box"], + ) + ############################################################################### # Adjust Input Power to MRI Coil # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -113,7 +122,9 @@ # input_scale = 1/AverageSAR at Point1 -sol_data = hfss.post.get_solution_data("Average_SAR", primary_sweep_variable="Freq", context="Point1", +sol_data = hfss.post.get_solution_data(expressions="Average_SAR", + primary_sweep_variable="Freq", + context="Point1", report_category="Fields") sol_data.data_real() @@ -204,6 +215,15 @@ report_category="Fields") data.plot() +mech.post.plot_animated_field(quantity="Temperature", + object_list="implant:YZ", + plot_type="CutPlane", + intrinsics={"Time": "10s"}, + variation_variable="Time", + variation_list=["10s", "20s", "30s", "40s", "50s", "60s"], + filter_objects=["implant_box"], + ) + ############################################################################### # Thermal Simulation # ~~~~~~~~~~~~~~~~~~ @@ -277,7 +297,7 @@ # Plot Temperature on cut plane. # Plot Temperature on monitor point. -ipk.analyze(num_cores=6) +ipk.analyze(num_cores=4,num_tasks=4) ipk.post.create_fieldplot_cutplane("implant:YZ", "Temperature", filter_objects=["implant_box"], intrinsincDict={"Time": "0s"}) ipk.save_project() diff --git a/examples/07-Circuit/Reports.py b/examples/07-Circuit/Reports.py index 5c3a5d2fc6a..e09ee381453 100644 --- a/examples/07-Circuit/Reports.py +++ b/examples/07-Circuit/Reports.py @@ -9,9 +9,8 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~ # Perform required imports and set the local path to the path for PyAEDT. -# sphinx_gallery_thumbnail_path = 'Resources/spectrum_plot.png' import os - +from IPython.display import Image import pyaedt # Set local path to path for PyAEDT @@ -33,7 +32,7 @@ # The Boolean parameter ``new_thread`` defines whether to create a new instance # of AEDT or try to connect to an existing instance of it. -non_graphical = False +non_graphical = True NewThread = True ############################################################################### @@ -47,6 +46,7 @@ specified_version=desktopVersion, new_desktop_session=True ) +cir.analyze() ############################################################################### # Create spectrum report @@ -58,10 +58,17 @@ # in non-graphical mode in AEDT 2023 R2 and later. report1 = cir.post.create_report_from_configuration(os.path.join(project_path,'Spectrum_CISPR_Basic.json')) +out = cir.post.export_report_to_jpg(cir.working_directory, report1.plot_name) +Image(out) -if not non_graphical: - report1_full = cir.post.create_report_from_configuration(os.path.join(project_path,'Spectrum_CISPR_Custom.json')) +############################################################################### +# Create spectrum report +# ~~~~~~~~~~~~~~~~~~~~~~ +# Every aspect of the report can be customized. +report1_full = cir.post.create_report_from_configuration(os.path.join(project_path,'Spectrum_CISPR_Custom.json')) +out = cir.post.export_report_to_jpg(cir.working_directory, report1_full.plot_name) +Image(out) ############################################################################### # Create transient report # ~~~~~~~~~~~~~~~~~~~~~~~ @@ -70,31 +77,45 @@ # before generating the report. You can create custom reports in non-graphical # mode in AEDT 2023 R2 and later. -if non_graphical: - props = pyaedt.data_handler.json_to_dict(os.path.join(project_path, 'Transient_CISPR_Basic.json')) -else: - props = pyaedt.data_handler.json_to_dict(os.path.join(project_path, 'Transient_CISPR_Custom.json')) + +props = pyaedt.data_handler.json_to_dict(os.path.join(project_path, 'Transient_CISPR_Custom.json')) report2 = cir.post.create_report_from_configuration(input_dict=props, solution_name="NexximTransient") +out = cir.post.export_report_to_jpg(cir.working_directory, report2.plot_name) +Image(out) + +############################################################################### +# Create transient report +# ~~~~~~~~~~~~~~~~~~~~~~~ +# Property dictionary can be customized in any aspect and new report can be created easily. +# In this example the curve name is customized. + props["expressions"] = {"V(Battery)": {}, "V(U1_VDD)": {}} props["plot_name"] = "Battery Voltage" report3 = cir.post.create_report_from_configuration(input_dict=props, solution_name="NexximTransient") +out = cir.post.export_report_to_jpg(cir.working_directory, report3.plot_name) +Image(out) ############################################################################### # Create eye diagram # ~~~~~~~~~~~~~~~~~~ # Create an eye diagram. If the JSON file contains an eye mask, you can create -# an eye diagram and fully customize it. You can create custom reports in -# non-graphical mode in AEDT 2023 R2 and later. +# an eye diagram and fully customize it. report4 = cir.post.create_report_from_configuration(os.path.join(project_path, 'EyeDiagram_CISPR_Basic.json')) +out = cir.post.export_report_to_jpg(cir.working_directory, report4.plot_name) +Image(out) -if not non_graphical: - report4_full = cir.post.create_report_from_configuration(os.path.join(project_path, 'EyeDiagram_CISPR_Custom.json')) +############################################################################### +# Create eye diagram +# ~~~~~~~~~~~~~~~~~~ +# You can create custom reports in +# non-graphical mode in AEDT 2023 R2 and later. -if not non_graphical: - cir.post.export_report_to_jpg(cir.working_directory, report4.plot_name) +report4_full = cir.post.create_report_from_configuration(os.path.join(project_path, 'EyeDiagram_CISPR_Custom.json')) +out = cir.post.export_report_to_jpg(cir.working_directory, report4_full.plot_name) +Image(out) ################################################ # This is how the spectrum looks like # .. image:: Resources/spectrum_plot.png diff --git a/pyaedt/aedt_logger.py b/pyaedt/aedt_logger.py index f1c635f56a3..a3a307eb1f8 100644 --- a/pyaedt/aedt_logger.py +++ b/pyaedt/aedt_logger.py @@ -320,7 +320,7 @@ def get_messages(self, project_name=None, design_name=None, level=0, aedt_messag """ project_name = project_name or self._project_name design_name = design_name or self._design_name - if self._log_on_desktop or aedt_messages: + if aedt_messages and self._desktop.GetVersion() > "2022.2": global_message_data = self._desktop.GetMessages("", "", level) # if a 3d component is open, GetMessages without the project name argument returns messages with # "(3D Component)" appended to project name diff --git a/pyaedt/application/Analysis.py b/pyaedt/application/Analysis.py index 12bf51149aa..23d37b3ebf0 100644 --- a/pyaedt/application/Analysis.py +++ b/pyaedt/application/Analysis.py @@ -1724,27 +1724,36 @@ def analyze_setup( skip_files = True if not skip_files: if num_cores: - skip_files = update_hpc_option(target_name, "NumCores", num_cores, False) + succeeded = update_hpc_option(target_name, "NumCores", num_cores, False) + skip_files = True if not succeeded else skip_files if num_gpu: - skip_files = update_hpc_option(target_name, "NumGPUs", num_gpu, False) + succeeded = update_hpc_option(target_name, "NumGPUs", num_gpu, False) + skip_files = True if not succeeded else skip_files if num_tasks: - skip_files = update_hpc_option(target_name, "NumEngines", num_tasks, False) - skip_files = update_hpc_option(target_name, "ConfigName", config_name, True) - skip_files = update_hpc_option(target_name, "DesignType", self.design_type, True) + succeeded = update_hpc_option(target_name, "NumEngines", num_tasks, False) + skip_files = True if not succeeded else skip_files + succeeded = update_hpc_option(target_name, "ConfigName", config_name, True) + skip_files = True if not succeeded else skip_files + succeeded = update_hpc_option(target_name, "DesignType", self.design_type, True) + skip_files = True if not succeeded else skip_files if self.design_type == "Icepak": use_auto_settings = False - skip_files = update_hpc_option(target_name, "UseAutoSettings", use_auto_settings, False) + succeeded = update_hpc_option(target_name, "UseAutoSettings", use_auto_settings, False) + skip_files = True if not succeeded else skip_files if num_variations_to_distribute: - skip_files = update_hpc_option( + succeeded = update_hpc_option( target_name, "NumVariationsToDistribute", num_variations_to_distribute, False ) + skip_files = True if not succeeded else skip_files if isinstance(allowed_distribution_types, list): num_adt = len(allowed_distribution_types) adt_string = "', '".join(allowed_distribution_types) adt_string = "[{}: '{}']".format(num_adt, adt_string) - skip_files = update_hpc_option( + + succeeded = update_hpc_option( target_name, "AllowedDistributionTypes", adt_string, False, separator="" ) + skip_files = True if not succeeded else skip_files if settings.remote_rpc_session: remote_name = ( diff --git a/pyaedt/edb_core/edb_data/connectable.py b/pyaedt/edb_core/edb_data/connectable.py index d6f19e0916f..bc55363f7d7 100644 --- a/pyaedt/edb_core/edb_data/connectable.py +++ b/pyaedt/edb_core/edb_data/connectable.py @@ -1,4 +1,5 @@ from pyaedt import pyaedt_function_handler +from pyaedt.edb_core.edb_data.obj_base import ObjBase class LayoutObjInstance: @@ -9,7 +10,7 @@ def __init__(self, pedb, edb_object): self._edb_object = edb_object -class LayoutObj(object): +class LayoutObj(ObjBase): """Manages EDB functionalities for the layout object.""" def __getattr__(self, key): # pragma: no cover @@ -22,8 +23,7 @@ def __getattr__(self, key): # pragma: no cover raise AttributeError("Attribute not present") def __init__(self, pedb, edb_object): - self._pedb = pedb - self._edb_object = edb_object + super().__init__(pedb, edb_object) @property def _edb(self): @@ -55,11 +55,6 @@ def _obj_type(self): """Returns LayoutObjType.""" return self._edb_object.GetObjType().ToString() - @property - def is_null(self): - """Flag indicating if this object is null.""" - return self._edb_object.IsNull() - @property def id(self): """Primitive ID. diff --git a/pyaedt/edb_core/edb_data/obj_base.py b/pyaedt/edb_core/edb_data/obj_base.py new file mode 100644 index 00000000000..4d43360e47a --- /dev/null +++ b/pyaedt/edb_core/edb_data/obj_base.py @@ -0,0 +1,16 @@ +class ObjBase(object): + """Manages EDB functionalities for a base object.""" + + def __init__(self, pedb, model): + self._pedb = pedb + self._edb_object = model + + @property + def is_null(self): + """Flag indicating if this object is null.""" + return self._edb_object.IsNull() + + @property + def type(self): + """Get type.""" + return self._edb_object.GetType() diff --git a/pyaedt/edb_core/edb_data/primitives_data.py b/pyaedt/edb_core/edb_data/primitives_data.py index d3c7e37387e..4b29f1c4dbc 100644 --- a/pyaedt/edb_core/edb_data/primitives_data.py +++ b/pyaedt/edb_core/edb_data/primitives_data.py @@ -835,6 +835,113 @@ def create_edge_port( else: return self._app.hfss.create_edge_port_vertical(self.id, pos, name, 50, reference_layer) + pyaedt_function_handler() + + def create_via_fence(self, distance, gap, padstack_name): + """Create via fences on both sides of the trace. + + Parameters + ---------- + distance: str, float + Distance between via fence and trace center line. + gap: str, float + Gap between vias. + padstack_name: str + Name of the via padstack. + + Returns + ------- + + """ + + def getAngle(v1, v2): # pragma: no cover + v1_mag = math.sqrt(v1[0] ** 2 + v1[1] ** 2) + v2_mag = math.sqrt(v2[0] ** 2 + v2[1] ** 2) + dotsum = v1[0] * v2[0] + v1[1] * v2[1] + if v1[0] * v2[1] - v1[1] * v2[0] > 0: + scale = 1 + else: + scale = -1 + dtheta = scale * math.acos(dotsum / (v1_mag * v2_mag)) + + return dtheta + + def getLocations(line, gap): # pragma: no cover + location = [line[0]] + residual = 0 + + for n in range(len(line) - 1): + x0, y0 = line[n] + x1, y1 = line[n + 1] + length = math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) + dx, dy = (x1 - x0) / length, (y1 - y0) / length + x = x0 - dx * residual + y = y0 - dy * residual + length = length + residual + while length >= gap: + x += gap * dx + y += gap * dy + location.append((x, y)) + length -= gap + + residual = length + return location + + def getParalletLines(pts, distance): # pragma: no cover + leftline = [] + rightline = [] + + x0, y0 = pts[0] + x1, y1 = pts[1] + vector = (x1 - x0, y1 - y0) + orientation1 = getAngle((1, 0), vector) + + leftturn = orientation1 + math.pi / 2 + righrturn = orientation1 - math.pi / 2 + leftPt = (x0 + distance * math.cos(leftturn), y0 + distance * math.sin(leftturn)) + leftline.append(leftPt) + rightPt = (x0 + distance * math.cos(righrturn), y0 + distance * math.sin(righrturn)) + rightline.append(rightPt) + + for n in range(1, len(pts) - 1): + x0, y0 = pts[n - 1] + x1, y1 = pts[n] + x2, y2 = pts[n + 1] + + v1 = (x1 - x0, y1 - y0) + v2 = (x2 - x1, y2 - y1) + dtheta = getAngle(v1, v2) + orientation1 = getAngle((1, 0), v1) + + leftturn = orientation1 + dtheta / 2 + math.pi / 2 + righrturn = orientation1 + dtheta / 2 - math.pi / 2 + + distance2 = distance / math.sin((math.pi - dtheta) / 2) + leftPt = (x1 + distance2 * math.cos(leftturn), y1 + distance2 * math.sin(leftturn)) + leftline.append(leftPt) + rightPt = (x1 + distance2 * math.cos(righrturn), y1 + distance2 * math.sin(righrturn)) + rightline.append(rightPt) + + x0, y0 = pts[-2] + x1, y1 = pts[-1] + + vector = (x1 - x0, y1 - y0) + orientation1 = getAngle((1, 0), vector) + leftturn = orientation1 + math.pi / 2 + righrturn = orientation1 - math.pi / 2 + leftPt = (x1 + distance * math.cos(leftturn), y1 + distance * math.sin(leftturn)) + leftline.append(leftPt) + rightPt = (x1 + distance * math.cos(righrturn), y1 + distance * math.sin(righrturn)) + rightline.append(rightPt) + return leftline, rightline + + distance = self._pedb.edb_value(distance).ToDouble() + gap = self._pedb.edb_value(gap).ToDouble() + center_line = self.get_center_line() + leftline, rightline = getParalletLines(center_line, distance) + for x, y in getLocations(rightline, gap) + getLocations(leftline, gap): + self._pedb.padstacks.place([x, y], padstack_name) + class EdbRectangle(EDBPrimitives, RectangleDotNet): def __init__(self, raw_primitive, core_app): diff --git a/pyaedt/edb_core/layout_validation.py b/pyaedt/edb_core/layout_validation.py index 7ed850acda0..1f5446ab8d8 100644 --- a/pyaedt/edb_core/layout_validation.py +++ b/pyaedt/edb_core/layout_validation.py @@ -230,3 +230,21 @@ def illegal_net_names(self, fix=False): self._pedb._logger.info("Found {} illegal net names.".format(len(renamed_nets))) return + + def illegal_rlc_values(self, fix=False): + """Find and fix rlc illegal values.""" + inductors = self._pedb.components.inductors + + temp = [] + for k, v in inductors.items(): + componentProperty = v.edbcomponent.GetComponentProperty() + model = componentProperty.GetModel().Clone() + pinpairs = model.PinPairs + + if not len(list(pinpairs)): # pragma: no cover + temp.append(k) + if fix: + v.rlc_values = [0, 1, 0] + + self._pedb._logger.info("Found {} inductors have no value.".format(len(temp))) + return diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index dfc1b54bcab..0d68f27f88e 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -1516,6 +1516,7 @@ def plot(self, export_image_path=None): bool """ self.pv = pv.Plotter(notebook=self.is_notebook, off_screen=self.off_screen, window_size=self.windows_size) + self.pv.enable_ssao() self.meshes = None if self.background_image: self.pv.add_background_image(self.background_image) @@ -1582,8 +1583,8 @@ def plot(self, export_image_path=None): if self.show_axes: self.pv.show_axes() - if not self.is_notebook: - self.pv.show_grid(color=tuple(axes_color), grid=self.show_grid, fmt="%.3e") + if not self.is_notebook and self.show_grid: + self.pv.show_grid(color=tuple(axes_color), grid=self.show_grid, fmt="%.2e") if self.bounding_box: self.pv.add_bounding_box(color=tuple(axes_color)) self.pv.set_focus(self.pv.mesh.center) diff --git a/pyaedt/hfss.py b/pyaedt/hfss.py index 4b466df71ab..4eca4251975 100644 --- a/pyaedt/hfss.py +++ b/pyaedt/hfss.py @@ -6467,3 +6467,85 @@ def set_radiated_power_calc_method(self, method="Auto"): """ self.oradfield.EditRadiatedPowerCalculationMethod(method) return True + + @pyaedt_function_handler() + def set_mesh_fusion_settings(self, component=None, volume_padding=None, priority=None): + # type: (list|str, list, list) -> bool + + """Set mesh fusion settings in Hfss. + + component : list, optional + List of active 3D Components. + The default is ``None``, in which case components are disabled. + volume_padding : list, optional + List of mesh envelope padding, the format is ``[+x, -x, +y, -y, +z, -z]``. + The default is ``None``, in which case all zeros are applied. + priority : list, optional + List of components with the priority flag enabled. The default is ``None``. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + References + ---------- + + >>> oDesign.SetDoMeshAssembly + + Examples + -------- + + >>> import pyaedt + >>> app = pyaedt.Hfss() + >>> app.set_mesh_fusion_settings(component=["Comp1", "Comp2"], + ... volume_padding=[[0,0,0,0,0,0], [0,0,5,0,0,0]], + ... priority=["Comp1"]) + """ + arg = ["NAME:AllSettings"] + arg2 = ["NAME:MeshAssembly"] + arg3 = ["NAME:Priority Components"] + + if component and not isinstance(component, list): + component = [component] + + if not volume_padding and component: + for comp in component: + if comp in self.modeler.user_defined_component_names: + mesh_assembly_arg = ["NAME:" + comp] + mesh_assembly_arg.append("MeshAssemblyBoundingVolumePadding:=") + mesh_assembly_arg.append(["0", "0", "0", "0", "0", "0"]) + arg2.append(mesh_assembly_arg) + else: + self.logger.warning(comp + " does not exist.") + + elif component and isinstance(volume_padding, list) and len(volume_padding) == len(component): + count = 0 + for comp in component: + padding = [str(pad) for pad in volume_padding[count]] + if comp in self.modeler.user_defined_component_names: + mesh_assembly_arg = ["NAME:" + comp] + mesh_assembly_arg.append("MeshAssemblyBoundingVolumePadding:=") + mesh_assembly_arg.append(padding) + arg2.append(mesh_assembly_arg) + else: + self.logger.warning("{0} does not exist".format(str(comp))) + count += 1 + elif component and isinstance(volume_padding, list) and len(volume_padding) != len(component): + self.logger.error("Volume padding length is different than component list length.") + return False + + if priority and not isinstance(priority, list): + priority = [priority] + + if component and priority: + for p in priority: + if p in self.modeler.user_defined_component_names: + arg3.append(p) + else: + self.logger.warning("{0} does not exist".format(str(p))) + + arg.append(arg2) + arg.append(arg3) + self.odesign.SetDoMeshAssembly(arg) + return True diff --git a/pyaedt/maxwell.py b/pyaedt/maxwell.py index 82d1971c36b..67acc669ebe 100644 --- a/pyaedt/maxwell.py +++ b/pyaedt/maxwell.py @@ -10,7 +10,6 @@ from pyaedt.application.Analysis3D import FieldAnalysis3D from pyaedt.application.Variables import decompose_variable_value -from pyaedt.generic.DataHandlers import float_units from pyaedt.generic.constants import SOLUTIONS from pyaedt.generic.general_methods import generate_unique_name from pyaedt.generic.general_methods import open_file @@ -2829,23 +2828,19 @@ def xy_plane(self, value=True): @property def model_depth(self): """Model depth.""" - - if "ModelDepth" in self.design_properties: - value_str = self.design_properties["ModelDepth"] - a = None - try: - a = float_units(value_str) - except: - a = self.variable_manager[value_str].value - finally: - return a + design_settings = self.design_settings() + if "ModelDepth" in design_settings: + value_str = design_settings["ModelDepth"] + return value_str else: return None @model_depth.setter def model_depth(self, value): """Set model depth.""" - return self.change_design_settings({"ModelDepth": self.modeler._arg_with_dim(value, self.modeler.model_units)}) + if isinstance(value, float) or isinstance(value, int): + value = self.modeler._arg_with_dim(value, self.modeler.model_units) + self.change_design_settings({"ModelDepth": value}) @pyaedt_function_handler() def generate_design_data(self, linefilter=None, objectfilter=None): diff --git a/pyaedt/misc/install_extra_toolkits.py b/pyaedt/misc/install_extra_toolkits.py index 8d97f8c5425..3748895fe1e 100644 --- a/pyaedt/misc/install_extra_toolkits.py +++ b/pyaedt/misc/install_extra_toolkits.py @@ -22,13 +22,6 @@ "installation_path": "Project", "package_name": "ansys.aedt.toolkits.choke", }, - "TemplateToolkit": { - "pip": "git+https://github.com/ansys/pyaedt-toolkit-template.git", - "image": "pyansys.png", - "toolkit_script": "ansys/aedt/toolkits/template/run_toolkit.py", - "installation_path": "Project", - "package_name": "ansys.aedt.toolkits.template", - }, } diff --git a/pyaedt/misc/pyaedt_local_config.acf b/pyaedt/misc/pyaedt_local_config.acf index cb73887a0d1..4a496f85e08 100644 --- a/pyaedt/misc/pyaedt_local_config.acf +++ b/pyaedt/misc/pyaedt_local_config.acf @@ -1,7 +1,7 @@ $begin 'Configs' $begin 'Configs' $begin 'DSOConfig' - ConfigName='PyAEDT' + ConfigName='pyaedt_config' DesignType='HFSS' $begin 'DSOMachineList' $begin 'DSOMachineInfo' diff --git a/pyaedt/modeler/cad/elements3d.py b/pyaedt/modeler/cad/elements3d.py index b7f82b8f46a..4b3f549022e 100644 --- a/pyaedt/modeler/cad/elements3d.py +++ b/pyaedt/modeler/cad/elements3d.py @@ -69,7 +69,7 @@ class EdgeTypePrimitive(object): @pyaedt_function_handler() def fillet(self, radius=0.1, setback=0.0): - """Add a fillet to the selected edge. + """Add a fillet to the selected edges in 3D/vertices in 2D. Parameters ---------- @@ -98,7 +98,7 @@ def fillet(self, radius=0.1, setback=0.0): if self._object3d.is3d: edge_id_list = [self.id] else: - self._object3d.logger.error("Filet is possible only on a vertex in 2D designs.") + self._object3d.logger.error("Fillet is possible only on a vertex in 2D designs.") return False vArg1 = ["NAME:Selections", "Selections:=", self._object3d.name, "NewPartsModelFlag:=", "Model"] @@ -116,7 +116,7 @@ def fillet(self, radius=0.1, setback=0.0): @pyaedt_function_handler() def chamfer(self, left_distance=1, right_distance=None, angle=45, chamfer_type=0): - """Add a chamfer to the selected edge. + """Add a chamfer to the selected edges in 3D/vertices in 2D. Parameters ---------- diff --git a/pyaedt/modules/AdvancedPostProcessing.py b/pyaedt/modules/AdvancedPostProcessing.py index a117436a222..b5373a42e15 100644 --- a/pyaedt/modules/AdvancedPostProcessing.py +++ b/pyaedt/modules/AdvancedPostProcessing.py @@ -321,6 +321,7 @@ def plot_field_from_fieldplot( dark_mode=False, show_grid=False, show_bounding=False, + show_legend=True, ): """Export a field plot to an image file (JPG or PNG) using Python PyVista. @@ -364,6 +365,8 @@ def plot_field_from_fieldplot( Whether to display the axes grid or not. The default is ``False``. show_bounding : bool, optional Whether to display the axes bounding box or not. The default is ``False``. + show_legend : bool, optional + Whether to display the legend or not. The default is ``True``. Returns ------- @@ -380,7 +383,7 @@ def plot_field_from_fieldplot( file_to_add = self.export_field_plot(plotname, self._app.working_directory) model = self.get_model_plotter_geometries(generate_mesh=False, get_objects_from_aedt=plot_cad_objs) - + model.show_legend = show_legend model.off_screen = not show if dark_mode: model.background_color = [40, 40, 40] @@ -431,6 +434,8 @@ def plot_field( dark_mode=False, show_bounding=False, show_grid=False, + show_legend=True, + filter_objects=[], ): """Create a field plot using Python PyVista and export to an image file (JPG or PNG). @@ -481,12 +486,18 @@ def plot_field( Whether to display the axes grid or not. The default is ``False``. show_bounding : bool, optional Whether to display the axes bounding box or not. The default is ``False``. + show_legend : bool, optional + Whether to display the legend or not. The default is ``True``. + filter_objects : list, optional + Objects list for filtering the ``CutPlane`` plots. Returns ------- :class:`pyaedt.generic.plot.ModelPlotter` Model Object. """ + if os.getenv("PYAEDT_DOC_GENERATION", "False").lower() in ("true", "1", "t"): # pragma: no cover + show = False if not setup_name: setup_name = self._app.existing_analysis_sweeps[0] if not intrinsics: @@ -500,7 +511,9 @@ def plot_field( elif plot_type == "Volume": plotf = self.create_fieldplot_volume(object_list, quantity, setup_name, intrinsics) else: - plotf = self.create_fieldplot_cutplane(object_list, quantity, setup_name, intrinsics) + plotf = self.create_fieldplot_cutplane( + object_list, quantity, setup_name, intrinsics, filter_objects=filter_objects + ) # if plotf: # file_to_add = self.export_field_plot(plotf.name, self._app.working_directory, plotf.name) @@ -520,6 +533,7 @@ def plot_field( dark_mode=dark_mode, show_grid=show_grid, show_bounding=show_bounding, + show_legend=show_legend, ) if not keep_plot_after_generation: plotf.delete() @@ -549,6 +563,8 @@ def plot_animated_field( dark_mode=False, show_grid=False, show_bounding=False, + show_legend=True, + filter_objects=[], ): """Create an animated field plot using Python PyVista and export to a gif file. @@ -600,12 +616,18 @@ def plot_animated_field( Whether to display the axes grid or not. The default is ``False``. show_bounding : bool, optional Whether to display the axes bounding box or not. The default is ``False``. + show_legend : bool, optional + Whether to display the legend or not. The default is ``True``. + filter_objects : list, optional + Objects list for filtering the ``CutPlane`` plots. Returns ------- :class:`pyaedt.generic.plot.ModelPlotter` Model Object. """ + if os.getenv("PYAEDT_DOC_GENERATION", "False").lower() in ("true", "1", "t"): # pragma: no cover + show = False if intrinsics is None: intrinsics = {} if not export_path: @@ -626,7 +648,9 @@ def plot_animated_field( elif plot_type == "Volume": plotf = self.create_fieldplot_volume(object_list, quantity, setup_name, intrinsics) else: - plotf = self.create_fieldplot_cutplane(object_list, quantity, setup_name, intrinsics) + plotf = self.create_fieldplot_cutplane( + object_list, quantity, setup_name, intrinsics, filter_objects=filter_objects + ) if plotf: file_to_add = self.export_field_plot(plotf.name, export_path, plotf.name + str(v)) if file_to_add: @@ -641,6 +665,7 @@ def plot_animated_field( model.background_color = [40, 40, 40] model.bounding_box = show_bounding model.show_grid = show_grid + model.show_legend = show_legend if fields_to_add: model.add_frames_from_file(fields_to_add, log_scale=log_scale) if export_gif: diff --git a/pyaedt/modules/MeshIcepak.py b/pyaedt/modules/MeshIcepak.py index b3df7d30034..9773f3bbed6 100644 --- a/pyaedt/modules/MeshIcepak.py +++ b/pyaedt/modules/MeshIcepak.py @@ -187,7 +187,7 @@ def autosettings(self): if self.SubModels: arg.append("SubModels:=") arg.append(self.SubModels) - else: + if self.Objects: arg.append("Objects:=") arg.append(self.Objects) arg.extend(self._new_versions_fields) @@ -242,7 +242,7 @@ def manualsettings(self): if self.SubModels: arg.append("SubModels:=") arg.append(self.SubModels) - else: + if self.Objects: arg.append("Objects:=") arg.append(self.Objects) arg.extend(self._new_versions_fields) @@ -669,12 +669,23 @@ def assign_mesh_region(self, objectlist=[], level=5, is_submodel=False, name=Non except Exception: # pragma : no cover created = False if created: - objectlist2 = self.modeler.object_names - added_obj = [i for i in objectlist2 if i not in all_objs] - if not added_obj: - added_obj = [i for i in objectlist2 if i not in all_objs or i in objectlist] - meshregion.Objects = added_obj - meshregion.SubModels = None + if virtual_region and self._app.check_beta_option_enabled( + "S544753_ICEPAK_VIRTUALMESHREGION_PARADIGM" + ): # pragma : no cover + if is_submodel: + meshregion.Objects = [i for i in objectlist if i in all_objs] + meshregion.SubModels = [i for i in objectlist if i not in all_objs] + else: + meshregion.Objects = objectlist + meshregion.SubModels = None + else: + objectlist2 = self.modeler.object_names + added_obj = [i for i in objectlist2 if i not in all_objs] + if not added_obj: + added_obj = [i for i in objectlist2 if i not in all_objs or i in objectlist] + meshregion.Objects = added_obj + meshregion.SubModels = None + meshregion.update() return meshregion else: diff --git a/pyaedt/modules/PostProcessor.py b/pyaedt/modules/PostProcessor.py index 5b11a512393..286207b85f1 100644 --- a/pyaedt/modules/PostProcessor.py +++ b/pyaedt/modules/PostProcessor.py @@ -1302,9 +1302,9 @@ def export_report_to_jpg(self, project_dir, plot_name, width=0, height=0): plot_name : str Name of the plot to export. width : int, optional - Image width. Default is ``0`` which takes Desktop size or 500 pixel in case of non-graphical mode. + Image width. Default is ``0`` which takes Desktop size or 1980 pixel in case of non-graphical mode. height : int, optional - Image height. Default is ``0`` which takes Desktop size or 500 pixel in case of non-graphical mode. + Image height. Default is ``0`` which takes Desktop size or 1020 pixel in case of non-graphical mode. Returns ------- @@ -1319,11 +1319,11 @@ def export_report_to_jpg(self, project_dir, plot_name, width=0, height=0): # path npath = project_dir file_name = os.path.join(npath, plot_name + ".jpg") # name of the image file - if self._app.desktop_class.non_graphical: + if self._app.desktop_class.non_graphical: # pragma: no cover if width == 0: - width = 500 + width = 1980 if height == 0: - height = 500 + height = 1020 self.oreportsetup.ExportImageToFile(plot_name, file_name, width, height) return True @@ -3505,7 +3505,7 @@ def export_model_obj(self, obj_list=None, export_path=None, export_as_single_obj if not self._app.modeler[el].display_wireframe: transp = 0.6 t = self._app.modeler[el].transparency - if t: + if t is not None: transp = t files_exported.append([fname, self._app.modeler[el].color, 1 - transp]) else: diff --git a/pyproject.toml b/pyproject.toml index 7b6b96ad7d4..b771bc9f609 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ "cffi == 1.15.1;platform_system=='Linux' and python_version == '3.7'", "cffi == 1.16.0;platform_system=='Linux' and python_version > '3.7'", "pywin32 >= 303;platform_system=='Windows'", - "pythonnet == 3.0.2", + "ansys-pythonnet>=3.1.0rc2", "rpyc==5.3.1", "psutil", "dotnetcore2 ==3.1.23;platform_system=='Linux'",