Skip to content

hfss fixes for export_touchstone() #1166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion _unittest/test_12_PostProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,26 @@ def test_03_get_solution_data(self):
assert os.path.exists(os.path.join(self.local_scratch.path, "output.csv"))

def test_04_export_touchstone(self):
self.aedtapp.export_touchstone("Setup1", "Sweep", os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p"))
setup_name = "Setup1"
sweep_name = "Sweep"
self.aedtapp.export_touchstone(
setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p")
)
assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p"))

sweep_name = None
self.aedtapp.export_touchstone(
setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep2.S2p")
)
assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep2.S2p"))
setup_name = None
self.aedtapp.export_touchstone(
setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep3.S2p")
)
assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep3.S2p"))

assert self.aedtapp.export_touchstone(setup_name, sweep_name)

@pytest.mark.skipif(config["build_machine"] == True, reason="Not running in non-graphical mode")
def test_05_export_report_to_jpg(self):

Expand Down
9 changes: 8 additions & 1 deletion _unittest/test_21_Circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,14 @@ def test_17_create_setup(self):
def test_18_export_touchstone(self):
assert self.aedtapp.analyze_nominal()
time.sleep(30)
assert self.aedtapp.export_touchstone("Dom_LNA", "Dom_LNA", os.path.join(self.local_scratch.path, "new.s2p"))
solution_name = "Dom_LNA"
sweep_name = None
file_name = os.path.join(self.local_scratch.path, "new.s2p")
assert self.aedtapp.export_touchstone(solution_name, sweep_name, file_name)
assert os.path.exists(file_name)
assert self.aedtapp.existing_analysis_sweeps[0] == solution_name
assert self.aedtapp.setup_names[0] == solution_name
assert self.aedtapp.export_touchstone(solution_name, sweep_name)

def test_19A_create_sweeps(self):
setup_name = "Sweep_LNA"
Expand Down
7 changes: 6 additions & 1 deletion _unittest/test_41_3dlayout_modeler.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,13 @@ def test_19B_analyze_setup(self):
@pytest.mark.skipif(os.name == "posix", reason="To be investigated on linux.")
def test_19C_export_touchsthone(self):
filename = os.path.join(scratch_path, "touchstone.s2p")
assert self.aedtapp.export_touchstone("RFBoardSetup3", "Last Adaptive", filename, [], [])
solution_name = "RFBoardSetup3"
sweep_name = "Last Adaptive"
assert self.aedtapp.export_touchstone(solution_name, sweep_name, filename)
assert os.path.exists(filename)
assert self.aedtapp.export_touchstone(solution_name)
sweep_name = None
assert self.aedtapp.export_touchstone(solution_name, sweep_name)

def test_19D_export_to_hfss(self):
with Scratch(scratch_path) as local_scratch:
Expand Down
117 changes: 117 additions & 0 deletions pyaedt/application/Analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1709,3 +1709,120 @@ def submit_job(
f1.write(line)
f1.close()
return self.odesktop.SubmitJob(os.path.join(project_path, "Job_settings.areg"), project_file)

@pyaedt_function_handler()
def _export_touchstone(
self, solution_name=None, sweep_name=None, file_name=None, variations=None, variations_value=None
):
"""Export the Touchstone file to a local folder.
Parameters
----------
solution_name : str, optional
Name of the solution that has been solved.
sweep_name : str, optional
Name of the sweep that has been solved.
This parameter has to be ignored or set with same value as solution_name
file_name : str, optional
Full path and name for the Touchstone file. The default is ``None``,
which exports the file to the working directory.
variations : list, optional
List of all parameter variations. For example, ``["$AmbientTemp", "$PowerIn"]``.
The default is ``None``.
variations_value : list, optional
List of all parameter variation values. For example, ``["22cel", "100"]``.
The default is ``None``.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
if variations is None:
variations = list(self.available_variations.nominal_w_values_dict.keys())
if variations_value is None:
variations_value = [str(x) for x in list(self.available_variations.nominal_w_values_dict.values())]

if solution_name is None:
nominal_sweep_list = [x.strip() for x in self.nominal_sweep.split(":")]
solution_name = nominal_sweep_list[0]
if self.design_type == "Circuit Design":
sweep_name = solution_name
else:
if sweep_name is None:
for sol in self.existing_analysis_sweeps:
if solution_name == sol.split(":")[0].strip():
sweep_name = sol.split(":")[1].strip()
break

if self.design_type == "HFSS 3D Layout Design":
n = str(len(self.port_list))
else:
n = str(len(self.excitations))
# Normalize the save path
if not file_name:
appendix = ""
for v, vv in zip(variations, variations_value):
appendix += "_" + v + vv.replace("'", "")
ext = ".S" + n + "p"
filename = os.path.join(self.working_directory, solution_name + "_" + sweep_name + appendix + ext)
else:
filename = file_name.replace("//", "/").replace("\\", "/")
self.logger.info("Exporting Touchstone " + filename)
DesignVariations = ""
for i in range(len(variations)):
DesignVariations += str(variations[i]) + "='" + str(variations_value[i].replace("'", "")) + "' "
# DesignVariations = "$AmbientTemp=\'22cel\' $PowerIn=\'100\'"
# array containing "SetupName:SolutionName" pairs (note that setup and solution are separated by a colon)
SolutionSelectionArray = [solution_name + ":" + sweep_name]
# 2=tab delimited spreadsheet (.tab), 3= touchstone (.sNp), 4= CitiFile (.cit),
# 7=Matlab (.m), 8=Terminal Z0 spreadsheet
FileFormat = 3
OutFile = filename # full path of output file
# array containin the frequencies to export, use ["all"] for all frequencies
FreqsArray = ["all"]
DoRenorm = True # perform renormalization before export
RenormImped = 50 # Real impedance value in ohm, for renormalization
DataType = "S" # Type: "S", "Y", or "Z" matrix to export
Pass = -1 # The pass to export. -1 = export all passes.
ComplexFormat = 0 # 0=Magnitude/Phase, 1=Real/Immaginary, 2=dB/Phase
DigitsPrecision = 15 # Touchstone number of digits precision
IncludeGammaImpedance = True # Include Gamma and Impedance in comments
NonStandardExtensions = False # Support for non-standard Touchstone extensions

if self.design_type == "HFSS":
self.osolution.ExportNetworkData(
DesignVariations,
SolutionSelectionArray,
FileFormat,
OutFile,
FreqsArray,
DoRenorm,
RenormImped,
DataType,
Pass,
ComplexFormat,
DigitsPrecision,
False,
IncludeGammaImpedance,
NonStandardExtensions,
)
else:
self.odesign.ExportNetworkData(
DesignVariations,
SolutionSelectionArray,
FileFormat,
OutFile,
FreqsArray,
DoRenorm,
RenormImped,
DataType,
Pass,
ComplexFormat,
DigitsPrecision,
False,
IncludeGammaImpedance,
NonStandardExtensions,
)
self.logger.info("Touchstone correctly exported to %s", filename)
return True
77 changes: 15 additions & 62 deletions pyaedt/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,19 +762,21 @@ def import_touchstone_solution(self, filename, solution_name="Imported_Data"):
return portnames

@pyaedt_function_handler()
def export_touchstone(self, solutionname, sweepname, filename=None, variation=None, variations_value=None):
def export_touchstone(
self, solution_name=None, sweep_name=None, file_name=None, variations=None, variations_value=None
):
"""Export the Touchstone file to a local folder.

Parameters
----------
solutionname : str
solution_name : str, optional
Name of the solution that has been solved.
sweepname : str
sweep_name : str, optional
Name of the sweep that has been solved.
filename : str, optional
Full path and name for the Touchstone file. The default is ``None``,
which exports the file to the working directory.
variation : list, optional
file_name : str, optional
Full path and name for the Touchstone file.
The default is ``None``, in which case the file is exported to the working directory.
variations : list, optional
List of all parameter variations. For example, ``["$AmbientTemp", "$PowerIn"]``.
The default is ``None``.
variations_value : list, optional
Expand All @@ -791,62 +793,13 @@ def export_touchstone(self, solutionname, sweepname, filename=None, variation=No

>>> oDesign.ExportNetworkData
"""
if variation == None:
variation = []
if variations_value == None:
variations_value = []

# Normalize the save path
if not filename:
appendix = ""
for v, vv in zip(variation, variations_value):
appendix += "_" + v + vv.replace("'", "")
ext = ".S" + str(self.oboundary.GetNumExcitations()) + "p"
filename = os.path.join(self.working_directory, solutionname + "_" + sweepname + appendix + ext)
else:
filename = filename.replace("//", "/").replace("\\", "/")
self.logger.info("Exporting Touchstone " + filename)
DesignVariations = ""
i = 0
for el in variation:
DesignVariations += str(variation[i]) + "='" + str(variations_value[i].replace("'", "")) + "' "
i += 1
# DesignVariations = "$AmbientTemp=\'22cel\' $PowerIn=\'100\'"
# array containing "SetupName:SolutionName" pairs (note that setup and solution are separated by a colon)
SolutionSelectionArray = [solutionname + ":" + sweepname]
# 2=tab delimited spreadsheet (.tab), 3= touchstone (.sNp), 4= CitiFile (.cit),
# 7=Matlab (.m), 8=Terminal Z0 spreadsheet
FileFormat = 3
OutFile = filename # full path of output file
# array containin the frequencies to export, use ["all"] for all frequencies
FreqsArray = ["all"]
DoRenorm = True # perform renormalization before export
RenormImped = 50 # Real impedance value in ohm, for renormalization
DataType = "S" # Type: "S", "Y", or "Z" matrix to export
Pass = -1 # The pass to export. -1 = export all passes.
ComplexFormat = 0 # 0=Magnitude/Phase, 1=Real/Immaginary, 2=dB/Phase
DigitsPrecision = 15 # Touchstone number of digits precision
IncludeGammaImpedance = True # Include Gamma and Impedance in comments
NonStandardExtensions = False # Support for non-standard Touchstone extensions

self.odesign.ExportNetworkData(
DesignVariations,
SolutionSelectionArray,
FileFormat,
OutFile,
FreqsArray,
DoRenorm,
RenormImped,
DataType,
Pass,
ComplexFormat,
DigitsPrecision,
False,
IncludeGammaImpedance,
NonStandardExtensions,
return self._export_touchstone(
solution_name=solution_name,
sweep_name=sweep_name,
file_name=file_name,
variations=variations,
variations_value=variations_value,
)
self.logger.info("Touchstone correctly exported to %s", filename)
return True

@pyaedt_function_handler()
def export_fullwave_spice(
Expand Down
74 changes: 16 additions & 58 deletions pyaedt/hfss.py
Original file line number Diff line number Diff line change
Expand Up @@ -4178,81 +4178,39 @@ def create_qfactor_report(self, project_dir, outputlist, setupname, plotname, Xa
return True

@pyaedt_function_handler()
def export_touchstone(self, solutionname, sweepname, filename=None, variation=[], variations_value=[]):
def export_touchstone(
self, solution_name=None, sweep_name=None, file_name=None, variations=None, variations_value=None
):
"""Export the Touchstone file to a local folder.

Parameters
----------
solutionname : str
solution_name : str, optional
Name of the solution that has been solved.
sweepname : str
sweep_name : str, optional
Name of the sweep that has been solved.
filename : str, optional
Full path and name for the output file.
file_name : str, optional
Full path and name for the Touchstone file.
The default is ``None``, in which case the file is exported to the working directory.
variation : list, optional
variations : list, optional
List of all parameter variations. For example, ``["$AmbientTemp", "$PowerIn"]``.
The default is ``[]``.
The default is ``None``.
variations_value : list, optional
List of all parameter variation values. For example, ``["22cel", "100"]``.
The default is ``[]``.
The default is ``None``.

Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""

# Normalize the save path
if not filename:
appendix = ""
for v, vv in zip(variation, variations_value):
appendix += "_" + v + vv.replace("'", "")
ext = ".S" + str(self.oboundary.GetNumExcitations()) + "p"
filename = os.path.join(self.working_directory, solutionname + "_" + sweepname + appendix + ext)
else:
filename = filename.replace("//", "/").replace("\\", "/")
print("Exporting Touchstone " + filename)
DesignVariations = ""
i = 0
for el in variation:
DesignVariations += str(variation[i]) + "='" + str(variations_value[i].replace("'", "")) + "' "
i += 1
# DesignVariations = "$AmbientTemp=\'22cel\' $PowerIn=\'100\'"
# array containing "SetupName:SolutionName" pairs (note that setup and solution are separated by a colon)
SolutionSelectionArray = [solutionname + ":" + sweepname]
# 2=tab delimited spreadsheet (.tab), 3= touchstone (.sNp), 4= CitiFile (.cit),
# 7=Matlab (.m), 8=Terminal Z0 spreadsheet
FileFormat = 3
OutFile = filename # full path of output file
# array containin the frequencies to export, use ["all"] for all frequencies
FreqsArray = ["all"]
DoRenorm = True # perform renormalization before export
RenormImped = 50 # Real impedance value in ohm, for renormalization
DataType = "S" # Type: "S", "Y", or "Z" matrix to export
Pass = -1 # The pass to export. -1 = export all passes.
ComplexFormat = 0 # 0=Magnitude/Phase, 1=Real/Immaginary, 2=dB/Phase
DigitsPrecision = 15 # Touchstone number of digits precision
IncludeGammaImpedance = True # Include Gamma and Impedance in comments
NonStandardExtensions = False # Support for non-standard Touchstone extensions

self.osolution.ExportNetworkData(
DesignVariations,
SolutionSelectionArray,
FileFormat,
OutFile,
FreqsArray,
DoRenorm,
RenormImped,
DataType,
Pass,
ComplexFormat,
DigitsPrecision,
False,
IncludeGammaImpedance,
NonStandardExtensions,
return self._export_touchstone(
solution_name=solution_name,
sweep_name=sweep_name,
file_name=file_name,
variations=variations,
variations_value=variations_value,
)
return True

@pyaedt_function_handler()
def set_export_touchstone(self, activate, export_dir=""):
Expand Down
Loading