diff --git a/README.md b/README.md index 52cf951..7f6ea0d 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,11 @@ If they are not filled in, it should be 1 * `margin/xy` - mesh grid pitch in x and y direction (micrometers) outside of the board area * `margin/z` - mesh grid pitch in z direction (micrometers) outside of the board area. +##### Output +`Output` set format of output image (Not mandatory) +* `format` - Set image output format [png, svg, tiff] (default: png) +* `dpi` - Set DPI of output image (default: 600) + ##### Ports `ports` is a list of ports. Each port has the following parameters: diff --git a/examples/basic/simulation.json b/examples/basic/simulation.json index a7ab093..63b30f8 100644 --- a/examples/basic/simulation.json +++ b/examples/basic/simulation.json @@ -21,6 +21,10 @@ "xy": 3000, "z": 3000 }, + "output": { + "format": "tiff", + "dpi": 800 + }, "ports": [ { "width": 400, diff --git a/examples/differential/simulation.json b/examples/differential/simulation.json index cb0e66a..e0b4a20 100644 --- a/examples/differential/simulation.json +++ b/examples/differential/simulation.json @@ -21,6 +21,9 @@ "xy": 3000, "z": 3000 }, + "output": { + "format": "svg" + }, "ports": [ { "width": 500, diff --git a/src/gerber2ems/config.py b/src/gerber2ems/config.py index cf5e881..332694d 100644 --- a/src/gerber2ems/config.py +++ b/src/gerber2ems/config.py @@ -155,6 +155,12 @@ def get( return default +class OutputConfig: + def __init__(self, format, dpi): + self.format = format + self.dpi = dpi + + class Config: """Class representing and parsing config.""" @@ -203,6 +209,9 @@ def __init__(self, json: Any, args: Any) -> None: self.via_plating = int(get(json, ["via", "plating_thickness"], (int, float), 50)) self.via_filling_epsilon = float(get(json, ["via", "filling_epsilon"], (int, float), 1)) + format = get(json, ["output", "format"], str, "png") + dpi = get(json, ["output", "dpi"], int, 600) + self.output_cfg = OutputConfig(format, dpi) self.arguments = args ports = get(json, ["ports"], list) diff --git a/src/gerber2ems/main.py b/src/gerber2ems/main.py index 1220762..cc3e88a 100755 --- a/src/gerber2ems/main.py +++ b/src/gerber2ems/main.py @@ -117,7 +117,7 @@ def postprocess(sim: Simulation) -> None: add_virtual_ports(sim) frequencies = np.linspace(Config.get().start_frequency, Config.get().stop_frequency, 1001) - post = Postprocesor(frequencies, len(Config.get().ports)) + post = Postprocesor(frequencies, len(Config.get().ports), Config.get().output_cfg) impedances = np.array([p.impedance for p in Config.get().ports]) post.add_impedances(impedances) diff --git a/src/gerber2ems/postprocess.py b/src/gerber2ems/postprocess.py index 19f7402..46ea687 100644 --- a/src/gerber2ems/postprocess.py +++ b/src/gerber2ems/postprocess.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt import skrf -from gerber2ems.config import Config +from gerber2ems.config import Config, OutputConfig from gerber2ems.constants import RESULTS_DIR, PLOT_STYLE logger = logging.getLogger(__name__) @@ -15,8 +15,17 @@ class Postprocesor: """Class used to postprocess and display simulation data.""" + def save_figure(self, fig, name, **kwargs): + """Abstraction level to save figure""" + dst = os.path.join(os.getcwd(), RESULTS_DIR, name) + dst = f"{dst}.{self.out_cfg.format}" - def __init__(self, frequencies: np.ndarray, port_count: int) -> None: + if self.out_cfg.dpi: + fig.savefig(dst, format=self.out_cfg.format, dpi=self.out_cfg.dpi, **kwargs) + else: + fig.savefig(dst, format=self.out_cfg.format, **kwargs) + + def __init__(self, frequencies: np.ndarray, port_count: int, output_config: OutputConfig) -> None: """Initialize postprocessor.""" self.frequencies = frequencies # Frequency list for whitch parameters are calculated self.count = port_count # Number of ports @@ -42,6 +51,8 @@ def __init__(self, frequencies: np.ndarray, port_count: int) -> None: [self.count, self.count, len(self.frequencies)], np.float64 ) # Group delay table ([output_port][input_port][frequency]) + self.out_cfg = output_config + def add_port_data( self, port: int, @@ -133,7 +144,7 @@ def render_s_params(self): axes.set_xlabel("Frequency, f [GHz]") axes.set_ylabel("Magnitude, [dB]") axes.grid(True) - fig.savefig(os.path.join(os.getcwd(), RESULTS_DIR, f"S_x{i+1}.png")) + self.save_figure(fig, f"S_x{i+1}") def render_diff_pair_s_params(self): """Render differential pair S parameter plots to files.""" @@ -174,7 +185,7 @@ def render_diff_pair_s_params(self): axes.set_xlabel("Frequency, f [GHz]") axes.set_ylabel("Magnitude, [dB]") axes.grid(True) - fig.savefig(os.path.join(os.getcwd(), RESULTS_DIR, f"SDD_{pair.name}")) + self.save_figure(fig, f"SDD_{pair.name}") def render_diff_impedance(self): """Render differential pair impedance plots to files.""" @@ -218,10 +229,7 @@ def render_diff_impedance(self): axs[0].grid(True) axs[1].grid(True) - fig.savefig( - os.path.join(os.getcwd(), RESULTS_DIR, f"Z_diff_{pair.name}.png"), - bbox_inches="tight", - ) + self.save_figure(fig, f"Z_diff_{pair.name}", bbox_inches="tight") else: logger.error( f"Reference impedances for ports in differential pair {pair.name} are not all equal. Cannot calculate impedance" # noqa: E501 @@ -263,10 +271,7 @@ def render_impedance(self, include_margins=False): axs[0].axhline(np.real(min_z), color="red") axs[0].axhline(np.real(max_z), color="red") - fig.savefig( - os.path.join(os.getcwd(), RESULTS_DIR, f"Z_{port+1}.png"), - bbox_inches="tight", - ) + self.save_figure(fig, f"Z_{port+1}", bbox_inches="tight") def render_smith(self): """Render port reflection smithcharts to files.""" @@ -286,10 +291,7 @@ def render_smith(self): show_legend=True, draw_vswr=[vswr_margin], ) - fig.savefig( - os.path.join(os.getcwd(), RESULTS_DIR, f"S_{port+1}{port+1}_smith.png"), - bbox_inches="tight", - ) + self.save_figure(fig, f"S_{port+1}{port+1}_smith", bbox_inches="tight") def render_trace_delays(self): """Render all trace delay plots to files.""" @@ -307,7 +309,7 @@ def render_trace_delays(self): axes.set_xlabel("Frequency, f [GHz]") axes.set_ylabel("Trace delay, [ns]") axes.grid(True) - fig.savefig(os.path.join(os.getcwd(), RESULTS_DIR, f"{trace.name}_delay.png")) + self.save_figure(fig, f"{trace.name}_delay") for pair in Config.get().diff_pairs: if ( @@ -330,7 +332,7 @@ def render_trace_delays(self): axes.set_xlabel("Frequency, f [GHz]") axes.set_ylabel("Trace delay, [ns]") axes.grid(True) - fig.savefig(os.path.join(os.getcwd(), RESULTS_DIR, f"{pair.name}_delay.png")) + self.save_figure(fig, f"{pair.name}_delay") def save_to_file(self) -> None: """Save all parameters to files."""