diff --git a/PySpice/Probe/WaveForm.py b/PySpice/Probe/WaveForm.py index ca92d15f..d86b4dd9 100644 --- a/PySpice/Probe/WaveForm.py +++ b/PySpice/Probe/WaveForm.py @@ -244,7 +244,7 @@ class Analysis: ############################################## - def __init__(self, simulation, nodes=(), branches=(), elements=(), internal_parameters=()): + def __init__(self, simulation, nodes=(), branches=(), elements=(), internal_parameters=(), measurements={}): # Fixme: branches are elements in fact, and elements is not yet supported ... @@ -254,6 +254,7 @@ def __init__(self, simulation, nodes=(), branches=(), elements=(), internal_para self._branches = {waveform.name:waveform for waveform in branches} self._elements = {waveform.name:waveform for waveform in elements} self._internal_parameters = {waveform.name:waveform for waveform in internal_parameters} + self.measurements = measurements ############################################## @@ -291,6 +292,8 @@ def _get_item(self, name): return self._elements[name] elif name in self._internal_parameters: return self._internal_parameters[name] + elif name in self.measurements: + return self.measurements[name] else: raise IndexError(name) @@ -320,7 +323,8 @@ def __getattr__(self, name): 'Nodes :' + os.linesep + self._format_dict(self._nodes) + os.linesep + 'Branches :' + os.linesep + self._format_dict(self._branches) + os.linesep + 'Elements :' + os.linesep + self._format_dict(self._elements) + os.linesep + - 'Internal Parameters :' + os.linesep + self._format_dict(self._internal_parameters) + 'Internal Parameters :' + os.linesep + self._format_dict(self._internal_parameters) + + 'Measurements :' + os.linesep + self._format_dict(self.measurements) ) #################################################################################################### diff --git a/PySpice/Spice/NgSpice/Shared.py b/PySpice/Spice/NgSpice/Shared.py index 183c08a4..14d5936e 100644 --- a/PySpice/Spice/NgSpice/Shared.py +++ b/PySpice/Spice/NgSpice/Shared.py @@ -262,28 +262,31 @@ def elements(self, abscissa=None): ############################################## - def to_analysis(self): + def to_analysis(self, measurements={}): if self.plot_name.startswith('op'): - return self._to_operating_point_analysis() + analysis = self._to_operating_point_analysis() elif self.plot_name.startswith('sens'): - return self._to_sensitivity_analysis() + analysis = self._to_sensitivity_analysis() elif self.plot_name.startswith('dc'): - return self._to_dc_analysis() + analysis = self._to_dc_analysis() elif self.plot_name.startswith('ac'): - return self._to_ac_analysis() + analysis = self._to_ac_analysis() elif self.plot_name.startswith('tran'): - return self._to_transient_analysis() + analysis = self._to_transient_analysis() elif self.plot_name.startswith('disto'): - return self._to_distortion_analysis() + analysis = self._to_distortion_analysis() elif self.plot_name.startswith('noise'): - return self._to_noise_analysis() + analysis = self._to_noise_analysis() elif self.plot_name.startswith('pz'): - return self._to_polezero_analysis() + analysis = self._to_polezero_analysis() elif self.plot_name.startswith('tf'): - return self._to_transfer_function_analysis() + analysis = self._to_transfer_function_analysis() else: raise NotImplementedError("Unsupported plot name {}".format(self.plot_name)) + + analysis.measurements = measurements + return analysis ############################################## @@ -1189,13 +1192,30 @@ def run(self, background=False): # in the background thread and wait until the simulation is done command = 'bg_run' if background else 'run' - self.exec_command(command) + results = self.exec_command(command) if background: self._is_running = True else: self._logger.debug("Simulation is done") + # Parse out measurement results + results = results if isinstance(results, list) else results.splitlines() + measurements = {} + meas_start_index = 0 + meas_end_index = 0 + for line in results: + if line.startswith('Measurements'): + meas_start_index = results.index(line) + 1 + elif meas_start_index and '=' in line: + meas_end_index = results.index(line) + 1 + if meas_start_index and meas_end_index: + for line in results[meas_start_index:meas_end_index]: + # Extract each measurement result as a k,v pair + [k, _, v, *_] = line.split() + measurements[k] = float(v) + return measurements + # time.sleep(.1) # required before to test if the simulation is running # while (self._ngspice_shared.ngSpice_running()): # time.sleep(.1) diff --git a/PySpice/Spice/NgSpice/Simulation.py b/PySpice/Spice/NgSpice/Simulation.py index 92b62ec2..fc01dd57 100644 --- a/PySpice/Spice/NgSpice/Simulation.py +++ b/PySpice/Spice/NgSpice/Simulation.py @@ -116,7 +116,7 @@ def _run(self, analysis_method, *args, **kwargs): # load circuit and simulation # Fixme: Error: circuit not parsed. self._ngspice_shared.load_circuit(str(self)) - self._ngspice_shared.run() + measurements = self._ngspice_shared.run() self._logger.debug(str(self._ngspice_shared.plot_names)) self.reset_analysis() @@ -124,4 +124,4 @@ def _run(self, analysis_method, *args, **kwargs): if plot_name == 'const': raise NameError('Simulation failed') - return self._ngspice_shared.plot(self, plot_name).to_analysis() + return self._ngspice_shared.plot(self, plot_name).to_analysis(measurements)