Skip to content

Commit ea260aa

Browse files
authored
Merge pull request #282 from nunobrum/adopting-clipin
Adopting clipin
2 parents fd9ed4b + c45f6e4 commit ea260aa

File tree

8 files changed

+108
-170
lines changed

8 files changed

+108
-170
lines changed

README.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# README <!-- omit in toc -->
22

3-
_current version: 1.4.8
3+
_current version: 1.4.9 (alpha)_
44

55
*spicelib* is a toolchain of python utilities design to interact with spice simulators, as for example:
66

@@ -61,12 +61,12 @@ Try it. It's awesome. </b>
6161
- [Simulation Analysis Toolkit](#simulation-analysis-toolkit)
6262
- [ltsteps](#ltsteps)
6363
- [Command Line Interface](#command-line-interface)
64-
- [ltsteps.exe](#ltstepsexe)
65-
- [histogram.exe](#histogramexe)
66-
- [raw\_convert.exe](#raw_convertexe)
67-
- [rawplot.exe](#rawplotexe)
68-
- [run\_server.exe](#run_serverexe)
69-
- [asc\_to\_qsch.exe](#asc_to_qschexe)
64+
- [ltsteps](#ltsteps)
65+
- [histogram](#histogram)
66+
- [raw\_convert](#raw_convert)
67+
- [rawplot](#rawplot)
68+
- [run\_server](#run_server)
69+
- [asc\_to\_qsch](#asc_to_qsch)
7070
- [Other functions](#other-functions)
7171
- [log\\semi\_dev\_op\_reader.opLogReader](#logsemi_dev_op_readeroplogreader)
7272
- [Debug Logging](#debug-logging)
@@ -96,19 +96,18 @@ Try it. It's awesome. </b>
9696
by the user and the netlist is updated accordingly. The netlist can then be used with the SimRunner to run a batch of
9797
simulations or with the LTspice GUI.
9898

99-
* __ltsteps.exe__
99+
* __ltsteps__
100100
An command line tool that extracts from LTspice output files data, and formats it for import in a spreadsheet, such like Excel
101101
or Calc.
102102

103-
* __histogram.exe__
103+
* __histogram__
104104
A command line tool that uses numpy and matplotlib to create a histogram and calculate the sigma deviations. This is
105105
useful for Monte-Carlo analysis.
106106

107-
* __asc_to_qsch.exe__
107+
* __asc_to_qsch__
108108
A command line tool that converts LTspice schematic format [.asc] into Qspice schematic format [.qsch]
109109

110-
(Note that the extension '.exe' is only available on Windows. On MacOS or Linux, the commands will have the same name,
111-
but without '.exe')
110+
(Note that in Windows operating system the command line has the extension '.exe'. )
112111

113112
### Main Classes
114113

@@ -932,11 +931,11 @@ The second possibility is to use the module directly on the command line
932931

933932
## Command Line Interface
934933

935-
The following tools will be installed when you install the library via pip. The extension '.exe' is only available on
936-
Windows. On MacOS or Linux, the commands will have the same name, but without '.exe'. The executables are simple links
934+
The following tools will be installed when you install the library via pip. In windows operating system the command
935+
lines receive the .exe extension. Other OSes don't have this particularity. The executables are simple links
937936
to python scripts with the same name, of which the majority can be found in the package's 'scripts' directory.
938937

939-
### ltsteps.exe
938+
### ltsteps
940939

941940
```text
942941
Usage: ltsteps [filename]
@@ -948,7 +947,7 @@ where the data read is formatted into a more convenient tab separated format. In
948947
the
949948
script will scan the directory and process the newest log, txt or out file found.
950949

951-
### histogram.exe
950+
### histogram
952951

953952
This module uses the data inside on the filename to produce a histogram image.
954953

@@ -979,7 +978,7 @@ Options:
979978
Name of the image File. extension 'png'
980979
```
981980

982-
### raw_convert.exe
981+
### raw_convert
983982

984983
A tool to convert .raw files into csv or Excel files.
985984

@@ -997,17 +996,21 @@ Options:
997996
-s SEPARATOR, --sep=SEPARATOR
998997
Value separator for CSV output. Default: "\t" <TAB>
999998
Example: -d ";"
999+
-D DIALECT, --dialect=DIALECT
1000+
Dialect to pass to RawRead (e.g., 'ltspice' ,
1001+
'qspice', 'ngspice' ,'xyce')
1002+
10001003
```
10011004

1002-
### rawplot.exe
1005+
### rawplot
10031006

1004-
Uses matplotlib to plot the data in the raw file.
1007+
Uses matplotlib to plot the data in the raw file. Matplotlib must be installed for this to work.
10051008

10061009
```text
10071010
Usage: rawplot RAW_FILE TRACE_NAME
10081011
```
10091012

1010-
### run_server.exe
1013+
### run_server
10111014

10121015
This module is used to run a server that can be used to run simulations in a remote machine. The server will run in the
10131016
background and will wait for a client to connect. The client will send a netlist to the server and the server will run
@@ -1073,9 +1076,9 @@ options:
10731076
Maximum number of parallel simulations. Default is 4
10741077
```
10751078

1076-
### asc_to_qsch.exe
1079+
### asc_to_qsch
10771080

1078-
Converts LTspice schematics into QSPICE schematics.
1081+
Converts LTspice schematics into QSPICE schematics. Note that not all LTspice components are supported in QSPICE.
10791082

10801083
```text
10811084
Usage: asc_to_qsch [options] ASC_FILE [QSCH_FILE]
@@ -1127,6 +1130,11 @@ For support and improvement requests please open an Issue
11271130
in [GitHub spicelib issues](https://github.com/nunobrum/spicelib/issues)
11281131

11291132
## History
1133+
* Version 1.4.9
1134+
* Adopting clipin for clipboard operations
1135+
* Adding dialect support to raw_convert
1136+
* renamed CLI rawconvert to raw_convert for consistency
1137+
* Removing .exe extensions from CLI tools references in README
11301138
* Version 1.4.8
11311139
* Fixing Issue #269 - improved support for Ø,€,£,× components for Qspice
11321140
* Fixing Issue #262 - Support for comments in netlists
@@ -1144,7 +1152,7 @@ in [GitHub spicelib issues](https://github.com/nunobrum/spicelib/issues)
11441152
* Fixing Issue #235 and #236 - Inconsistent formulas in montecarlo.py and in tolerance_deviations.py
11451153
* Fixing Issue #233 and #234 - `run_server` enhancements and platform compatibility
11461154
* Fixing Issue #224 - Allow maintenance of `.control` sections
1147-
* Fixing Issue #219 - Provide an option for defining the directory in which spice is executed
1155+
* Fixing Issue #219 - Provides an option for defining the directory in which spice is executed
11481156
* Fixing Issue #218 - Allow reading of multiple plots from 1 raw file
11491157
* Fixing Issue #214 - Netlist concatenations are badly interpreted
11501158
* Fixing Issue #213 - Add support for Verilog A elements

examples/run_montecarlo.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,17 @@
2020
mc.set_parameter_deviation('Vos', 3e-4, 5e-3, 'uniform') # The keyword 'distribution' is optional
2121
mc.prepare_testbench(num_runs=1000) # Prepares the testbench for 1000 simulations
2222

23-
manually_simulating_in_LTspice = False
23+
# Finally the netlist is saved to a file. This file contains all the instructions to run the simulation in LTspice
24+
mc.save_netlist('./testfiles/temp/sallenkey_mc.asc')
25+
# -- End of Example 1 --
2426

25-
if manually_simulating_in_LTspice:
26-
# Finally the netlist is saved to a file. This file contains all the instructions to run the simulation in LTspice
27-
mc.save_netlist('./testfiles/temp/sallenkey_mc.asc')
28-
# -- End of Example 1 --
29-
else:
30-
# Using the Toolkit to run the simulation.
31-
mc.run_testbench(runs_per_sim=100, exe_log=False) # Runs the simulation with splits of 100 runs each
32-
logs = mc.read_logfiles() # Reads the log files and stores the results in the results attribute
33-
logs.obtain_amplitude_and_phase_from_complex_values() # Splits the complex values into real and imaginary parts
34-
logs.export_data('./temp_mc/data_testbench.csv') # Exports the data to a csv file
35-
logs.plot_histogram('fcut') # Plots the histograms for the results
36-
mc.cleanup_files() # Deletes the temporary files
27+
# Using the Toolkit to run the simulation.
28+
mc.run_testbench(runs_per_sim=100, exe_log=False) # Runs the simulation with splits of 100 runs each
29+
logs = mc.read_logfiles() # Reads the log files and stores the results in the results attribute
30+
logs.obtain_amplitude_and_phase_from_complex_values() # Splits the complex values into real and imaginary parts
31+
logs.export_data('./temp_mc/data_testbench.csv') # Exports the data to a csv file
32+
logs.plot_histogram('fcut') # Plots the histograms for the results
33+
mc.cleanup_files() # Deletes the temporary files
3734

3835
print("=====================================")
3936
a = input("Make 1000 simulations ? [Y/N]")

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ numpy = "*"
1717
scipy = "*"
1818
psutil = "*"
1919
matplotlib = "*"
20+
clipin = "*"
2021

2122
[tool.poetry.scripts]
2223
ltsteps = "spicelib.scripts.ltsteps:main"
2324
histogram = "spicelib.scripts.histogram:main"
2425
rawplot = "spicelib.scripts.rawplot:main"
2526
run_server = "spicelib.scripts.run_server:main"
2627
asc_to_qsch = "spicelib.scripts.asc_to_qsch:main"
27-
rawconvert = "spicelib.raw.raw_convert:main"
28+
raw_convert = "spicelib.scripts.raw_convert:main"
2829
readme_update = "spicelib.scripts.readme_update:main"
2930

3031
[tool.poetry.urls]

spicelib/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from .editor.asc_editor import AscEditor
88
from .editor.qsch_editor import QschEditor
99
from .sim.sim_runner import SimRunner
10-
from .utils.clipboard import Clipboard
1110

1211

1312
def all_loggers():

spicelib/log/logfile_data.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,13 @@ def try_convert_value(value: Union[str, int, float, list]) -> Union[int, float,
9696
ans = float(value)
9797
except ValueError:
9898
try:
99-
ans = LTComplex(value)
99+
# Tries to convert to complex
100+
ans = complex(value)
100101
except ValueError:
101-
ans = value.strip() # Removes the leading trailing spaces
102+
try:
103+
ans = LTComplex(value)
104+
except ValueError:
105+
ans = value.strip() # Removes the leading trailing spaces
102106
return ans
103107

104108

spicelib/scripts/histogram.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def main():
7373
from optparse import OptionParser
7474

7575
usage = "usage: %prog [options] LOG_FILE TRACE"
76-
opts = OptionParser(usage=usage, version="%prog 0.1")
76+
opts = OptionParser(usage=usage, version="%prog 1.2")
7777
# opts.add_option('v', "var", action="store", type="string", dest="trace", help="The trace to be used in the histogram")
7878
opts.add_option('-s', "--sigma", action="store", type="int", dest="sigma", default=3,
7979
help="Sigma to be used in the distribution fit. Default=3")
@@ -94,7 +94,8 @@ def main():
9494
opts.add_option('-r', "--range", action="store", type="string", dest="range",
9595
help="Range of the X axis to use for the histogram in the form min:max. Example: -r -1:1")
9696
opts.add_option('-C', "--clipboard", action="store_true", dest="clipboard",
97-
help="If the data from the clipboard is to be used.")
97+
help="If the data from the clipboard is to be used. If a full CSV is in the clipboard the user must provide the TRACE name as well."
98+
" If no TRACE is provided the script will try to convert all lines in the clipboard to numeric values.")
9899
# opts.add_option('-x', "--xname", action="store", dest="xname", help="Name for the variable displayed")
99100
opts.add_option('-o', "--output", action="store", type="string", dest="imagefile",
100101
help="Output the image to a file. Argument is the name of the image File with png extension.\n"
@@ -108,24 +109,56 @@ def main():
108109

109110
if options.clipboard:
110111

111-
from spicelib.utils.clipboard import Clipboard
112+
import clipin
113+
112114

113-
cb = Clipboard()
114-
115115
if len(args) > 0:
116116
TRACE = args[-1]
117117
else:
118118
TRACE = "var"
119119

120-
text = cb.paste()
120+
text = clipin.paste('text/plain')
121121

122-
del(cb)
122+
if len(args) == 0:
123+
for line in text.split('\n'):
124+
try:
125+
values.append(try_convert_value(line))
126+
except ValueError:
127+
print("Failed to convert line: '", line, "'")
128+
129+
if len(values) == 0:
130+
print("No valid numeric values found in clipboard.")
131+
exit(-1)
132+
133+
elif len(args) == 1: # The user provided the trace name
134+
header = text.split('\n')[0]
135+
for sep in ['\t', ';', ',']:
136+
if sep in header:
137+
break
138+
else:
139+
sep = None
123140

124-
for line in text.split('\n'):
141+
vars = header.split(sep)
125142
try:
126-
values.append(try_convert_value(line))
143+
sav_col = vars.index(TRACE)
127144
except ValueError:
128-
print("Failed to convert line: '", line, "'")
145+
print("Clipboard data doesn't have trace '%s'" % TRACE)
146+
print("Clipboard data contains %s" % vars)
147+
exit(-1)
148+
149+
for line in text.split('\n')[1:]:
150+
if line.strip() == '':
151+
continue
152+
vs = line.split(sep)
153+
try:
154+
values.append(try_convert_value(vs[sav_col]))
155+
except ValueError:
156+
print("Failed to convert value: '", vs[sav_col], "'")
157+
continue
158+
except IndexError:
159+
print("Line has not enough columns: '", line, "'")
160+
continue
161+
129162
elif len(args) == 0:
130163
opts.print_help()
131164
exit(-1)
@@ -211,7 +244,12 @@ def main():
211244
print("Not enough elements for an histogram."
212245
f"Only found {len(values)} elements. Histogram is specified for {options.nbins} bins")
213246
else:
214-
x = np.array(values, dtype=float)
247+
value_type = type(values[0])
248+
print("Data type detected: ", value_type)
249+
if value_type in [int, float]:
250+
x = np.array(values, dtype=float)
251+
elif value_type == complex:
252+
x = abs(np.array([v.real for v in values], dtype=complex)) # Can be changed to .real or .imag
215253
mu = x.mean()
216254
mn = x.min()
217255
mx = x.max()
Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
def main():
4848
usage = "usage: %prog [options] <rawfile> <trace_list>"
49-
parser = OptionParser(usage=usage, version="%prog 0.1")
49+
parser = OptionParser(usage=usage, version="%prog 1.2")
5050
parser.add_option("-o", "--output", dest="output", default=None,
5151
help="Output file name.\n"
5252
"Use .csv for CSV output, .xlsx for Excel output",
@@ -59,6 +59,9 @@ def main():
5959
help='Value separator for CSV output. Default: "\\t" <TAB>\n'
6060
'Example: -d ";"'
6161
)
62+
parser.add_option('-D', '--dialect', dest='dialect', default=None,
63+
help="Dialect to pass to RawRead (e.g., 'ltspice' , 'qspice', 'ngspice' ,'xyce')")
64+
6265

6366
(options, args) = parser.parse_args()
6467

@@ -76,7 +79,7 @@ def main():
7679

7780
# Read the raw file
7881
if traces != '*':
79-
raw_data = RawRead(rawfile, '*', header_only=True, verbose=False)
82+
raw_data = RawRead(rawfile, verbose=False, dialect=options.dialect)
8083
raw_traces = raw_data.get_trace_names()
8184
found_traces = []
8285
for trace in traces:
@@ -95,16 +98,17 @@ def main():
9598
else:
9699
print("Warning: Trace " + trace + " not found")
97100

101+
98102
if len(found_traces) == 0:
99103
print("Error: No traces found")
100104
print("Available Traces:\n ")
101105
for trace in raw_traces:
102106
print("\t<" + trace + ">")
103107
exit(1)
104108
print("Reading traces: ", found_traces)
105-
raw_data = RawRead(rawfile, found_traces, verbose=options.verbose)
109+
106110
else:
107-
raw_data = RawRead(rawfile, traces, verbose=options.verbose)
111+
raw_data = RawRead(rawfile, traces, dialect=options.dialect, verbose=options.verbose)
108112

109113
# Output the file
110114
if options.output is None:
@@ -115,11 +119,9 @@ def main():
115119
for i in range(data_size):
116120
text += options.separator.join([str(data[col][i]) for col in data.keys()]) + '\n'
117121
if options.clipboard:
118-
from spicelib.utils.clipboard import Clipboard
119-
cb = Clipboard()
122+
import clipin
120123
print(f"Copying to clipboard text with {len(text)} bytes")
121-
cb.copy(text)
122-
del(cb)
124+
clipin.copy({'text/plain': text})
123125
else:
124126
print(text)
125127
else:

0 commit comments

Comments
 (0)