From cedbd4ab7c81f792cf413832369c53d3fa314e8d Mon Sep 17 00:00:00 2001 From: nunobrum Date: Sun, 30 Apr 2023 22:37:04 +0200 Subject: [PATCH] Aligning the README.md with the current implementation. Preparing for 4.0 release Renaming Trace Class used for .raw reads as TraceRead Adding iteration capability to Datasets Correcting logging and printout messages Moving the raw_write tests to its own test file --- PyLTSpice/__init__.py | 2 +- PyLTSpice/raw/raw_classes.py | 14 +- PyLTSpice/raw/raw_read.py | 10 +- PyLTSpice/raw/raw_write.py | 111 +--------- PyLTSpice/sim/ltspice_simulator.py | 4 +- PyLTSpice/sim/sim_runner.py | 36 ++-- README.md | 312 +++++++++++++++++------------ tests/Batch_Test_1.log | 67 ++++--- tests/PI_Filter.raw | Bin 0 -> 77986 bytes tests/PI_Filter_resampled.raw | Bin 0 -> 16056 bytes tests/TRAN - STEP.raw | Bin 0 -> 4208 bytes tests/batch_test.py | 25 +-- tests/batch_test3.py | 5 +- tests/batch_test4.py | 2 +- tests/raw_write_tests.py | 108 ++++++++++ tests/testfile.raw | Bin 0 -> 23054 bytes 16 files changed, 381 insertions(+), 315 deletions(-) create mode 100644 tests/PI_Filter.raw create mode 100644 tests/PI_Filter_resampled.raw create mode 100644 tests/TRAN - STEP.raw create mode 100644 tests/raw_write_tests.py create mode 100644 tests/testfile.raw diff --git a/PyLTSpice/__init__.py b/PyLTSpice/__init__.py index f105538..40e7ae7 100644 --- a/PyLTSpice/__init__.py +++ b/PyLTSpice/__init__.py @@ -2,7 +2,7 @@ # Convenience direct imports from .raw.raw_read import RawRead, SpiceReadException -from .raw.raw_write import RawWrite, Trace as TraceW +from .raw.raw_write import RawWrite, Trace from .sim.spice_editor import SpiceEditor, SpiceCircuit from .sim.sim_runner import SimRunner from .sim.sim_batch import SimCommander diff --git a/PyLTSpice/raw/raw_classes.py b/PyLTSpice/raw/raw_classes.py index b6e7505..d0ac480 100644 --- a/PyLTSpice/raw/raw_classes.py +++ b/PyLTSpice/raw/raw_classes.py @@ -66,6 +66,12 @@ def __str__(self): def __len__(self): return len(self.data) + def __iter__(self): + return iter(self.data) + + def __getitem__(self, item): + return self.data[item] + def get_wave(self) -> np.array: """ :return: Internal data array @@ -184,7 +190,7 @@ def get_point(self, n, step: int = 0) -> Union[float, complex]: def __getitem__(self, item) -> Union[float, complex]: """This is only here for compatibility with previous code. """ - assert self.step_info is None, "Indexing should not be used with stepped data. Use get_point" + assert self.step_info is None, "Indexing should not be used with stepped data. Use get_point or get_wave" return self.data.__getitem__(item) def get_position(self, t, step: int = 0) -> Union[int, float]: @@ -231,8 +237,12 @@ def __len__(self): else: return self.get_len() + def __iter__(self): + assert self.step_info is None, "Iteration can't be used with stepped data. Use get_wave() method." + return self.data.__iter__() + -class Trace(DataSet): +class TraceRead(DataSet): """This class is used to represent a trace. It derives from DataSet and implements the additional methods to support STEPed simulations. This class is constructed by the get_trace() command. diff --git a/PyLTSpice/raw/raw_read.py b/PyLTSpice/raw/raw_read.py index 58ea1a7..485b298 100644 --- a/PyLTSpice/raw/raw_read.py +++ b/PyLTSpice/raw/raw_read.py @@ -214,7 +214,7 @@ from typing import Union, List, Tuple, Dict from pathlib import Path -from .raw_classes import Axis, Trace, DummyTrace, SpiceReadException +from .raw_classes import Axis, TraceRead, DummyTrace, SpiceReadException from ..utils.detect_encoding import detect_encoding import numpy as np @@ -429,10 +429,10 @@ def __init__(self, raw_filename: str, traces_to_read: Union[str, List[str], Tupl trace = self.axis elif (traces_to_read == "*") or (name in traces_to_read): if has_axis: # Reads data - trace = Trace(name, var_type, self.nPoints, self.axis, numerical_type) + trace = TraceRead(name, var_type, self.nPoints, self.axis, numerical_type) else: # If an Operation Point or Transfer Function, only one point per step - trace = Trace(name, var_type, self.nPoints, None, 'real') + trace = TraceRead(name, var_type, self.nPoints, None, 'real') else: trace = DummyTrace(name, var_type) @@ -560,8 +560,8 @@ def __init__(self, raw_filename: str, traces_to_read: Union[str, List[str], Tupl print("LOG file not found or problems happened while reading it. Auto-detecting steps") if has_axis: number_of_steps = 0 - for v in self.axis: - if v == self.axis[0]: + for v in self.axis.data: + if v == self.axis.data[0]: number_of_steps += 1 else: number_of_steps = self.nPoints diff --git a/PyLTSpice/raw/raw_write.py b/PyLTSpice/raw/raw_write.py index dfa4332..7f13056 100644 --- a/PyLTSpice/raw/raw_write.py +++ b/PyLTSpice/raw/raw_write.py @@ -319,7 +319,7 @@ def _consolidate(self): trace.data = self._interpolate(trace.data, my_axis, new_axis) for imported_trace in self._imported_data: new_trace = Trace(imported_trace.name, - self._interpolate(imported_trace.data, imported_trace.axis, new_axis), + self._interpolate(imported_trace.get_wave(), imported_trace.axis.get_wave(), new_axis), imported_trace.whattype, imported_trace.numerical_type) self._traces.append(new_trace) self._traces[0] = Trace(old_axis.name, new_axis, @@ -355,112 +355,3 @@ def tobytes_for_trace(trace: Trace): def tobytes(value): return value.tobytes() return tobytes - - -if __name__ == '__main__': - import numpy as np - from raw_read import RawRead - - def test_readme_snippet(): - LW = RawWrite(fastacces=False) - tx = Trace('time', np.arange(0.0, 3e-3, 997E-11)) - vy = Trace('N001', np.sin(2 * np.pi * tx.data * 10000)) - vz = Trace('N002', np.cos(2 * np.pi * tx.data * 9970)) - LW.add_trace(tx) - LW.add_trace(vy) - LW.add_trace(vz) - LW.save("teste_snippet1.raw") - - def test_trc2raw(): # Convert Teledyne-Lecroy trace files to raw files - f = open(r"Current_Lock_Front_Right_8V.trc") - raw_type = '' # Initialization of parameters that need to be overridden by the file header - wave_size = 0 - for line in f: - tokens = line.rstrip('\r\n').split(',') - if len(tokens) == 4: - if tokens[0] == 'Segments' and tokens[2] == 'SegmentSize': - wave_size = int(tokens[1]) * int(tokens[3]) - if len(tokens) == 2: - if tokens[0] == 'Time' and tokens[1] == 'Ampl': - raw_type = 'transient' - break - if raw_type == 'transient' and wave_size > 0: - data = np.genfromtxt(f, dtype='float,float', delimiter=',', max_rows=wave_size) - LW = RawWrite() - LW.add_trace(Trace('time', [x[0] for x in data])) - LW.add_trace(Trace('Ampl', [x[1] for x in data])) - LW.save("teste_trc.raw") - f.close() - - - def test_axis_sync(): # Test axis sync - LW = RawWrite() - tx = Trace('time', np.arange(0.0, 3e-3, 997E-11)) - vy = Trace('N001', np.sin(2 * np.pi * tx.data * 10000)) - vz = Trace('N002', np.cos(2 * np.pi * tx.data * 9970)) - LW.add_trace(tx) - LW.add_trace(vy) - LW.add_trace(vz) - LW.save("teste_w.raw") - LR = RawRead("..\\test_files\\testfile.raw") - LW.add_traces_from_raw(LR, ('V(out)',), force_axis_alignment=True) - LW.save("merge.raw") - test = """ - equal = True - for ii in range(len(tx)): - if t[ii] != tx[ii]: - print(t[ii], tx[ii]) - equal = False - print(equal) - - v = LR.get_trace('N001') - max_error = 1.5e-12 - for ii in range(len(vy)): - err = abs(v[ii] - vy[ii]) - if err > max_error: - max_error = err - print(v[ii], vy[ii], v[ii] - vy[ii]) - print(max_error) - """ - - def test_write_ac(): - LW = RawWrite() - LR = RawRead("..\\tests\\PI_Filter.raw") - LR1 = RawRead("..\\tests\\PI_Filter_resampled.raw") - LW.add_traces_from_raw(LR, ('V(N002)',)) - LW.add_traces_from_raw(LR1, 'V(N002)', rename_format='N002_resampled', force_axis_alignment=True) - LW.flag_fastaccess = False - LW.save("..\\tests\\PI_filter_rewritten.raw") - LW.flag_fastaccess = True - LW.save("..\\tests\\PI_filter_rewritten_fast.raw") - - def test_write_tran(): - LR = RawRead("..\\tests\\TRAN - STEP.raw") - LW = RawWrite() - LW.add_traces_from_raw(LR, ('V(out)', 'I(C1)')) - LW.flag_fastaccess = False - LW.save("..\\tests\\TRAN - STEP0_normal.raw") - LW.flag_fastaccess = True - LW.save("..\\tests\\TRAN - STEP0_fast.raw") - - def test_combine_tran(): - LW = RawWrite() - for tag, raw in ( - ("AD820_15", "../tests/Batch_Test_AD820_15.raw"), - # ("AD820_10", "../tests/Batch_Test_AD820_10.raw"), - ("AD712_15", "../tests/Batch_Test_AD712_15.raw"), - # ("AD712_10", "../tests/Batch_Test_AD712_10.raw"), - # ("AD820_5", "../tests/Batch_Test_AD820_5.raw"), - # ("AD712_5", "../tests/Batch_Test_AD712_5.raw"), - ): - LR = RawRead(raw) - LW.add_traces_from_raw(LR, ("V(out)", "I(R1)"), rename_format="{}_{tag}", tag=tag, force_axis_alignment=True) - LW.flag_fastaccess = False - LW.save("../tests/Batch_Test_Combine.raw") - - - # test_readme_snippet() - # test_axis_sync() - # test_write_ac() - # test_write_tran() - test_combine_tran() diff --git a/PyLTSpice/sim/ltspice_simulator.py b/PyLTSpice/sim/ltspice_simulator.py index 905e432..26572c6 100644 --- a/PyLTSpice/sim/ltspice_simulator.py +++ b/PyLTSpice/sim/ltspice_simulator.py @@ -164,7 +164,7 @@ def create_netlist(cls, circuit_file: Union[str, Path]) -> Path: if sys.platform == 'darwin': NotImplementedError("In this platform LTSpice doesn't have netlist generation capabilities") cmd_netlist = cls.spice_exe + ['-netlist'] + [circuit_file.as_posix()] - print(f'Creating netlist file from "{circuit_file}"', end='...') + # print(f'Creating netlist file from "{circuit_file}"', end='...') error = run_function(cmd_netlist) if error == 0: @@ -173,6 +173,6 @@ def create_netlist(cls, circuit_file: Union[str, Path]) -> Path: print("OK") return netlist msg = "Failed to create netlist" - print(msg) + # print(msg) logging.error(msg) raise RuntimeError(msg) \ No newline at end of file diff --git a/PyLTSpice/sim/sim_runner.py b/PyLTSpice/sim/sim_runner.py index 9ce3b76..322294f 100644 --- a/PyLTSpice/sim/sim_runner.py +++ b/PyLTSpice/sim/sim_runner.py @@ -168,6 +168,9 @@ def __init__(self, parallel_sims: int = 4, timeout=None, verbose=True, output_fo self.logger.setLevel(logging.INFO) # redirect this logger to a file. self.logger.addHandler(logging.FileHandler('SimRunner.log', mode='w')) + # if verbose is true, all log messages are also printed to the console + if verbose: + self.logger.addHandler(logging.StreamHandler()) self.logger.info("SimRunner started") self.runno = 0 # number of total runs @@ -272,21 +275,12 @@ def create_netlist(self, asc_file: Union[str, Path]): if not isinstance(asc_file, Path): asc_file = Path(asc_file) if asc_file.suffix == '.asc': - netlist_file = asc_file.with_suffix('.net') if self.verbose: self.logger.info("Creating Netlist") - retcode = self.simulator.create_netlist(asc_file) - if retcode == 0 and netlist_file.exists(): - if self.verbose: - self.logger.info("The Netlist was successfully created") - netlist_file = self._to_output_folder(netlist_file, copy=False) - self.workfiles.append(netlist_file) - return netlist_file - else: - self.logger.error("Unable to create Netlist") - if self.verbose: - self.logger.info("Unable to create the Netlist from %s" % asc_file) - return None + return self.simulator.create_netlist(asc_file) + else: + self.logger.info("Unable to create the Netlist from %s" % asc_file) + return None def _prepare_sim(self, netlist: Union[str, Path, SpiceEditor], run_filename: str): """Internal function""" @@ -493,28 +487,24 @@ def file_cleanup(self): # Delete the log file if exists logfile = workfile.with_suffix('.log') if logfile.exists(): - self.logger.info("Deleting", logfile) + self.logger.info("Deleting..." + logfile.name) logfile.unlink() # Delete the raw file if exists rawfile = workfile.with_suffix('.raw') if rawfile.exists(): - self.logger.info("Deleting", rawfile) + self.logger.info("Deleting..." + rawfile.name) rawfile.unlink() # Delete the op.raw file if exists oprawfile = workfile.with_suffix('.op.raw') if oprawfile.exists(): - self.logger.info("Deleting", oprawfile) + self.logger.info("Deleting..." + oprawfile.name) oprawfile.unlink() # Delete the file - self.logger.info("Deleting", workfile) + self.logger.info("Deleting..." + workfile.name) workfile.unlink() - def __call__(self, timeout=0): - self._timeout = timeout - return self - def __iter__(self): return self @@ -541,5 +531,5 @@ def __next__(self): raise StopIteration sleep(0.2) # Go asleep for a sec - if self._timeout > 0 and ((clock() - t0) > self._timeout): - raise SimRunnerTimeoutError(f"Exceeded {self._timeout} seconds waiting for tasks to finish") + if self.timeout and ((clock() - t0) > self.timeout): + raise SimRunnerTimeoutError(f"Exceeded {self.timeout} seconds waiting for tasks to finish") diff --git a/README.md b/README.md index 0348ea4..2a48009 100644 --- a/README.md +++ b/README.md @@ -5,48 +5,52 @@ PySpicer is a toolchain of python utilities design to interact with LTSpice and ## What is contained in this repository ## * __LTSteps.py__ -An utility that extracts from LTSpice output files data, and formats it for import in a spreadsheet, such like Excel or Calc. + An utility that extracts from LTSpice output files data, and formats it for import in a spreadsheet, such like Excel + or Calc. * __raw_read.py__ -A pure python class that serves to read raw files into a python class. + A pure python class that serves to read raw files into a python class. * __raw_write.py__ -A class to write RAW files that can be read by LTSpice Wave Application. + A class to write RAW files that can be read by LTSpice Wave Application. * __Histogram.py__ -A python script that uses numpy and matplotlib to create an histogram and calculate the sigma deviations. This is useful for Monte-Carlo analysis. + A python script that uses numpy and matplotlib to create an histogram and calculate the sigma deviations. This is + useful for Monte-Carlo analysis. * __sim_batch.py__ -This is a script to launch Spice Simulations. This is useful because: + This is a script to launch Spice Simulations. This is useful because: - Can overcome the limitation of only stepping 3 parameters - Different types of simulations .TRAN .AC .NOISE can be run in a single batch - The RAW Files are smaller and easier to treat - When used with the RawRead.py and LTSteps.py, validation of the circuit can be done automatically. - Different models can be simulated in a single batch, by using the following instructions: - - `set_element_model('D1', '1N4148') # Replaces the Diode D1 with the model 1N4148 ` - - `set_component_value('R2', '33k') # Replaces the value of R2 by 33k` - - `set_parameters(run=1, TEMP=80) # Creates or updates the netlist to have .PARAM run=1 or .PARAM TEMP=80` - - `add_instructions(".STEP run -1 1023 1", ".dc V1 -5 5") ` - - `remove_instruction(".STEP run -1 1023 1") # Removes previously added instruction` - - `reset_netlist() # Resets all edits done to the netlist.` + - `set_element_model('D1', '1N4148') # Replaces the Diode D1 with the model 1N4148 ` + - `set_component_value('R2', '33k') # Replaces the value of R2 by 33k` + - `set_parameters(run=1, TEMP=80) # Creates or updates the netlist to have .PARAM run=1 or .PARAM TEMP=80` + - `add_instructions(".STEP run -1 1023 1", ".dc V1 -5 5") ` + - `remove_instruction(".STEP run -1 1023 1") # Removes previously added instruction` + - `reset_netlist() # Resets all edits done to the netlist.` - Note: It was only tested with Windows based installations. + Note: It was only tested with Windows based installations. ## How to Install ## -`pip install PyLTSpice ` + +`pip install PyLTSpice ` ### Updating PyLTSpice ### - `pip install --upgrade PyLTSpice ` + +`pip install --upgrade PyLTSpice ` ### Using GITHub ### - `git clone https://github.com/nunobrum/PyLTSpice.git ` +`git clone https://github.com/nunobrum/PyLTSpice.git ` If using this method it would be good to add the path where you cloned the site to python path. - `import sys ` - `sys.path.append() ` +`import sys ` +`sys.path.append() ` ## How to use ## @@ -55,10 +59,12 @@ Here follows a quick outlook on how to use each of the tools. More comprehensive documentation can be found in https://pyltspice.readthedocs.io/en/latest/ ## LICENSE ## + GNU V3 License (refer to the LICENSE file) ### raw_read.py ### + The example below reads the data from a Spice Simulation called "TRAN - STEP.raw" and displays all steps of the "I(R1)" trace in a matplotlib plot @@ -77,89 +83,99 @@ x = LTR.get_trace('time') # Gets the time axis steps = LTR.get_steps() for step in range(len(steps)): # print(steps[step]) - plt.plot(x.get_time_axis(step), IR1.get_wave(step), label=steps[step]) + plt.plot(x.get_wave(step), IR1.get_wave(step), label=steps[step]) plt.legend() # order a legend plt.show() ``` ### raw_write.py ### -The following example writes a RAW file with a 3 milliseconds transient simulation sine with a -10kHz and a cosine with 9.997kHz + +The following example writes a RAW file with a 3 milliseconds transient simulation sine with a 10kHz and a cosine with +9.997kHz + ```python import numpy as np from PyLTSpice import Trace, RawWrite -LW = RawWrite() +LW = RawWrite(fastacces=False) tx = Trace('time', np.arange(0.0, 3e-3, 997E-11)) vy = Trace('N001', np.sin(2 * np.pi * tx.data * 10000)) vz = Trace('N002', np.cos(2 * np.pi * tx.data * 9970)) LW.add_trace(tx) LW.add_trace(vy) LW.add_trace(vz) -LW.save("teste_w.raw") - +LW.save("teste_snippet1.raw") ``` - ### sim_batch.py ### -This module is used to launch LTSPice simulations. Results then can be processed with either the RawRead -or with the LTSteps module to read the log file which can contain .MEAS results. -The script will firstly invoke the LTSpice in command line to generate a netlist, and then this netlist can be -updated directly by the script, in order to change component values, parameters or simulation commands. +This module is used to launch LTSPice simulations. Results then can be processed with either the RawRead or with the +LTSteps module to read the log file which can contain .MEAS results. + +The script will firstly invoke the LTSpice in command line to generate a netlist, and then this netlist can be updated +directly by the script, in order to change component values, parameters or simulation commands. Here follows an example of operation. ```python -import os -from PyLTSpice import SimCommander - -def processing_data(raw_file, log_file): - print("Handling the simulation data of %s, log file %s" % (raw_file, log_file)) +from PyLTSpice import SimRunner +from PyLTSpice import SpiceEditor # select spice model -LTC = SimCommander("Batch_Test.asc") +LTC = SimRunner(output_folder='./temp') +LTC.create_netlist('Batch_Test.asc') +netlist = SpiceEditor('Batch_Test.net') # set default arguments -LTC.set_parameters(res=0, cap=100e-6) -LTC.set_component_value('R2', '2k') -LTC.set_component_value('R1', '4k') -LTC.set_element_model('V3', "SINE(0 1 3k 0 0 0)") -# define simulation -LTC.add_instructions( - "; Simulation settings", - ".param run = 0" +netlist.set_parameters(res=0, cap=100e-6) +netlist.set_component_value('R2', '2k') # Modifying the value of a resistor +netlist.set_component_value('R1', '4k') +netlist.set_element_model('V3', "SINE(0 1 3k 0 0 0)") # Modifying the +netlist.set_component_value('XU1:C2', 20e-12) # modifying a define simulation +netlist.add_instructions( + "; Simulation settings", + ".param run = 0" ) for opamp in ('AD712', 'AD820'): - LTC.set_element_model('XU1', opamp) + netlist.set_element_model('XU1', opamp) for supply_voltage in (5, 10, 15): - LTC.set_component_value('V1', supply_voltage) - LTC.set_component_value('V2', -supply_voltage) - # overriding he automatic netlist naming - run_netlist_file = "{}_{}_{}.net".format(LTC.circuit_radic, opamp, supply_voltage) - LTC.run(run_filename=run_netlist_file, callback=processing_data) - - -LTC.reset_netlist() -LTC.add_instructions( - "; Simulation settings", - ".ac dec 30 10 1Meg", - ".meas AC Gain MAX mag(V(out)) ; find the peak response and call it ""Gain""", - ".meas AC Fcut TRIG mag(V(out))=Gain/sqrt(2) FALL=last" + netlist.set_component_value('V1', supply_voltage) + netlist.set_component_value('V2', -supply_voltage) + print("simulating OpAmp", opamp, "Voltage", supply_voltage) + LTC.run(netlist) + +for raw, log in LTC: + print("Raw file: %s, Log file: %s" % (raw, log)) + # do something with the data + # raw_data = RawRead(raw) + # log_data = LTSteps(log) + # ... + +netlist.reset_netlist() +netlist.add_instructions( + "; Simulation settings", + ".ac dec 30 10 1Meg", + ".meas AC Gain MAX mag(V(out)) ; find the peak response and call it ""Gain""", + ".meas AC Fcut TRIG mag(V(out))=Gain/sqrt(2) FALL=last" ) -LTC.run() -LTC.wait_completion() +# Sim Statistics +print('Successful/Total Simulations: ' + str(LTC.okSim) + '/' + str(LTC.runno)) + +enter = input("Press enter to delete created files") +if enter == '': + LTC.file_cleanup() # Sim Statistics print('Successful/Total Simulations: ' + str(LTC.okSim) + '/' + str(LTC.runno)) ``` ### LTSteps.py ### -This module defines a class that can be used to parse LTSpice log files where the information about .STEP information is written. -There are two possible usages of this module, either programmatically by importing the module and then accessing data through the -class as exemplified here: + +This module defines a class that can be used to parse LTSpice log files where the information about .STEP information is +written. There are two possible usages of this module, either programmatically by importing the module and then +accessing data through the class as exemplified here: ```python from PyLTSpice.LTSteps import LTSpiceLogReader @@ -182,14 +198,16 @@ print("Total number of measures found :", data.measure_count) ``` The second possibility is to use the module directly on the command line - `python -m PyLTSpice.LTSteps ` - The can be either be a log file (.log), a data export file (.txt) or a measurement output file (.meas) - This will process all the data and export it automatically into a text file with the extension (tlog, tsv, tmeas) - where the data read is formatted into a more convenient tab separated format. - In case the is not provided, the script will scan the directory and process the newest log, txt or out file found. +`python -m PyLTSpice.LTSteps ` +The can be either be a log file (.log), a data export file (.txt) or a measurement output file (.meas) +This will process all the data and export it automatically into a text file with the extension (tlog, tsv, tmeas) +where the data read is formatted into a more convenient tab separated format. In case the is not provided, the +script will scan the directory and process the newest log, txt or out file found. ### Histogram.py ### + This module uses the data inside on the filename to produce an histogram image. + ``` Usage: Histogram.py [options] LOG_FILE TRACE @@ -217,9 +235,32 @@ Options: Name of the image File. extension 'png' ``` +### rawconvert.py ### + +A tool to convert .raw files into csv or Excel files. + +``` +Usage: raw_convert.py [options] + +Options: + --version show program's version number and exit + -h, --help show this help message and exit + -o FILE, --output=FILE + Output file name. Use .csv for CSV output, .xlsx for + Excel output + -c, --clipboard Output to clipboard + -v, --verbose Verbose output + -s SEPARATOR, --sep=SEPARATOR + Value separator for CSV output. Default: "\t" + Example: -d ";" + + +``` + ### SemiDevOpReader.py ### -This module is used to read from LTSpice log files Semiconductor Devices Operating Point Information. -A more detailed documentation is directly included in the source file docstrings. + +This module is used to read from LTSpice log files Semiconductor Devices Operating Point Information. A more detailed +documentation is directly included in the source file docstrings. ## To whom do I talk to? ## @@ -228,110 +269,123 @@ A more detailed documentation is directly included in the source file docstrings * Alternative contact : nuno.brum@gmail.com ## History ## + +* Version 4.0.0\ + Separating the SimCommander into two separate classes, one for the spice netlist editing (SpiceEditor) and another for + the simulation execution (SimRunner).\ + Implementing simulation server to allow for remote simulation execution and the respective client.\ + Supporting Wiggler element in the new LTSpiceXVII.\ + Renaming all files into lowercase.\ + Creating Error classes for better error handling.\ + Adding support for other simulators (ex: ngspice) where the simulator is defined by a class. This + support class needs to be a subclass of the abstract class Simulator.\ + Enormous improvement in the documentation of the code. + * Version 3.0\ -Eliminating the LTSpice prefixes from files and classes.\ -Adopting the lowercase convention for filenames. + Eliminating the LTSpice prefixes from files and classes.\ + Adopting the lowercase convention for filenames. * Version 2.3.1\ -Bug fix on the parameter replacement + Bug fix on the parameter replacement * Version 2.3\ -Supporting the creation of RAW Noise Analysis\ -Bug Fixes (See GitHub Log) + Supporting the creation of RAW Noise Analysis\ + Bug Fixes (See GitHub Log) * Version 2.2\ -Making numpy as an requirement and eliminating all code that avoided the use of numpy\ -Using new packaging tool\ -Fixes on the LTSpice_RawWrite\ -Fixes in the handling of stepped operating point simulations + Making numpy as an requirement and eliminating all code that avoided the use of numpy\ + Using new packaging tool\ + Fixes on the LTSpice_RawWrite\ + Fixes in the handling of stepped operating point simulations * Version 2.1\ -Adopting minimum python version 3.7\ -Starting to use unit tests to validate all modules and improving testbenches\ -Compatibility with NGSpice\ -Avoiding the use of setup.py as per PEP517 and PEP518\ -Bug Fixes (See GitHub log for more information)\ -Improvements on the management of stepped data in the LTSpice_RawRead.py + Adopting minimum python version 3.7\ + Starting to use unit tests to validate all modules and improving testbenches\ + Compatibility with NGSpice\ + Avoiding the use of setup.py as per PEP517 and PEP518\ + Bug Fixes (See GitHub log for more information)\ + Improvements on the management of stepped data in the LTSpice_RawRead.py * Version 2.0.2\ -Improvements on Encoding detection + Improvements on Encoding detection * Version 2.0\ -International Support using the correct encoding when loading log files.\ -Code Optimizations on the LTSpice_RawReader that allow faster data loading.\ -Improving the functionality on the LTSpice_RawWriter.py\ -Adding support to editing components inside subcircuits (.subckt)\ -Supporting resistors with Model Definitions\ -Fixing problem with LTSpiceLogReader that would return messed up data\ -Fixing problem with replacing the file extension in certain names\ -Correcting problem with deprecations on the numpy functions used by the Histogram.py\ -Adding back the README.md that somehow was deleted + International Support using the correct encoding when loading log files.\ + Code Optimizations on the LTSpice_RawReader that allow faster data loading.\ + Improving the functionality on the LTSpice_RawWriter.py\ + Adding support to editing components inside subcircuits (.subckt)\ + Supporting resistors with Model Definitions\ + Fixing problem with LTSpiceLogReader that would return messed up data\ + Fixing problem with replacing the file extension in certain names\ + Correcting problem with deprecations on the numpy functions used by the Histogram.py\ + Adding back the README.md that somehow was deleted * Version 1.9\ -Adding support for µ character in the SpiceEditor.\ -Adding get_component_floatvalue() method in the netlist manipulating class that handles the conversion of - numeric fields into a float. This function takes into account the engineering qualifiers 'k' for kilos, 'm' or milis, + Adding support for µ character in the SpiceEditor.\ + Adding get_component_floatvalue() method in the netlist manipulating class that handles the conversion of numeric + fields into a float. This function takes into account the engineering qualifiers 'k' for kilos, 'm' or milis, 'u' or 'µ' for microns, 'n' for nanos, 'f' for femtos and 'Meg' for Megas. * Version 1.8\ -Uniforming License reference across files and improvements on the documentation\ -An enormous and wholehearted thanks to Logan Herrera (lpherr) for the improvements in the documentation.\ -Bugfix on the add_LTspiceRunCmdLineSwitches() ; Supporting .param name value format\ -Allowing the LTSpiceRawRead to proceed when the log file can't be found or when there are problems reading it. + Uniforming License reference across files and improvements on the documentation\ + An enormous and wholehearted thanks to Logan Herrera (lpherr) for the improvements in + the documentation.\ + Bugfix on the add_LTspiceRunCmdLineSwitches() ; Supporting .param name value format\ + Allowing the LTSpiceRawRead to proceed when the log file can't be found or when there are problems reading it. * Version 1.7\ -Running in Linux under wine is now possible + Running in Linux under wine is now possible * Version 1.6\ -Adding LTSpice_RawWrite. Adding documentation. + Adding LTSpice_RawWrite. Adding documentation. * Version 1.5\ -Small fixes and improvements on the class usage. No added features + Small fixes and improvements on the class usage. No added features * Version 1.4 \ -Adding the LTSpice_SemiDevOpReader module\ -Re-enabling the Histogram functions which where disabled by mistake. + Adding the LTSpice_SemiDevOpReader module\ + Re-enabling the Histogram functions which where disabled by mistake. * Version 1.3 \ -Bug fixes on the SpiceEditor Class + Bug fixes on the SpiceEditor Class * Version 1.2 \ -README.md: -Adding link to readthedocs documentation\ -All files: -Comprehensive documentation on how to use each module + README.md: + Adding link to readthedocs documentation\ + All files: + Comprehensive documentation on how to use each module * Version 1.1\ -README.md: -Updated the description\ -LTSpiceBatch.py: -Corrected the name of the returned raw file.\ -Added comments throughout the code and cleanup + README.md: + Updated the description\ + LTSpiceBatch.py: + Corrected the name of the returned raw file.\ + Added comments throughout the code and cleanup * Version 1.0\ -LTSpiceBatch.py: -Implemented an new approach (NOT BACKWARDS COMPATIBLE), that avoids the usage of the sim_settings.inc file. -And allows to modify not only parameters, but also models and even the simulation commands.\ -LTSpice_RawRead.py: -Added the get_time_axis method to the RawRead class to avoid the problems with negative values on -time axis, when 2nd order compression is enabled in LTSpice.\ -LTSteps.py: -Modified the LTSteps so it can also read measurements on log files without any steps done. + LTSpiceBatch.py: + Implemented an new approach (NOT BACKWARDS COMPATIBLE), that avoids the usage of the sim_settings.inc file. And allows + to modify not only parameters, but also models and even the simulation commands.\ + LTSpice_RawRead.py: + Added the get_time_axis method to the RawRead class to avoid the problems with negative values on time axis, when 2nd + order compression is enabled in LTSpice.\ + LTSteps.py: + Modified the LTSteps so it can also read measurements on log files without any steps done. * Version 0.6\ -Histogram.py now has an option to make the histogram directly from values stored in the clipboard + Histogram.py now has an option to make the histogram directly from values stored in the clipboard * Version 0.5\ -The LTSpice_RawReader.py now uses the struc.unpack function for a faster execution + The LTSpice_RawReader.py now uses the struc.unpack function for a faster execution * Version 0.4\ -Added LTSpiceBatch.py to the collection of tools + Added LTSpiceBatch.py to the collection of tools * Version 0.3\ -A version of LTSteps that can be imported to use in a higher level script + A version of LTSteps that can be imported to use in a higher level script * Version 0.2\ -Adding LTSteps.py and Histogram.py + Adding LTSteps.py and Histogram.py * Version 0.1 \ -First commit to the bitbucket repository. + First commit to the bitbucket repository. diff --git a/tests/Batch_Test_1.log b/tests/Batch_Test_1.log index ba8fc05..f696ea8 100644 --- a/tests/Batch_Test_1.log +++ b/tests/Batch_Test_1.log @@ -1,5 +1,8 @@ Circuit: * C:\sandbox\PySpice\tests\Batch_Test.asc +No AC stimulus found: + Set the value of a current or voltage source to "AC 1." + to make it behave as a signal generator for AC analysis. Direct Newton iteration failed to find .op point. (Use ".option noopiter" to skip.) Starting Gmin stepping Gmin = 10 @@ -11,38 +14,54 @@ Gmin = 0.000142725 Gmin = 1.5325e-05 Gmin = 1.6455e-06 Gmin = 1.76685e-07 -Gmin = 1.89714e-08 -Gmin = 2.03704e-09 -Gmin = 2.18725e-10 -Gmin = 2.34854e-11 -Gmin = 2.52173e-12 -Gmin = 2.70769e-13 +vernier = 0.5 +vernier = 0.25 +Gmin = 6.41063e-08 +vernier = 0.125 +vernier = 0.0625 +vernier = 0.0833333 +Gmin = 6.04858e-08 +vernier = 0.111111 +Gmin = 4.7254e-08 +vernier = 0.148148 +vernier = 0.197531 +Gmin = 3.13284e-08 +vernier = 0.263374 +vernier = 0.351165 +Gmin = 1.6399e-08 +vernier = 0.46822 +Gmin = 6.0282e-09 +vernier = 0.624294 +vernier = 0.832392 +Gmin = 1.18541e-09 +vernier = 1 +Gmin = 1.36264e-10 +Gmin = 1.46313e-11 +Gmin = 1.57102e-12 +Gmin = 1.68687e-13 Gmin = 0 Gmin stepping succeeded in finding the operating point. -vout_rms: RMS(v(out))=1.06048 FROM 0 TO 0.001 -vin_rms: RMS(v(in))=0.707048 FROM 0 TO 0.001 -gain: vout_rms/vin_rms=1.49987 -vout1m: v(out)=-0.0013187 at 0.001 -period: time=9.87226e-09 at 9.87226e-09 +Multiply defined .measure result: gain + Each .measure statement needs a unique result name. -Date: Sun Apr 23 22:49:24 2023 -Total elapsed time: 0.126 seconds. +Date: Sun Apr 30 20:47:19 2023 +Total elapsed time: 0.079 seconds. tnom = 27 temp = 27 -method = modified trap -totiter = 2460 -traniter = 2092 -tranpoints = 1047 -accept = 1046 -rejected = 1 -matrix size = 11 -fillins = 2 +method = trap +totiter = 1029 +traniter = 0 +tranpoints = 0 +accept = 0 +rejected = 0 +matrix size = 20 +fillins = 17 solver = Normal -Avg thread counts: 1.3/1.6/1.6/1.3 -Matrix Compiler1: 566 bytes object code size 0.8/0.6/[0.2] -Matrix Compiler2: 1.10 KB object code size 0.3/0.4/[0.2] +Avg thread counts: 2.4/0.0/4.4/1.6 +Matrix Compiler1: 82 opcodes +Matrix Compiler2: off [0.2]/0.4/0.7 diff --git a/tests/PI_Filter.raw b/tests/PI_Filter.raw new file mode 100644 index 0000000000000000000000000000000000000000..f39c5c5023ea8b38a953dc818c64b1c873c1e16b GIT binary patch literal 77986 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

9uXv;#B|uyv$sNCp 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

;om>a5%uQahf4Y<`nb+`aG(?x1&BuQ(<^nESPI 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 G!2bd5D{{I3 literal 0 HcmV?d00001 diff --git a/tests/PI_Filter_resampled.raw b/tests/PI_Filter_resampled.raw new file mode 100644 index 0000000000000000000000000000000000000000..f37f0e921f965460d5379be60ab3743d3e1b8371 GIT binary patch literal 16056 zcma*N2{;vR{P%x~M3g0a*|kVnvSm4QA6o275~Wl`BxK*RFJ;LVitLFjDfBv&wM`j=XKw6&il+gMh|xv=ZLeync?JcytotC z`z*F~9p`{E#@XOZaVEI?I9E*T;M{N;I6d4YoGq4d8;ie*Q{K*1!8u`3H?e3Z?0p~G zw#T-tu^dM%$^lzDZ0Dvn6lqKZj8m+ZWEZ|M6jw3SnK<6=ddkOK8fnm zcFVjtMJ&!9(-Jr_Y<(JA%VBRBY%PwH{cq1{?C3s>)(RtW#CS-p@3f+b^^DX8X`dC= z8wZTV0gJtWDPx>DwoR&a8_WA&Jg%6&gK2x53l?FIjRx;_yXIJy7Pemm)B4*-?qX{b z>=>!Pq*lbS*Z+>u!D8=Xbx9*ZI{JTmoxw?A8QNIAJ6Mz%7W=;=#jr|Z|Bsg$PIxzQA#PQ9V z*=hy5pCULO_T&{c3A{U=>3utWEVA7^FKac9x1LKbY8Ah&eZ;G2L0O>i;#1TlLc)6O zgFcye_&+{s+PTaJ-gnWA|FpN5nq^9YAL{iVFaH^*3kf-XsJ-HyHG)%{0#}*nN=%9# zlKtjWgWlGp!dmH$-U>M`9nUI`*Bs(qHdjwV4vRmx2#(;#U(q#FG>%P1aJK55Ea|(e z^LS_}XU-<=@Y)`!#$BM-FJJq+!;2HFZqm$(G#pAn^F*>H=F@JHc`yFQMfKRJI+z}1)~@K1 z?dVA1TRs%t1pGM;8k*CFFOfk0<&HBH>iDjo7xL^t27+6$5N=S@!E4Djg#XohxxhIYwBlB|n$E(xfaYG}?6}|Ky?ZcPiT*QxLpgFBighH>h8k2b!4 zzJ)qe`86W9+qAi$=^|c4&H=DI%tLTrkJ|<2UB&x2Ge>F@UhnYDo~_1}nvIOk(d}qD z-D*MV!_FzSZ_tIX@9BEMHe}wk|M>JBw3*vDe9@o3cgA-j#$x34Y8)Dadx&e=hnU!>Ecma)9ldb+=<-+e2L9Qj_qeQ#BIN33y1l5Q zIi8A%asMyBVg$#W?si4>9=^%ft1vCKXopYkQZ;8W@%_vyfw>EEFFHb zytK$JC;QO07!dd76>R>;OxI_4R(hP1!#qP*}PaKB~ zw4D#!eZ~FeS`FegyQI9B=Y?OX6}Ypz`wm}GWHoN#j&w)m>1|DHNvxJ%GkG5OqXRv~ zC8Q%&7ft5X?%d%M*L=9`AFf_I`lK$E@c3~eDoxnoEtk%@J|#s&jmP*W*g913Q*y-4 z-&0XY)8UeEVGa}g*L^#hFaEi!Q++lb)TxJ}wmrzlD#Z$3mH4%sY~>b*Q3TiNN3ca|@i{$omEu_=+kBC{ zZ>w?ktgU&>O52*(yRtf4s3ZHk+;_C}jLii014HJ0X0*d+_2tgCe|T~K!*(nH(_IZ5 z>=Lag)#46s))0G|j7BT^EZ0d)liwU45@7X_&x3|douOuIWEhs^u6Zinx5rQ)`KJiSgbxCL<3?7?ozye>5OGs%D# zfh|*&hAY~It}!>LuwHh?ui>r6_EBXaRm;dNYL!U*WgE+FeN)Nd%pS3BeDw5i*c|;5 z(#??=I4=GTZ&SEuoU3gK!Bysp^nMw||JK%h5J`(^QtP`~s&Q(01U1Kt+gc^`TlGz5 zAqB0-WmLLv>~xS-A(>Zu`v+qI+9;6?C4@m6K5 z^dM@Rxly+n9*EDG%DPvXpN}lR|H~$QKLwxSp1H06oO_w9XEK3TS^9ZJreqDV#7ULE zx;}}g*LuCBMEs559!<2xi!S5u)d+|jd%L#H_Z-(>jU)74$R%9a)-#2Z)p7lIGPORf zqlxjPrGm_R-fDB3?}nhzwtukMEN|;I#Mz>1b_^AKN43rCZnZHG`*#d22J_KqYYe^* zf3@&+GVuDh)}Ce_kv6IStg(lV6Mt~e0x{=n;Y#4mjFtiB)T>0JOP zWcjo%au?!a(UE!G5x31DPW_`A=YJ}|spr-<@2k;Y)$dB(a4&xBf>bIxnjDSq$-E{f z*0%X}pLgB%kFL+-+xqI46Rbi9=g{^ox@}&D%m>L&PRyY~KJ=gY*k0mWI*2!3A0{FK zZzQ%v)T{BDEalt!h|w4oYd?dlKN%3i zVxf)$15_jqA9MDNYFt^TPS9QRZC+YdDpX0I^}W{wHFPtTc))SA z@{iLtE!(>2{g@NC#0t8|&autAm2<_>=J9=j{QNW+Z}9%%WLq(EZ6nD549q;q24m?8h!Y#BV611qNU<&f}hEs|g|}O4{Oy3~X54SRnOD|=xXnk=smM$64-x0H+j>;Xn_4yb<-K>>XwCA6BE+VRbt0}?5TU5L$ETHHm$89Yy3(6+w(gt=(r!)c_dd&Ku^ zAvZV>WS7qWOajT350TTM;sv-DrCxPD2$JG4miZ@#dz-h)?HG!SE8b^i?oHwqvl)^= z{RD+1rHXi=dxvWjRrD~K*IO=dn~y_&VB0^4yJIkeTL8^eCn?Xf)55dy#oN5QUJjYE ziqOJG=L7G$*^l6xMOc!;_6{OBe7D)cY}fH>MW+)<`rSiwwg4_Aq|ilqdFs*;FqdMY zz%;Fd+#MFadF0$tfa5>Fa^7AOS-Q&g+)?WYi9^gQTN=elB^BNJ5=i1b-Y;?%9SUY{ zHkLdFDVdT%&fZBfFU1TvN z@`%CR*bY+t?LXLR_`3A=c*5#k6x;qGU9>^sEqQ76@W(MuNR&*&QWinO9ZmC11y1;) ztAAWW35Uo|bruQ#okapYs?O7tuptf$8TlmbCHEk^VB{9!`XafZ?5QN+Y;G6SPccU3 z0tJqyc}W4>%LV^2+j~ghq-mQ&l;k$=9q!90?qJRE@Xq{`aC6ug6+KnsA96<;(ipx> zy(#~T%o}(AG4_MD0E`pAeI)ruK=HBEpv{6Xf{eok`bT zK~s7}L0ZkRTVMrw@AI{~YV;`LPrJvKq&*B#wIy|1#GEcDG(AB9BuGB`NJC+Vu=0lN z9vQ#`+_GDSo2NT6?;P<+H%5WPVZ(6S6vff?P12v+o_|ueE83xMA3nQr^8y%;CujQST=W_z@NP0$+y|l*J8@a-Tn`Rz93$#juzVTT3Ak+382Ug)Z zfLl>VJf8$3)-+>@TfJv74xb8{Hx4MyF~(TzGHL$lgMXLhgL0gvmg-754~b~Fw2<>2 z!vFd_ytU>3N#YC79(Yai4^P9s9+EcB4+;1fA`Xc^XR#~xMG#!$wKy3k4g(60H4PF@ zAsjC9;i7gF;7@I56ufjE8EG2uBI%Pm6CLZCqnh(<{3E07a~aFeec?FcN4FG=+M&7 z)>F`e{-ndx5l{7ycCoKDB>j~8e)AdKB;+hlxI(??C6H#u5to*bjBM>mw;$W92XJ~y zNKWS~BsSP=V&KFj(s{NzWbg#V9o~$&l17?;`mjBtOF^%CQRM6%)`N!B-BJx@%w*o! zg?()#zH4k*0w$P$bm@JuBk6#<$IXNn2=L#(Q0x}OB6u9(DB1dl02g&a4-G1*BhR{Y z?v&RufxFRaLGwemk;4spL`gd5AD0EM)@$T^XQXFAOnW+b5RAX(*0CBQ9B)H2)k{Inl4UwY{ zD*x~^bAnXNS8bsRRXwFm_4TMJq{L1D4kt+F zb^j@^N#Zpx97jVj{|M#9&Hu%;vYeN|$`u`Ga`-pZE{u2e!ipQ;9Ub_M@^fgs`Ca62 zu)wSwH$QN|`D)q*`XRM8!beCtJ*Dv3>sw98k>E#0=2drr+oX3mMerxYcA|evZO{_n zhSWTzZMzUI4~@dMlDio1*e#+r5yf5Sn0<}SPqDFCNt^$K?&3*#BZ9MnVYV$nGEKr{ zUL(G~OwxGfm`Hx)!~Em7WF_torcmilS1IkEoLYyT5P@agNjSDC)Pvc=O#Fds|VQrNZsPOQiW{mFdW@UNooL=P-+-1N1$r!thi} zg3NotEY*xOo_4L2={=Z#oaelz@*C5Z_#V@Vh@0@FoO~w*#ye)zWPdmNCOpxx->~HM zBZU5jVYIKOIN)Dltb44KhDn^ra|-fym;dT~ICCVLvOGKySY zTW|wD-wa1RH+~{svWZIYiz~)^v{;%rh~nINm-hRU=AY+itM<;IniTc4ZF?U;dz;e% zMICZv-trR5^$m0X#(Pl@vfTLyq!aF%Eq@IG?M0@77jDK>!{w0R%h@>KWLV| zclu(w5}DU1XkPsn#`mR0^*IyfAF>y<H=x`n&b!%}2oh(6gi;(|du# z^N-C-G{Jx{+t;X-%mlKI_c_F@J_0zOrY9U(e=vU#@Masu=AS-nxxz}+Fi@hOz{VZ| z?VB{tR*tKZdB;E3ot?w@eyLL0WMKXw)^NeG0n^E=`>R-mo#0UJkFY}+Z_L{m*5?XN z5Wd&!xvo)yJj-;7sI}(JeZ>qAf zvVj4MgrqBGQGnO^?RAZHKHx6X)vcNliSd3H7|W)GxL*|y4gInCC(*cC|22Pw1lXTwDs{<&98C zoAmR9yIs=hLL+JsM$7mle+?b*+MT+ic4Gi>`Sa2ACZ@T4wF{^WkAR>XC40^vdj@)h zCcFDpj{@znU4QnSj03mU0|NOC#X&7B`%caG4B&|Uyl~C`6!N)@=)SY zIPcyk)gcxS_u@#)RWfhEoVQ>l#uvrN@QzQ3$qi#NZ}Dde#a;`2M`B_hOg(V92|j(V_xrcFiR|_KbI`^4CiuQENLMj+7KDt) zM7%c41no8}IK_r@V7g9H<(B>{P%PcLc<_`CfC0J8otH8JZptfrVDt>cm0!vDVN45f z7NrG~%;(|L7p}(+>t;bgF~b;nehV^h|4Sd;O^mPT?`q?3ng?+6+n~Vap9R3e(M}ih zE*d_ie|X7j*CJ>x>KlLfB^na_zp|VAEF%tQ0>Z`n&49m})ic?ReIQXR#jc~*3>g2} z3a*sD1P-6Kdrigo7Rc$m(|>$W4>Tv%EnSt#2QfyE$A}2_{|JX!u%GHJz}2#s&{3&C zT-kG)o@ExyKe&H}8R@}DRMty=A|KKOrkvKPwI%Z&l03GT8siPKirH_|YIf& z7J#~O8NZ5k0{rE7`OwJjMZjNWS^gqA0p_UB>m&{A0ZxXK$33^~fGnXag?bMP29|DfG&R_RSAf(F ze=mTFUy^qE!cSo4gc{4inFa97XeKx)FbDET*{fviTLfI)VK2(Ma^RMvZ3IUiFVJK? z6&F=nxaRlG)d^0}$9V8~JuP-U@3yNr%)<|wOZx3USy~U1jd+zj zJRg#Iedb5vW0w|yhR21NBO38A*Ds6JWW{6s0B~&b^Vh2nm4RD9!4scz0l+dKrt$)H6xa`*3wp7%0Qo;^!EUut zV4q>#srsv*!Q!D*`ZT8m(9g{zetn`D5JcH>ihBbffrp`XJ<^E+A07q)1X1``yW%e3t&v+=Dqdz6|m48m9sj!2nvoM z^!PWGu#BBQqfZF{u}vbsp!8$#{A!V_vRM*K<`wcc`=kDG0WfrU2#Muo!SA90)b$1nKuoDrg>z30%v4e{ z8@Yg8pYc)3%gTR%myd6K{d-FbC>FbN@CQW${U|ddKcPE-alBzA>})hB>&|18XvzmN z^J}Ny-|Gkdl<|Vz4+=n($2q2rlmWo(FUHT|UJ2^|wN(_f^?^wJJ$%hK(_!k|fZ&3$ zKM4BH4>&<0Qadsz4i0uJb0ex zQL;~`5f0W?_sTz51d-vG2P8K`FV*o4k2E82<#4B-?Ba7!e0F-JHq{BJ<(pi8D*PM_ zRKIkjy8a#<85Zf+{r4R#?$t=7qp1ODtBetETgO0ZxoiX5izYB={?YB_iSHnCRp=G} z<3gCfcR{1s={az1SA42{t_B7?Ex#)MY8-0bQ3j@~FUh=`5=FzByB9#$kV)WyB zV!nduz#K55O)j$k@C7Q@Akpas*nFOzGc(8KD+GeOOm7ZafuV^5YfEM?0GD!5d>LyX zppl`M*@I655f%4-xh%AUsgkSd&je;c&!$Y#skjbsExYNLxy&3mY#q`%9Nz~%6dlTW z&^Qek%<+X^^xne;hQ-FAwnFgd@0Q)nmk!wUOrG_l(LB^!IP^!9Cy&g_ooy7ct8@;$ z4X&@gf%(U=!A)&b(P_YY;DEO3_ik9*U+uOmvj~nX|NE!kJqnZK4uk0xcfic-_r%gG z3sBYuFJ~7;1ImZ8oRc*#f#1Nnb9WggfUCx-{C4UueX)gyGFHXz^a^n#)CE;=273%F=*`ug*;aRdOw##TxOLZA5}H*infoB zbf1IahALs2;Wpr?P`~XQZ!s8;agxog^9LQS(_g}uUx0%`udI@@afHAj1BTD$Z6G^& zn9UTs+aGfvc7~_E9b7l`W@{Av3+hwe5k8+Bg{Ow(_qK+$fuM*aXILe>eHkC%Zn4#Qg% zI`84uYZ>KFVZ*SO(Ikr9+!FeIH?H zpfRzbq!nF}nUW zf0g9`PwZ{ee^(9vB{0RCTYrIsxhPz=tS$5(TDvn^RtG{w#t&YadIHstkFI^4h9G)u z?CJ-~pCJ55OYAY(Vc4S`yPv;e8PL5?v+i;E21`)$9G^pd;OsrKu zz#>%a$g#w3Fi{<2I+e8ypS@6bY?Ju}Qk^D3(cX44Z+Nol>fg0l5NFbH+b2j9FuN<2 z;>Ra|hooU z?D~?XlrB3Bq}^qU8!?}A{LE;{tTPW&xJ(fpCqFO-IJB!z_mX)BOL_{wD$ao=v1PgE z#c|O1-}eZYj!EFtzESOK~@Vl_F@A|IY!KOf{B0icABQhVN{C?Bzgj+>0W~`UgB!{icyP@)K&re|pY5(`prB`~yQ16$k2rmg^5&WWFNS|eFN4=$ zg5O@15-0*b5l60k{VvEpbd{6u?-cN9DcbwgMHAdm4V%4B@dHvn{MqW-KMbq>mX8~# zO_O(|W`y>c?q!Z)OLxcxs9kB^q3{>~y?c zG6eaS)XGQRG-;JG|b) zCwMk32-27B3jR?R18eLWxpMMb!Er5%oM6IF@YwSC*vxtl2tE8yp4EB|$Y_lD95xsO z50a?~r$oNNT4LNfb+x;z4ASRPbrZe+kH&2z^NX1;?@|Atw@ z&V7N4^B3{lsVlHe(#$pZ$0q!J8(cDH4BoLkIm+&I(5Z;9vspqGo7s8} zE0(}nrKX?mfg@lbNYD47M;{z6{U>$HVg+2KDB;Q~83#Iv>L%Z0Gob&cq@tqp1(4>? zyc>JZDEP}_9m65q4G-Po(o2chgy(MYm^1P1Cej=n7O{!iOXl5eR~JleH3cY)wBLPA z`~shJNkqPB?+3a*E<&Y}{cwRZ>4R^#H;l_EP+ST0fY0|BSG^LO0-x@e4Bk`35k4`V zn7&W*6Z})F{F%V;69n`e=ea=L2c)PUINUom2v4c3*!q522P2GSr~LL!f_DE;L}*thsY^Yq3t zI1_y-`!EkB;REfBitd_Cz+wr7Gp8596s`GfOZhKgB+8*gKWGr%oIE7dLyaTI)7Jgr zjTi;TSH2yHolbztGo?PY6i?vE1ifO4jdma}U}4Q^F#y|!7Q zuX-2}S;@Q?zO%RCevg8}8}$h~#7>y$urF$;l?cqmdCM2^ebD?y7>KLvF*KR22BjH=D|C=gxJbagUb>+*AGH&N)^Q*;=td4mb}9Kk}Y z9yj%pLwwRfqUWz*`w5DDMEiv3E1|!Rka;I~baQEv`#}6bOY51OPH1iX?OMy@0+_)m z+uQfL1rBGZ%Q2Vfz*FLqG@1-jfbzc91qUx$LXBT#2D;8bum}sC>xkSQS&DRK1=W%1QXhAZQoe z%0zf`=6lC=@i}n)%D0HRv2{2X`VR?ED}n+CukOw^$%c~V6dH65GvGJxkM7>L8!$)j zj>e^VC0Keg4fm5l11LeWxL1Njuu=BD0i4-#IQ3Mg4VL-_?~CHkfPYqPSfn2Zz~gN7spCV7XtKWQ@1#LSFp|mN zA^Vb-&_(E8Qu%U#;2sfloFnsYl;d-6=avA5+?mGYuzL7v)#6i5NjPjt7b^I0Ob&!nzBD^r@d8Qh zS5dNmwTuiuoe%8DWFGgvUB&8AuG3F@Hz6 zvy?KrujwK(E){Zt)Ah*a8Cu;$6#>E(ZtgsbqGd3Uqw}EnVl~uHZ9Dher5)DsQfm)m z`66s#JfHrpAj3ZzJTD2LkdObR>ILk$CA}z)oyQ1?iv8sBD}5Fj;Efra$Kqqelfpq! zFCzGgKKC-605MwFQc6U479tN_bD3){k$E@HH-zRyz5toe89wJw-GN_~k2Q~D&xQPB z`5MjTAPE&+7%y^v2u7!GOsHv!JD~1g{*BI^79e~(y7GWY>m6X;f1q9BdO8s5`YRY{ zPz;;yxhB|qbA$62`J#TgNJ6#7YoQMJ(!qmY;fMa-D~7S+J*%QD`KVNRrnib%9Qve9 z``Smy4dTpqdC%BM!gHrW^sinJAnLr2@x2_B0CoM!MMNC0k$F{AE^UCu3{d@LKsPJD z7+{YEcn%M!g3#5sEGe`Gp!uRN=gZ!gh?!ZkB8%@c6qittG}gvXILWQZ;Bavo7ENCt ztdpt({XT=5%KcB^0cSp|56h|`Tr5tievbh-LED&Cu3ZPd{tcL!xfcb6d>5vlaWo+x z!yde?J6ny0Ka}ar{-z4-=qZn}?Kc1-@QjbZQ32w~3$f?k3aj&br-bM9N|z|_5sTVnL4>m5P2Dct3Q$Y3Kg*I zd{ipIM|eeKg+-3OkLg`nq#6I|(=->vjy0&f~t_cFFwNKvXloAoe z@+spAsRDEWdy4;_JP)D2)3{>ab6Vn6pOd_8f7(E@NR45^#VTlcEs2TC!wo!IF#Y%o z27!;O&M`!jFCZtf%ePRr0=oK5i#(qgLqzboqLb)rX$+8DOKq>P76K z{-rw>4)$H{5-xpsi1dh;w5XeHB0o`n=*$1{OUL=lPoPsQ}=LHqE; zC!ss_kWR??5BGc&0L8IGkNqQo*6#$Tm8b@wdSXSi{BkW6>btM;VXPl9aq0B(%NK{~BKyMCKLG-m3gZJqG?s*c%h+ z2EhXEHu3(;IKZ2vW_|ZX7`XIzz9haQ54oumvpCdNj;j2tq;F}bBXmfivY`S@L>-%) zwR?G0;0XN*qgeBL_$cFSz>SPJ5FW4Yqn#24dUB1Ljqkk&;g^q?rH0kQH!6D-3o_dg zPwetPg<=S0j1}dO#Oi(EQ(F;D4+B&^J}3RB_Y=KuO)C8U$V70uC^3+DJc`VlDYo&$ z!)6MMMC>2w3F-y!)?S3>&?bZ7+{DKELxCVhdI?rWCnKlVEhRYWOVFgc=sym!y9v)* zqvbbuF%Tc8GL83!=YjK_Oq8M@KENnG`JaMx$>8U|X0`(yfgp$d%3Ei(QedDK%b#pl z0|VcmF|y?OfS7YDH8IQdp-nPVYoS=ZGs<^191jNq zp!*q_m&(2O z94m?|dh}4ZESK6^>79i(o>I)VDZ*I(t}r-4{EV40ZW!ApE)(5;&95f_#}G{=Hl)VL0v z+xX~ZSCfEEkYdNfCuNZ9Qs!N8?+{cUw{_$g+KP^{%^wxS;&09S%`)JxLzTGQ4$oqz z;Ovcl+t2|@LP~pm{2t0zWZqYM3uro&5d zZ}oYx{N;Go+*%`#}LQOXM&ENdP@?<62rlHVx35ze2 zp0qoS)gwr^iVgn!1ka|Nvoaa~1r9P$YxK#Kl6k+hQG5)3u>h(HeJ5|nRf5{d=8#)y zv7r3Av#XFzB1IJ}Da5X&SKpE*6Z ziQWHkdeu?3@jDPQ&CHn(p9%**^Lyo$u>6NxKW3st?|}S(+GlVp0iKd$j1%TdLwmo> zT)uZZ8NH&GI4g+Nqq%nfn*bJn>(kQyUHCWfQK35{$Lb{LI^x4zYhOp^rDC`$t}wX( zTBE`m*Q|4a-iPSZnX`UC?Jkt|>kNle*|6%tkR58<+~qjAXol|BUiCQcoCLNiS_V1& zh9ReSUR=_kH~b(Pb-p#z0WvbzI{0Dv5&4tH;;?*?mzMHL(*{6R@XGksr5N}mr>*{i z!Bg~MvYViZbtqb#c9H)r7SHlHu+jsI_xYWxQ?rr``5ycps1zK*p6|io%vxH=yt@rX zIl_Ko&%dk;2`|~C1Iml^d*+}MfUkS+j@tx7>){`Vew;Bwd*mc8O&!rixPDb zzw%19$~U_qt@!28>1X!vyPxr!C-XO9LxWCq4VK>)G~+RkSU* literal 0 HcmV?d00001 diff --git a/tests/TRAN - STEP.raw b/tests/TRAN - STEP.raw new file mode 100644 index 0000000000000000000000000000000000000000..80a735dd2cd17bd6a2ea536af8012e20ccd82315 GIT binary patch literal 4208 zcma);3s@B88pkKGM9M2_D6$TqXd()z?9A-4vmZCL1Xe&IFcbl~2rR)ag2H-FRF=mu z6)Vf*C9jncy0f!uffw>p78xAzuB9bO<}H=9&i8%uo}=e^dOT<6`OSW_|Mz{r+s=O` zfyrS^OdgZT2n@@N#DwG4G^UtIV+xoIW+r1~O7XRUDPtxx2~0dwh%?f0{B&jl&7H`Y zany7iZN?aJy9l@PagGT`72|U;ZYMBt3}Rw%{QyinzK+B-N8?_KaWyw40=Gy!8AUv; zM7}d|Z!8ncjK}97Mvc|6xJ}OE=F~-$5ncrr>tu9=_{hZ9Zg?g}JbIQ% zq!BszJd>`XQYYkz2m_AHq5Ufwi?jaw2*Ps+#2K-;*IBryOxzb44LJgFFM z!VT}95wAc#9uL_)Qe`sjoy@BUUnSt`=}b0Ojdabj@LG^PC$lZ2XR;4DxK%)N6YzNc zz2hvCgy%a6A8vm;Z#Skp9!GbYPj=yPizq>uL}mmX%}cmlLPuc2I%p5A990Z`PYa<10!8Kz`(ZhMA z`091OR6GAtPhIzhGy#z1an}s(}=yhbE0 zx^3YBdvs}w>)!0wsOH!^NsODG$^-U_MZ0$o`!I!S(pH0b@ebkv`$tua4QqdRooWZ_ z62-s#U*Z9~@s)tNi+j(Y+Svyw;#I3V57?J|>+zLlOd8c<-<~1fuVZ+?zGKw(>Y${V zR7;XG#D<&;93UO9R8JYcFr8|{6SBpq_C^knI(}?&_u833HDsDCo{HVh0a7oN*xL7G zCe>^s3&iFDH5?!XZMahF`fwK2%9j?3XV+J7fE540l=A1$Y^v>ARU|&En#KW=d1_bH zo#-5@H6@zFTRlV$kk);=`r@^cT&i8aXcotRKa2w;dk^2u7e1IxHCOc;pAmdvq9$IDRvqYV~PlqVxPIHDDV;ZoffBs%4|O;%u!`4cNTJ zJ&9+$3#qo+WuAB|ZL=D%1$W$2C+<_ULA&RPmETy^fGzx8abWYyZ_vD%x^i*Js1h|` zOPI8*^OXyVmb|}QwC$Rz25g!4PMm2fE~0r>{|d3v%&P%g$<_h;k!vy4#;vRnuit0Y zfUW8E@nHeUie{E8#I6_nsR7$RpRe%U{;Q(tx>>~E)z7E_+xg4v+gD0WwC1`-Pxa7hIY7x>s&AOK#|Nau4ZB%E#Q3YgDeV? zrf@B-zFNRJVodoP-&cN%eUL?S&$FS1U|%iZ{P9$|95DYD)slY;)_HcaTEO{9N&ki2 zDqQd!Sk!t**14YZ(gMzBUGg-wd3~t1cl}UNh#9B_oRK}kFSzdXq}sjF3q-lVT?;tf zI=Z#yYKBtnR9~AoAo~R^;7r}>my&25MYYc5onqQy7cJnd7&4=Cj{8`ug?`|zzuR#~ z12|Cs<%!)|iAS<%%7sb#sJM$7!12e}o?)+56OUw3aE(d7!+cBwI9m44IUn*q@kkbp z@mr4U8Yj4r{*X9p0CDh z07uZ^sHiVQ;*l)6TXRdl;4PH~aHRQpwU4PF9?7C3a~|p=W85@=Gn&s+_ zQcMW~Am4Q4E=jH@9?7EGJ^fHh3@-q3cj}+SBU!Y@X8(t z3s2uL?#?3~$)ZuudZIM}n|Z*#e)^fljFrSAS>(Rm6II7o^ML(R`g|y$+Q^W>X!3+o z9ae!3!Nym)3 zNaBMmO0}xc=7ak=KsreL^R%MHe6B)^_io_;>3iaz1;htg^ySYg6!CjC2S|_olSP(a zRA^3(l>?;5{>h@Q*H!3hw3P#-r}?Lc>xsSR7AxrF8`vnAzy;%{LkNSo~M83FO>ku{{jw9s-FM= literal 0 HcmV?d00001 diff --git a/tests/batch_test.py b/tests/batch_test.py index 022b13f..668efd0 100644 --- a/tests/batch_test.py +++ b/tests/batch_test.py @@ -1,9 +1,5 @@ -from PyLTSpice.sim.sim_runner import SimRunner -from PyLTSpice.sim.spice_editor import SpiceEditor - -def processing_data(raw_file, log_file): - print("Handling the simulation data of %s, log file %s" % (raw_file, log_file)) - +from PyLTSpice import SimRunner +from PyLTSpice import SpiceEditor # select spice model LTC = SimRunner(output_folder='./temp') @@ -25,12 +21,15 @@ def processing_data(raw_file, log_file): for supply_voltage in (5, 10, 15): netlist.set_component_value('V1', supply_voltage) netlist.set_component_value('V2', -supply_voltage) - # overriding he automatic netlist naming - run_netlist_file = "{}_{}_{}.net".format(netlist.netlist_file.stem, opamp, supply_voltage) print("simulating OpAmp", opamp, "Voltage", supply_voltage) - LTC.run(netlist, callback=processing_data, run_filename=run_netlist_file) + LTC.run(netlist) -LTC.wait_completion() +for raw, log in LTC: + print("Raw file: %s, Log file: %s" % (raw, log)) + # do something with the data + # raw_data = RawRead(raw) + # log_data = LTSteps(log) + # ... netlist.reset_netlist() netlist.add_instructions( @@ -40,12 +39,6 @@ def processing_data(raw_file, log_file): ".meas AC Fcut TRIG mag(V(out))=Gain/sqrt(2) FALL=last" ) - -raw, log = netlist.run("no_callback.net").wait_results() -processing_data(raw, log) - -LTC.wait_completion() - # Sim Statistics print('Successful/Total Simulations: ' + str(LTC.okSim) + '/' + str(LTC.runno)) diff --git a/tests/batch_test3.py b/tests/batch_test3.py index 0a297de..8f7cc8d 100644 --- a/tests/batch_test3.py +++ b/tests/batch_test3.py @@ -3,6 +3,7 @@ from time import sleep from random import random + def processing_data(raw_file, log_file): print("Handling the simulation data of ""%s"", log file ""%s""" % (raw_file, log_file)) time_to_sleep = random( ) * 5 @@ -39,9 +40,9 @@ def processing_data(raw_file, log_file): if use_run_now: runner.run_now(netlist, run_filename=run_netlist_file) else: - runner.run(netlist, run_filename=run_netlist_file) + runner.run(netlist, run_filename=run_netlist_file, callback=processing_data) -for results in runner(4): +for results in runner: print(results) netlist.reset_netlist() diff --git a/tests/batch_test4.py b/tests/batch_test4.py index e947dbd..51ac1a1 100644 --- a/tests/batch_test4.py +++ b/tests/batch_test4.py @@ -40,7 +40,7 @@ def callback(raw_file, log_file): run_netlist_file = "{}_{}_{}.net".format(netlist.netlist_file.stem, opamp, supply_voltage) runner.run(netlist, run_filename=run_netlist_file, callback=CallbackProc) - for results in runner(0.4): + for results in runner: print(results) netlist.reset_netlist() diff --git a/tests/raw_write_tests.py b/tests/raw_write_tests.py new file mode 100644 index 0000000..397e1f0 --- /dev/null +++ b/tests/raw_write_tests.py @@ -0,0 +1,108 @@ + + +import numpy as np +from PyLTSpice import RawRead, Trace, RawWrite + +def test_readme_snippet(): + LW = RawWrite(fastacces=False) + tx = Trace('time', np.arange(0.0, 3e-3, 997E-11)) + vy = Trace('N001', np.sin(2 * np.pi * tx.data * 10000)) + vz = Trace('N002', np.cos(2 * np.pi * tx.data * 9970)) + LW.add_trace(tx) + LW.add_trace(vy) + LW.add_trace(vz) + LW.save("teste_snippet1.raw") + +def test_trc2raw(): # Convert Teledyne-Lecroy trace files to raw files + f = open(r"Current_Lock_Front_Right_8V.trc") + raw_type = '' # Initialization of parameters that need to be overridden by the file header + wave_size = 0 + for line in f: + tokens = line.rstrip('\r\n').split(',') + if len(tokens) == 4: + if tokens[0] == 'Segments' and tokens[2] == 'SegmentSize': + wave_size = int(tokens[1]) * int(tokens[3]) + if len(tokens) == 2: + if tokens[0] == 'Time' and tokens[1] == 'Ampl': + raw_type = 'transient' + break + if raw_type == 'transient' and wave_size > 0: + data = np.genfromtxt(f, dtype='float,float', delimiter=',', max_rows=wave_size) + LW = RawWrite() + LW.add_trace(Trace('time', [x[0] for x in data])) + LW.add_trace(Trace('Ampl', [x[1] for x in data])) + LW.save("teste_trc.raw") + f.close() + + +def test_axis_sync(): # Test axis sync + LW = RawWrite() + tx = Trace('time', np.arange(0.0, 3e-3, 997E-11)) + vy = Trace('N001', np.sin(2 * np.pi * tx.data * 10000)) + vz = Trace('N002', np.cos(2 * np.pi * tx.data * 9970)) + LW.add_trace(tx) + LW.add_trace(vy) + LW.add_trace(vz) + LW.save("teste_w.raw") + LR = RawRead("testfile.raw") + LW.add_traces_from_raw(LR, ('V(out)',), force_axis_alignment=True) + LW.save("merge.raw") + test = """ + equal = True + for ii in range(len(tx)): + if t[ii] != tx[ii]: + print(t[ii], tx[ii]) + equal = False + print(equal) + + v = LR.get_trace('N001') + max_error = 1.5e-12 + for ii in range(len(vy)): + err = abs(v[ii] - vy[ii]) + if err > max_error: + max_error = err + print(v[ii], vy[ii], v[ii] - vy[ii]) + print(max_error) + """ + +def test_write_ac(): + LW = RawWrite() + LR = RawRead("PI_Filter.raw") + LR1 = RawRead("PI_Filter_resampled.raw") + LW.add_traces_from_raw(LR, ('V(N002)',)) + LW.add_traces_from_raw(LR1, 'V(N002)', rename_format='N002_resampled', force_axis_alignment=True) + LW.flag_fastaccess = False + LW.save("PI_filter_rewritten.raw") + LW.flag_fastaccess = True + LW.save("PI_filter_rewritten_fast.raw") + +def test_write_tran(): + LR = RawRead("TRAN - STEP.raw") + LW = RawWrite() + LW.add_traces_from_raw(LR, ('V(out)', 'I(C1)')) + LW.flag_fastaccess = False + LW.save("TRAN - STEP0_normal.raw") + LW.flag_fastaccess = True + LW.save("TRAN - STEP0_fast.raw") + +def test_combine_tran(): + LW = RawWrite() + for tag, raw in ( + ("AD820_15", "Batch_Test_AD820_15.raw"), + # ("AD820_10", "Batch_Test_AD820_10.raw"), + ("AD712_15", "Batch_Test_AD712_15.raw"), + # ("AD712_10", "Batch_Test_AD712_10.raw"), + # ("AD820_5", "Batch_Test_AD820_5.raw"), + # ("AD712_5", "Batch_Test_AD712_5.raw"), + ): + LR = RawRead(raw) + LW.add_traces_from_raw(LR, ("V(out)", "I(R1)"), rename_format="{}_{tag}", tag=tag, force_axis_alignment=True) + LW.flag_fastaccess = False + LW.save("Batch_Test_Combine.raw") + + +test_readme_snippet() +test_axis_sync() +test_write_ac() +test_write_tran() +test_combine_tran() diff --git a/tests/testfile.raw b/tests/testfile.raw new file mode 100644 index 0000000000000000000000000000000000000000..0a83fc655b935c117998a677d92608cc731a163b GIT binary patch literal 23054 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 z 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