Skip to content

Commit

Permalink
TEST: Improve touchstone parser coverage (#5349)
Browse files Browse the repository at this point in the history
  • Loading branch information
SMoraisAnsys authored Nov 5, 2024
1 parent ea34abc commit 3c8503b
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 33 deletions.
42 changes: 10 additions & 32 deletions src/ansys/aedt/core/visualization/advanced/touchstone_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import subprocess
import warnings

from ansys.aedt.core.aedt_logger import pyaedt_logger as logger
from ansys.aedt.core.generic.aedt_versions import aedt_versions
from ansys.aedt.core.generic.general_methods import pyaedt_function_handler

Expand Down Expand Up @@ -67,30 +68,6 @@
keys = {REAL_IMAG: ("real", "imag"), MAG_ANGLE: ("mag", "deg"), DB_ANGLE: ("db20", "deg")}


def _parse_ports_name(file):
"""Parse and interpret the option line in the touchstone file.
Parameters
----------
file : str
Path of the touchstone file.
Returns
-------
List of str
Names of the ports in the touchstone file.
"""
portnames = []
line = file.readline()
while not line.startswith("! Port"):
line = file.readline()
while line.startswith("! Port"):
portnames.append(line.split(" = ")[1].strip())
line = file.readline()
return portnames


class TouchstoneData(rf.Network):
"""Contains data information from Touchstone Read call."""

Expand Down Expand Up @@ -180,7 +157,7 @@ def plot_insertion_losses(self, threshold=-3, plot=True):
List of tuples representing insertion loss excitations.
"""
temp_list = self.get_insertion_loss_index(threshold=threshold)
if plot: # pragma: no cover
if plot:
for i in temp_list:
self.plot_s_db(*i, logx=self.log_x)
plt.show()
Expand Down Expand Up @@ -208,9 +185,9 @@ def plot(self, index_couples=None, show=True):
self.plot_s_db(*i, logx=self.log_x)
if show:
plt.show()
return plt
return True

def plot_return_losses(self): # pragma: no cover
def plot_return_losses(self):
"""Plot all return losses.
Returns
Expand Down Expand Up @@ -260,6 +237,7 @@ def get_mixed_mode_touchstone_data(self, num_of_diff_ports=None, port_ordering="

ts_diff.renumber(port_order, new_port_order)
else:
logger.error("Invalid input provided for 'port_ordering'.")
return False

ts_diff.se2gmm(num_of_diff_ports)
Expand Down Expand Up @@ -320,7 +298,7 @@ def get_insertion_loss_index_from_prefix(self, tx_prefix, rx_prefix):
receiver_list = [i for i in self.port_names if rx_prefix in i]
values = []
if len(trlist) != len(receiver_list):
print("TX and RX should be same length lists")
logger.error("TX and RX should be same length lists.")
return False
for i, j in zip(trlist, receiver_list):
values.append([self.port_names.index(i), self.port_names.index(j)])
Expand Down Expand Up @@ -587,12 +565,12 @@ def find_touchstone_files(input_dir):
Dictionary with the SNP file names as the key and the absolute path as the value.
"""
out = {}
if not os.path.exists(input_dir): # pragma: no cover
if not os.path.exists(input_dir):
return out
pat_snp = re.compile(r"\.s\d+p$", re.IGNORECASE)
sNpFiles = {f: os.path.join(input_dir, f) for f in os.listdir(input_dir) if re.search(pat_snp, f)}
files = {f: os.path.join(input_dir, f) for f in os.listdir(input_dir) if re.search(pat_snp, f)}
pat_ts = re.compile("\.ts$")
for f in os.listdir(input_dir):
if re.search(pat_ts, f):
sNpFiles[f] = os.path.abspath(os.path.join(input_dir, f))
return sNpFiles
files[f] = os.path.abspath(os.path.join(input_dir, f))
return files
14 changes: 14 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,17 @@ def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item
item.add_marker(pytest.mark.solvers)
elif item.nodeid.startswith(SYSTEM_GENERAL_TEST_PREFIX):
item.add_marker(pytest.mark.general)


@pytest.fixture
def touchstone_file(tmp_path):
file_path = tmp_path / "dummy.s2p"
file_content = """
! Terminal data exported
! Port[1] = Port1
! Port[2] = Port2
0.1 0.1 0.2
"""

file_path.write_text(file_content)
return file_path
66 changes: 66 additions & 0 deletions tests/integration/test_touchstone_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2021 - 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from unittest.mock import patch

from ansys.aedt.core.visualization.advanced.touchstone_parser import TouchstoneData


@patch("ansys.aedt.core.visualization.advanced.touchstone_parser.plt")
def test_plot_insertion_losses(mock_show, touchstone_file):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.plot_insertion_losses()

assert res is not []
mock_show.show.assert_called_once()


@patch.object(TouchstoneData, "plot_s_db")
@patch("ansys.aedt.core.visualization.advanced.touchstone_parser.plt")
def test_plot(mock_show, mock_plot_s_db, touchstone_file):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.plot(show=True)

assert res
mock_show.show.assert_called_once()


@patch.object(TouchstoneData, "plot_s_db")
@patch("ansys.aedt.core.visualization.advanced.touchstone_parser.plt")
def test_plot_next_xtalk_losses(mock_show, mock_plot_s_db, touchstone_file):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.plot_next_xtalk_losses()

assert res
mock_show.show.assert_called_once()


@patch.object(TouchstoneData, "plot_s_db")
@patch("ansys.aedt.core.visualization.advanced.touchstone_parser.plt")
def test_plot_fext_xtalk_losses(mock_show, mock_plot_s_db, touchstone_file):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.plot_fext_xtalk_losses("Port", "Port")

assert res
mock_show.show.assert_called_once()
59 changes: 58 additions & 1 deletion tests/system/general/test_44_TouchstoneParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import logging
import os

from ansys.aedt.core import Hfss3dLayout
from ansys.aedt.core.visualization.advanced.touchstone_parser import TouchstoneData
from ansys.aedt.core.visualization.advanced.touchstone_parser import find_touchstone_files
from mock import patch
import pytest

from tests import TESTS_GENERAL_PATH
Expand Down Expand Up @@ -57,7 +61,6 @@ def test_01_get_touchstone_data(self):
assert ts_data.get_fext_xtalk_index_from_prefix("diff1", "diff2")

def test_02_read_ts_file(self):
from ansys.aedt.core.visualization.advanced.touchstone_parser import TouchstoneData

ts1 = TouchstoneData(touchstone_file=os.path.join(test_T44_dir, "port_order_1234.s8p"))
assert ts1.get_mixed_mode_touchstone_data()
Expand All @@ -77,3 +80,57 @@ def test_03_check_touchstone_file(self):
assert v[1]
elif v and v[0] == "causality":
assert not v[1]


def test_get_mixed_mode_touchstone_data_failure(touchstone_file, caplog: pytest.LogCaptureFixture):
ts = TouchstoneData(touchstone_file=touchstone_file)

assert not ts.get_mixed_mode_touchstone_data(port_ordering="12")
assert [
record
for record in caplog.records
if record.levelno == logging.ERROR and record.message == "Invalid input provided for 'port_ordering'."
]


def test_get_return_loss_index_with_dummy_prefix(touchstone_file):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.get_return_loss_index(excitation_name_prefix="dummy_prefix")

assert not res


def test_get_insertion_loss_index_from_prefix_failure(touchstone_file, caplog: pytest.LogCaptureFixture):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.get_insertion_loss_index_from_prefix("Port", "Dummy")

assert not res
assert [
record
for record in caplog.records
if record.levelno == logging.ERROR and record.message == "TX and RX should be same length lists."
]


def test_get_next_xtalk_index_with_dummy_prefix(touchstone_file):
ts = TouchstoneData(touchstone_file=touchstone_file)
res = ts.get_next_xtalk_index("Dummy")

assert not res


@patch("os.path.exists", return_value=False)
def test_find_touchstone_files_with_non_existing_directory(mock_exists):
res = find_touchstone_files("dummy_path")

assert res == {}


@patch("os.path.exists", return_value=True)
@patch("os.listdir")
def test_find_touchstone_files_success(mock_listdir, mock_exists):
mock_listdir.return_value = {"dummy.ts", "dummy.txt"}
res = find_touchstone_files("dummy_path")

assert "dummy.ts" in res
assert "dummy.txt" not in res

0 comments on commit 3c8503b

Please sign in to comment.