diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 3c6c63271ab..4ba4a7bb7a4 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -57,8 +57,12 @@ def teardown_class(self): BasisTest.my_teardown(self) def test_01B_Field_Plot(self): + assert len(self.aedtapp.post.available_display_types()) > 0 + assert len(self.aedtapp.post.available_report_types) > 0 + assert len(self.aedtapp.post.available_report_quantities()) > 0 cutlist = ["Global:XY", "Global:XZ", "Global:YZ"] setup_name = self.aedtapp.existing_analysis_sweeps[0] + assert self.aedtapp.setups[0].is_solved quantity_name = "ComplexMag_E" intrinsic = {"Freq": "5GHz", "Phase": "180deg"} min_value = self.aedtapp.post.get_scalar_field_value(quantity_name, "Minimum", setup_name, intrinsics="5GHz") @@ -254,6 +258,7 @@ def test_09_manipulate_report(self): assert data.primary_sweep == "Freq" assert data.expressions[0] == "S(1,1)" assert len(self.aedtapp.post.all_report_names) > 0 + variations = self.field_test.available_variations.nominal_w_values_dict variations["Theta"] = ["All"] variations["Phi"] = ["All"] @@ -511,7 +516,7 @@ def test_09h_add_line_from_point(self): # pragma: no cover config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." ) def test_09l_add_note(self): # pragma: no cover - new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") + new_report = self.aedtapp.post.reports_by_category.modal_solution() new_report.create() new_report.add_note("Test", 8000, 1500) @@ -608,8 +613,11 @@ def test_16_create_field_plot(self): assert plot def test_17_circuit(self): + assert not self.circuit_test.setups[0].is_solved + self.circuit_test.analyze_setup("LNA") self.circuit_test.analyze_setup("Transient") + assert self.circuit_test.setups[0].is_solved assert self.circuit_test.post.create_report(["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"], "LNA") new_report = self.circuit_test.post.reports_by_category.standard( ["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"], "LNA" @@ -648,10 +656,21 @@ def test_17_circuit(self): assert self.circuit_test.post.create_report( ["dB(V(net_11))", "dB(V(Port1))"], domain="Spectrum", setup_sweep_name="Transient" ) + new_report = self.circuit_test.post.reports_by_category.spectral(None, "Transient") + new_report.window = "Hanning" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = True + assert new_report.create() pass def test_18_diff_plot(self): + assert len(self.diff_test.post.available_display_types()) > 0 + assert len(self.diff_test.post.available_report_types) > 0 + assert len(self.diff_test.post.available_report_quantities()) > 0 self.diff_test.analyze_setup("LinearFrequency") + assert self.diff_test.setups[0].is_solved variations = self.diff_test.available_variations.nominal_w_values_dict variations["Freq"] = ["All"] variations["l1"] = ["All"] @@ -725,6 +744,7 @@ def test_54_reload(self): @pytest.mark.skipif(is_ironpython, reason="plot_scene method is not supported in ironpython") def test_55_time_plot(self): self.sbr_test.analyze_nominal(use_auto_settings=False) + assert self.sbr_test.setups[0].is_solved solution_data = self.sbr_test.post.get_solution_data( expressions=["NearEX", "NearEY", "NearEZ"], variations={"_u": ["All"], "_v": ["All"], "Freq": ["All"]}, @@ -778,6 +798,8 @@ def test_57_test_export_q2d_results(self): new_report = self.q2dtest.post.reports_by_category.rl_fields("Mag_H", polyline="Poly1") assert new_report.create() assert len(self.q2dtest.post.plots) == 3 + new_report = self.q2dtest.post.reports_by_category.standard() + assert new_report.get_solution_data() def test_58_test_no_report(self): assert not self.aedtapp.post.reports_by_category.eye_diagram() diff --git a/_unittest/test_20_HFSS.py b/_unittest/test_20_HFSS.py index 082f7e0c4c9..c60224e5865 100644 --- a/_unittest/test_20_HFSS.py +++ b/_unittest/test_20_HFSS.py @@ -127,6 +127,7 @@ def test_06a_create_linear_count_sweep(self): setup.props["MaximumPasses"] = 1 assert setup.update() assert self.aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401) + assert not self.aedtapp.setups[0].sweeps[0].is_solved assert self.aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401) assert self.aedtapp.create_linear_count_sweep( setupname="MySetup", diff --git a/pyaedt/application/design_solutions.py b/pyaedt/application/design_solutions.py index fd7b6ad66bd..68e5babaddc 100644 --- a/pyaedt/application/design_solutions.py +++ b/pyaedt/application/design_solutions.py @@ -336,14 +336,14 @@ "options": "TemperatureAndFlow", "report_type": "Monitor", "default_setup": 11, - "default_adaptive": None, + "default_adaptive": "SteadyState", }, "Transient": { "name": "Transient", "options": "TemperatureAndFlow", "report_type": "Monitor", "default_setup": 36, - "default_adaptive": None, + "default_adaptive": "Transient", }, }, "RMxprtSolution": { diff --git a/pyaedt/modules/PostProcessor.py b/pyaedt/modules/PostProcessor.py index 0ac82c5495e..912904c01ea 100644 --- a/pyaedt/modules/PostProcessor.py +++ b/pyaedt/modules/PostProcessor.py @@ -24,7 +24,7 @@ "HFSS": [ "Modal Solution Data", "Terminal Solution Data", - "EigenMode Parameters", + "Eigenmode Parameters", "Fields", "Far Fields", "Emissions", @@ -55,6 +55,7 @@ "Icepak": ["Monitor", "Fields"], "Circuit Design": ["Standard", "Eye Diagram", "Spectrum"], "HFSS 3D Layout": ["Standard", "Fields", "Spectrum"], + "HFSS 3D Layout Design": ["Standard", "Fields", "Spectrum"], "Mechanical": ["Standard", "Fields"], "Q3D Extractor": ["Matrix", "CG Fields", "DC R/L Fields", "AC R/L Fields"], "2D Extractor": ["Matrix", "CG Fields", "RL Fields"], @@ -73,7 +74,7 @@ "Far Fields": rt.FarField, "Near Fields": rt.NearField, "Eye Diagram": rt.EyeDiagram, - "EigenMode Parameters": rt.Standard, + "Eigenmode Parameters": rt.Standard, "Spectrum": rt.Spectral, } @@ -481,8 +482,8 @@ def eigenmode(self, expressions=None, setup_name=None): """ if not setup_name: setup_name = self._post_app._app.nominal_sweep - if "EigenMode Parameters" in self._templates: - rep = rt.Standard(self._post_app, "EigenMode Parameters", setup_name) + if "Eigenmode Parameters" in self._templates: + rep = rt.Standard(self._post_app, "Eigenmode Parameters", setup_name) rep.expressions = expressions return rep return @@ -609,6 +610,113 @@ def __init__(self, app): self.plots = self._get_plot_inputs() self.reports_by_category = Reports(self, self._app.design_type) + @property + def available_report_types(self): + """Report types. + + References + ---------- + + >>> oModule.GetAvailableReportTypes + """ + return list(self.oreportsetup.GetAvailableReportTypes()) + + @pyaedt_function_handler() + def available_display_types(self, report_category=None): + """Retrieve display types for a report categories. + + Parameters + ---------- + report_category : str, optional + Type of the report. The default value is ``None``. + + Returns + ------- + list + List of available report categories. + + References + ---------- + >>> oModule.GetAvailableDisplayTypes + """ + if not report_category: + report_category = self.available_report_types[0] + if report_category: + return list(self.oreportsetup.GetAvailableDisplayTypes(report_category)) + return [] + + @pyaedt_function_handler() + def available_quantities_categories(self, report_category=None, display_type=None, solution=None, context=""): + """Compute the list of all available report categories. + + Parameters + ---------- + report_category : str, optional + Report Category. Default is `None` which will take first default category. + display_type : str, optional + Report Display Type. + Default is `None` which will take first default type which is in most of the case "Rectangular Plot". + solution : str, optional + Report Setup. Default is `None` which will take first nominal_adpative solution. + context : str, optional + Report Category. Default is `""` which will take first default context. + + Returns + ------- + list + """ + if not report_category: + report_category = self.available_report_types[0] + if not display_type: + display_type = self.available_display_types(report_category)[0] + if not solution: + solution = self._app.nominal_adaptive + if solution and report_category and display_type: + return list(self.oreportsetup.GetAllCategories(report_category, display_type, solution, context)) + return [] + + @pyaedt_function_handler() + def available_report_quantities( + self, report_category=None, display_type=None, solution=None, quantities_category=None, context="" + ): + """Compute the list of all available report quantities of a given report quantity category. + + Parameters + ---------- + report_category : str, optional + Report Category. Default is `None` which will take first default category. + display_type : str, optional + Report Display Type. + Default is `None` which will take first default type which is in most of the case "Rectangular Plot". + solution : str, optional + Report Setup. Default is `None` which will take first nominal_adpative solution. + quantities_category : str, optional + The category to which quantities belong. It has to be one of `available_quantities_categories` method. + Default is `None` which will take first default quantity.". + context : str, optional + Report Category. Default is `""` which will take first default context. + + Returns + ------- + list + """ + if not report_category: + report_category = self.available_report_types[0] + if not display_type: + display_type = self.available_display_types(report_category)[0] + if not solution: + solution = self._app.nominal_adaptive + if not quantities_category: + categories = self.available_quantities_categories(report_category, display_type, solution, context) + quantities_category = categories[0] if categories else None + if quantities_category and display_type and report_category and solution: + return list( + self.oreportsetup.GetAllQuantities( + report_category, display_type, solution, context, quantities_category + ) + ) + return None + @pyaedt_function_handler() def _get_plot_inputs(self): names = self._app.get_oo_name(self.oreportsetup) @@ -1013,12 +1121,15 @@ def get_solution_data_per_variation( if not setup_sweep_name: setup_sweep_name = self._app.nominal_adaptive sweep_list = _convert_dict_to_report_sel(sweeps) - - data = list( - self.oreportsetup.GetSolutionDataPerVariation(soltype, setup_sweep_name, ctxt, sweep_list, expression) - ) - self.logger.info("Solution Data Correctly Loaded.") - return SolutionData(data) + try: + data = list( + self.oreportsetup.GetSolutionDataPerVariation(soltype, setup_sweep_name, ctxt, sweep_list, expression) + ) + self.logger.info("Solution Data Correctly Loaded.") + return SolutionData(data) + except: + self.logger.warning("Solution Data failed to load. Check solution, context or expression.") + return None @pyaedt_function_handler() def steal_focus_oneditor(self): @@ -1762,37 +1873,6 @@ def ofieldsreporter(self): """ return self._app.ofieldsreporter - @property - def report_types(self): - """Report types. - - References - ---------- - - >>> oModule.GetAvailableReportTypes - """ - return list(self.oreportsetup.GetAvailableReportTypes()) - - @pyaedt_function_handler() - def display_types(self, report_type): - """Retrieve display types for a report type. - - Parameters - ---------- - report_type : str - Type of the report. - - Returns - ------- - :attr:`pyaedt.modules.PostProcessor.PostProcessor.report_types` - - References - ---------- - - >>> oModule.GetAvailableDisplayTypes - """ - return self.oreportsetup.GetAvailableDisplayTypes(report_type) - @pyaedt_function_handler() def _get_base_name(self, setup): setups_data = self._app.design_properties["FieldsReporter"]["FieldsPlotManagerID"] @@ -1805,7 +1885,11 @@ def _get_base_name(self, setup): if isinstance(sim_data["SimSetup"], list): for solution in sim_data["SimSetup"]: base_name = solution["Name"] - for sol in solution["Solution"]: + if isinstance(solution["Solution"], (dict, OrderedDict)): + sols = [solution["Solution"]] + else: + sols = solution["Solution"] + for sol in sols: if sol["ID"] == setups_data[setup]["SolutionId"]: base_name += " : " + sol["Name"] return base_name diff --git a/pyaedt/modules/SetupTemplates.py b/pyaedt/modules/SetupTemplates.py index 1ec95108895..2f53aaf8ac0 100644 --- a/pyaedt/modules/SetupTemplates.py +++ b/pyaedt/modules/SetupTemplates.py @@ -1297,8 +1297,9 @@ class SweepHFSS(object): """ - def __init__(self, oanalysis, setupname, sweepname, sweeptype="Interpolating", props=None): - self.oanalysis = oanalysis + def __init__(self, app, setupname, sweepname, sweeptype="Interpolating", props=None): + self._app = app + self.oanalysis = app.omodule self.props = {} self.setupname = setupname self.name = sweepname @@ -1337,6 +1338,18 @@ def __init__(self, oanalysis, setupname, sweepname, sweeptype="Interpolating", p self.props["SMatrixOnlySolveAbove"] = "1MHz" self.props["SweepRanges"] = {"Subrange": []} + @property + def is_solved(self): + """Verify if solutions are available for given sweep. + + Returns + ------- + bool + `True` if solutions are available. + """ + sol = self._app.p_app.post.reports_by_category.standard(setup_name="{} : {}".format(self.setupname, self.name)) + return True if sol.get_solution_data() else False + @pyaedt_function_handler() def add_subrange(self, rangetype, start, end=None, count=None, unit="GHz", save_single_fields=False, clear=False): """Add a subrange to the sweep. @@ -1492,14 +1505,15 @@ class SweepHFSS3DLayout(object): def __init__( self, - oanalysis, + app, setupname, sweepname, sweeptype="Interpolating", save_fields=True, props=None, ): - self.oanalysis = oanalysis + self._app = app + self.oanalysis = app.omodule self.props = {} self.setupname = setupname self.name = sweepname @@ -1543,6 +1557,28 @@ def __init__( self.props["AllOffDiagEntries"] = False self.props["MagMinThreshold"] = 0.01 + @property + def combined_name(self): + """Compute the setupname : sweepname string. + + Returns + ------- + str + """ + return "{} : {}".format(self.setupname, self.name) + + @property + def is_solved(self): + """Verify if solutions are available for given sweep. + + Returns + ------- + bool + `True` if solutions are available. + """ + sol = self._app._app.post.reports_by_category.standard(setup_name=self.combined_name) + return True if sol.get_solution_data() else False + @pyaedt_function_handler() def change_type(self, sweeptype): """Change the type of the sweep. @@ -1738,8 +1774,9 @@ class SweepQ3D(object): """ - def __init__(self, oanalysis, setupname, sweepname, sweeptype="Interpolating", props=None): - self.oanalysis = oanalysis + def __init__(self, app, setupname, sweepname, sweeptype="Interpolating", props=None): + self._app = app + self.oanalysis = app.omodule self.setupname = setupname self.name = sweepname self.props = {} @@ -1773,6 +1810,18 @@ def __init__(self, oanalysis, setupname, sweepname, sweeptype="Interpolating", p self.props["InterpMinSolns"] = 0 self.props["InterpMinSubranges"] = 1 + @property + def is_solved(self): + """Verify if solutions are available for given sweep. + + Returns + ------- + bool + `True` if solutions are available. + """ + sol = self._app.p_app.post.reports_by_category.standard(setup_name="{} : {}".format(self.setupname, self.name)) + return True if sol.get_solution_data() else False + @pyaedt_function_handler() def add_subrange(self, type, start, end=None, count=None, unit="GHz", clear=False): """Add a subrange to the sweep. diff --git a/pyaedt/modules/SolveSetup.py b/pyaedt/modules/SolveSetup.py index cf1aa92f72f..bda75b1cd19 100644 --- a/pyaedt/modules/SolveSetup.py +++ b/pyaedt/modules/SolveSetup.py @@ -39,6 +39,24 @@ class Setup(object): """ + @property + def is_solved(self): + """Verify if solutions are available for given setup. + + Returns + ------- + bool + `True` if solutions are available. + """ + if self.p_app.design_solutions.default_adaptive: + sol = self.p_app.post.reports_by_category.standard( + setup_name="{} : {}".format(self.name, self.p_app.design_solutions.default_adaptive) + ) + else: + sol = self.p_app.post.reports_by_category.standard(setup_name=self.name) + + return True if sol.get_solution_data() else False + @property def p_app(self): """Parent.""" @@ -93,13 +111,13 @@ def __init__(self, app, solutiontype, setupname="MySetupAuto", isnewsetup=True): app.pop("MoveBackwards", None) for el in app: if isinstance(app[el], (OrderedDict, dict)): - self.sweeps.append(SweepHFSS(self.omodule, setupname, el, props=app[el])) + self.sweeps.append(SweepHFSS(self, setupname, el, props=app[el])) else: app = setup_data["Sweeps"] for el in app: if isinstance(app[el], (OrderedDict, dict)): - self.sweeps.append(SweepQ3D(self.omodule, setupname, el, props=app[el])) + self.sweeps.append(SweepQ3D(self, setupname, el, props=app[el])) setup_data.pop("Sweeps", None) self.props = SetupProps(self, OrderedDict(setup_data)) except: @@ -441,9 +459,9 @@ def add_sweep(self, sweepname=None, sweeptype="Interpolating"): self._app.logger.warning("This method only applies to HFSS and Q3d. Use add_eddy_current_sweep method.") return False if self.setuptype <= 4: - sweep_n = SweepHFSS(self.omodule, self.name, sweepname, sweeptype) + sweep_n = SweepHFSS(self, self.name, sweepname, sweeptype) else: - sweep_n = SweepQ3D(self.omodule, self.name, sweepname, sweeptype) + sweep_n = SweepQ3D(self, self.name, sweepname, sweeptype) sweep_n.create() self.sweeps.append(sweep_n) return sweep_n @@ -725,6 +743,18 @@ def __init__(self, app, solutiontype, setupname="MySetupAuto", isnewsetup=True): self.props["Name"] = setupname self.auto_update = True + @property + def is_solved(self): + """Verify if solutions are available for given setup. + + Returns + ------- + bool + `True` if solutions are available. + """ + sol = self.p_app.post.reports_by_category.standard(setup_name=self.name) + return True if sol.get_solution_data() else False + @property def name(self): """Name.""" @@ -1337,13 +1367,29 @@ def __init__(self, app, solutiontype, setupname="MySetupAuto", isnewsetup=True): app = setup_data["Data"] for el in app: if isinstance(app[el], (OrderedDict, dict)): - self.sweeps.append(SweepHFSS3DLayout(self.omodule, setupname, el, props=app[el])) + self.sweeps.append(SweepHFSS3DLayout(self, setupname, el, props=app[el])) self.props = SetupProps(self, OrderedDict(setup_data)) except: self.props = SetupProps(self, OrderedDict()) self.auto_update = True + @property + def is_solved(self): + """Verify if solutions are available for a given setup. + + Returns + ------- + bool + `True` if solutions are available. + """ + if self.props.get("SolveSetupType", "HFSS") == "HFSS": + sol = self._app.post.reports_by_category.standard(setup_name="{} : Last Adaptive".format(self.name)) + else: + sol = self._app.post.reports_by_category.standard(setup_name=self.name) + + return True if sol.get_solution_data() else False + @property def setup_type(self): """Setup type. @@ -1502,7 +1548,7 @@ def add_sweep(self, sweepname=None, sweeptype="Interpolating"): """ if not sweepname: sweepname = generate_unique_name("Sweep") - sweep_n = SweepHFSS3DLayout(self.omodule, self.name, sweepname, sweeptype) + sweep_n = SweepHFSS3DLayout(self, self.name, sweepname, sweeptype) if sweep_n.create(): self.sweeps.append(sweep_n) return sweep_n diff --git a/pyaedt/modules/report_templates.py b/pyaedt/modules/report_templates.py index 032c0190b59..981d71ab957 100644 --- a/pyaedt/modules/report_templates.py +++ b/pyaedt/modules/report_templates.py @@ -289,7 +289,7 @@ def set_symbol_properties(self, show=True, style=None, show_arrows=None, fill=No class CommonReport(object): """Provides common reports.""" - def __init__(self, app, report_category, setup_name): + def __init__(self, app, report_category, setup_name, expressions=None): self._post = app self.props = OrderedDict() self.report_category = report_category @@ -305,6 +305,8 @@ def __init__(self, app, report_category, setup_name): self.props["context"]["variations"][el] = k self.props["expressions"] = None self.props["plot_name"] = None + if expressions: + self.expressions = expressions self._is_created = True @property @@ -363,11 +365,12 @@ def expressions(self): @expressions.setter def expressions(self, value): - if not isinstance(value, list): + self.props["expressions"] = {} + if value is None: + value = [] + elif not isinstance(value, list): value = [value] for el in value: - if not self.props.get("expressions", None): - self.props["expressions"] = {} self.props["expressions"][el] = {} @property @@ -837,8 +840,27 @@ def secondary_sweep_range(self, val): def _context(self): return [] + @pyaedt_function_handler() + def update_expressions_with_defaults(self, quantities_category=None): + """Update the list of expressions by taking all the quantities from a given category. + + Parameters + ---------- + quantities_category : str, optional + Quantity category to use. If None, the default category for the specified report should be used. + + Returns + ------- + + """ + self.expressions = self._post.available_report_quantities( + self.report_category, self.report_type, self.setup, quantities_category + ) + @property def _trace_info(self): + if not self.expressions: + self.update_expressions_with_defaults() if isinstance(self.expressions, list): expr = self.expressions else: @@ -966,14 +988,16 @@ def get_solution_data(self): :class:`pyaedt.modules.solutions.SolutionData` `Solution Data object. """ + if not self.expressions: + self.update_expressions_with_defaults() solution_data = self._post.get_solution_data_per_variation( self.report_category, self.setup, self._context, self.variations, self.expressions ) - if self.primary_sweep: - solution_data.primary_sweep = self.primary_sweep if not solution_data: - self._post._app.logger.error("No Data Available. Check inputs") + self._post._app.logger.warning("No Data Available. Check inputs") return False + if self.primary_sweep: + solution_data.primary_sweep = self.primary_sweep return solution_data @pyaedt_function_handler() @@ -1783,8 +1807,8 @@ def update_trace_in_report(self, traces, setup_name=None, variations=None, conte class Standard(CommonReport): """Provides a reporting class that fits most of the application's standard reports.""" - def __init__(self, app, report_category, setup_name): - CommonReport.__init__(self, app, report_category, setup_name) + def __init__(self, app, report_category, setup_name, expressions=None): + CommonReport.__init__(self, app, report_category, setup_name, expressions) @property def sub_design_id(self): @@ -1908,8 +1932,8 @@ def _context(self): class AntennaParameters(Standard): """Provides a reporting class that fits Antenna Parameters reports in HFSS plot.""" - def __init__(self, app, report_category, setup_name, far_field_sphere=None): - Standard.__init__(self, app, report_category, setup_name) + def __init__(self, app, report_category, setup_name, far_field_sphere=None, expressions=None): + Standard.__init__(self, app, report_category, setup_name, expressions) self.far_field_sphere = far_field_sphere @property @@ -1935,8 +1959,8 @@ def _context(self): class Fields(CommonReport): """General Fields Class.""" - def __init__(self, app, report_type, setup_name): - CommonReport.__init__(self, app, report_type, setup_name) + def __init__(self, app, report_type, setup_name, expressions=None): + CommonReport.__init__(self, app, report_type, setup_name, expressions) self.domain = "Sweep" self.polyline = None self.point_number = 1001 @@ -1967,8 +1991,8 @@ def _context(self): class NearField(CommonReport): """Near Field Report Class.""" - def __init__(self, app, report_type, setup_name): - CommonReport.__init__(self, app, report_type, setup_name) + def __init__(self, app, report_type, setup_name, expressions=None): + CommonReport.__init__(self, app, report_type, setup_name, expressions) self.domain = "Sweep" @property @@ -1993,8 +2017,8 @@ def near_field(self, value): class FarField(CommonReport): """FarField Report Class.""" - def __init__(self, app, report_type, setup_name): - CommonReport.__init__(self, app, report_type, setup_name) + def __init__(self, app, report_type, setup_name, expressions=None): + CommonReport.__init__(self, app, report_type, setup_name, expressions) self.domain = "Sweep" self.primary_sweep = "Phi" self.secondary_sweep = "Theta" @@ -2027,8 +2051,8 @@ def _context(self): class EyeDiagram(CommonReport): """Eye Diagram Report Class.""" - def __init__(self, app, report_type, setup_name): - CommonReport.__init__(self, app, report_type, setup_name) + def __init__(self, app, report_type, setup_name, expressions=None): + CommonReport.__init__(self, app, report_type, setup_name, expressions) self.domain = "Time" self.time_start = "0ns" self.time_stop = "200ns" @@ -2504,16 +2528,16 @@ def export_mask_violation(self, out_file=None): class Emission(CommonReport): """Emission Report Class.""" - def __init__(self, app, report_type, setup_name): - CommonReport.__init__(self, app, report_type, setup_name) + def __init__(self, app, report_type, setup_name, expressions=None): + CommonReport.__init__(self, app, report_type, setup_name, expressions) self.domain = "Sweep" class Spectral(CommonReport): """Spectral Report from Transient data.""" - def __init__(self, app, report_type, setup_name): - CommonReport.__init__(self, app, report_type, setup_name) + def __init__(self, app, report_type, setup_name, expressions=None): + CommonReport.__init__(self, app, report_type, setup_name, expressions) self.domain = "Spectrum" self.algorithm = "FFT" self.time_start = "0ns"