InSpice 1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. inspice-1.6/InSpice/Cache/__init__.py +174 -0
  2. inspice-1.6/InSpice/Config/ConfigInstall.py +65 -0
  3. inspice-1.6/InSpice/Config/__init__.py +0 -0
  4. inspice-1.6/InSpice/Config/logging.yml +51 -0
  5. inspice-1.6/InSpice/DeviceLibrary/__init__.py +105 -0
  6. inspice-1.6/InSpice/Doc/ExampleTools.py +49 -0
  7. inspice-1.6/InSpice/Doc/__init__.py +0 -0
  8. inspice-1.6/InSpice/Export/Hdf5.py +126 -0
  9. inspice-1.6/InSpice/Export/__init__.py +0 -0
  10. inspice-1.6/InSpice/KiCad/__init__.py +150 -0
  11. inspice-1.6/InSpice/Logging/Logging.py +94 -0
  12. inspice-1.6/InSpice/Logging/__init__.py +0 -0
  13. inspice-1.6/InSpice/Math/Calculus.py +164 -0
  14. inspice-1.6/InSpice/Math/__init__.py +46 -0
  15. inspice-1.6/InSpice/Physics/MaterialProperties.py +40 -0
  16. inspice-1.6/InSpice/Physics/PhysicalConstants.py +64 -0
  17. inspice-1.6/InSpice/Physics/Resistor.py +30 -0
  18. inspice-1.6/InSpice/Physics/SemiConductor.py +66 -0
  19. inspice-1.6/InSpice/Physics/__init__.py +0 -0
  20. inspice-1.6/InSpice/Plot/BodeDiagram.py +60 -0
  21. inspice-1.6/InSpice/Plot/__init__.py +0 -0
  22. inspice-1.6/InSpice/Probe/Plot.py +43 -0
  23. inspice-1.6/InSpice/Probe/WaveForm.py +497 -0
  24. inspice-1.6/InSpice/Probe/__init__.py +0 -0
  25. inspice-1.6/InSpice/Scripts/Library.py +125 -0
  26. inspice-1.6/InSpice/Scripts/__init__.py +0 -0
  27. inspice-1.6/InSpice/Scripts/cir2py.py +96 -0
  28. inspice-1.6/InSpice/Scripts/inspice_post_installation.py +470 -0
  29. inspice-1.6/InSpice/Scripts/pyspice_post_installation.py +470 -0
  30. inspice-1.6/InSpice/Spice/AnalysisParameters.py +526 -0
  31. inspice-1.6/InSpice/Spice/BasicElement.py +1728 -0
  32. inspice-1.6/InSpice/Spice/DeviceModel.py +130 -0
  33. inspice-1.6/InSpice/Spice/Element.py +680 -0
  34. inspice-1.6/InSpice/Spice/ElementParameter.py +375 -0
  35. inspice-1.6/InSpice/Spice/FakeDipole.py +90 -0
  36. inspice-1.6/InSpice/Spice/HighLevelElement.py +866 -0
  37. inspice-1.6/InSpice/Spice/Library/Library.py +316 -0
  38. inspice-1.6/InSpice/Spice/Library/SpiceInclude.py +576 -0
  39. inspice-1.6/InSpice/Spice/Library/__init__.py +28 -0
  40. inspice-1.6/InSpice/Spice/Library/product-categories/digi-key.yaml +435 -0
  41. inspice-1.6/InSpice/Spice/Library/product-categories/infineon.yaml +38 -0
  42. inspice-1.6/InSpice/Spice/Library/product-categories/mouser.yaml +115 -0
  43. inspice-1.6/InSpice/Spice/Netlist.py +745 -0
  44. inspice-1.6/InSpice/Spice/NgSpice/ManualExampleExtractor.py +147 -0
  45. inspice-1.6/InSpice/Spice/NgSpice/ManualExamples.py +7902 -0
  46. inspice-1.6/InSpice/Spice/NgSpice/RawFile.py +234 -0
  47. inspice-1.6/InSpice/Spice/NgSpice/Server.py +159 -0
  48. inspice-1.6/InSpice/Spice/NgSpice/Shared.py +1339 -0
  49. inspice-1.6/InSpice/Spice/NgSpice/SimulationType.py +90 -0
  50. inspice-1.6/InSpice/Spice/NgSpice/Simulator.py +126 -0
  51. inspice-1.6/InSpice/Spice/NgSpice/__init__.py +23 -0
  52. inspice-1.6/InSpice/Spice/NgSpice/api.h +76 -0
  53. inspice-1.6/InSpice/Spice/Parser/Ast.py +950 -0
  54. inspice-1.6/InSpice/Spice/Parser/ElementData.py +141 -0
  55. inspice-1.6/InSpice/Spice/Parser/HighLevelParser.py +1321 -0
  56. inspice-1.6/InSpice/Spice/Parser/Parser.py +582 -0
  57. inspice-1.6/InSpice/Spice/Parser/SpiceSyntax.py +156 -0
  58. inspice-1.6/InSpice/Spice/Parser/Translator.py +563 -0
  59. inspice-1.6/InSpice/Spice/Parser/__init__.py +35 -0
  60. inspice-1.6/InSpice/Spice/Parser/parsetab.py +82 -0
  61. inspice-1.6/InSpice/Spice/RawFile.py +410 -0
  62. inspice-1.6/InSpice/Spice/Simulation.py +791 -0
  63. inspice-1.6/InSpice/Spice/Simulator.py +164 -0
  64. inspice-1.6/InSpice/Spice/StringTools.py +98 -0
  65. inspice-1.6/InSpice/Spice/Xyce/RawFile.py +175 -0
  66. inspice-1.6/InSpice/Spice/Xyce/Server.py +140 -0
  67. inspice-1.6/InSpice/Spice/Xyce/Simulation.py +42 -0
  68. inspice-1.6/InSpice/Spice/Xyce/Simulator.py +76 -0
  69. inspice-1.6/InSpice/Spice/Xyce/__init__.py +0 -0
  70. inspice-1.6/InSpice/Spice/__init__.py +85 -0
  71. inspice-1.6/InSpice/Spice/unit.py +100 -0
  72. inspice-1.6/InSpice/Tools/EnumFactory.py +176 -0
  73. inspice-1.6/InSpice/Tools/PathTools.py +60 -0
  74. inspice-1.6/InSpice/Tools/TextBuffer.py +59 -0
  75. inspice-1.6/InSpice/Tools/__init__.py +0 -0
  76. inspice-1.6/InSpice/Unit/SiUnits.py +330 -0
  77. inspice-1.6/InSpice/Unit/Unit.py +1907 -0
  78. inspice-1.6/InSpice/Unit/__init__.py +238 -0
  79. inspice-1.6/InSpice/__init__.py +39 -0
  80. inspice-1.6/InSpice.egg-info/PKG-INFO +117 -0
  81. inspice-1.6/InSpice.egg-info/SOURCES.txt +186 -0
  82. inspice-1.6/InSpice.egg-info/dependency_links.txt +1 -0
  83. inspice-1.6/InSpice.egg-info/entry_points.txt +2 -0
  84. inspice-1.6/InSpice.egg-info/requires.txt +11 -0
  85. inspice-1.6/InSpice.egg-info/top_level.txt +1 -0
  86. inspice-1.6/LICENSE.txt +661 -0
  87. inspice-1.6/MANIFEST.in +14 -0
  88. inspice-1.6/PKG-INFO +117 -0
  89. inspice-1.6/README.md +79 -0
  90. inspice-1.6/examples/.travis/travis.py +3 -0
  91. inspice-1.6/examples/Settings.py +12 -0
  92. inspice-1.6/examples/advanced-usages/index.rst +5 -0
  93. inspice-1.6/examples/advanced-usages/internal-device-parameters.py +93 -0
  94. inspice-1.6/examples/analyses/analyses.py +201 -0
  95. inspice-1.6/examples/analyses/pole_zero_analysis.py +60 -0
  96. inspice-1.6/examples/analyses/test_pole_zero.cir +11 -0
  97. inspice-1.6/examples/basic-usages/index.rst +5 -0
  98. inspice-1.6/examples/basic-usages/netlist-manipulations.py +70 -0
  99. inspice-1.6/examples/basic-usages/raw-spice.py +36 -0
  100. inspice-1.6/examples/basic-usages/skidl-like.py +177 -0
  101. inspice-1.6/examples/basic-usages/subcircuit.py +62 -0
  102. inspice-1.6/examples/basic-usages/unit.py +107 -0
  103. inspice-1.6/examples/c-examples/ngspice-shared/test-module.py +68 -0
  104. inspice-1.6/examples/c-examples/ngspice-shared/test.py +225 -0
  105. inspice-1.6/examples/c-examples/ngspice_cb/examples/adder_mos.cir +66 -0
  106. inspice-1.6/examples/data-analysis/fft.py +103 -0
  107. inspice-1.6/examples/diode/RingModulator.py +41 -0
  108. inspice-1.6/examples/diode/diode-characteristic-curve.py +204 -0
  109. inspice-1.6/examples/diode/diode-recovery-time.py +158 -0
  110. inspice-1.6/examples/diode/index.rst +7 -0
  111. inspice-1.6/examples/diode/rectification.py +152 -0
  112. inspice-1.6/examples/diode/ring-modulator.py +92 -0
  113. inspice-1.6/examples/diode/voltage-multiplier.py +70 -0
  114. inspice-1.6/examples/diode/zener-characteristic-curve.py +79 -0
  115. inspice-1.6/examples/electricity/three-phase.py +99 -0
  116. inspice-1.6/examples/filter/low-pass-rc-filter.py +59 -0
  117. inspice-1.6/examples/filter/rlc-filter.py +124 -0
  118. inspice-1.6/examples/fundamental-laws/index.rst +61 -0
  119. inspice-1.6/examples/fundamental-laws/millman-theorem.py +81 -0
  120. inspice-1.6/examples/fundamental-laws/thevenin-norton-theorem.py +91 -0
  121. inspice-1.6/examples/fundamental-laws/voltage-current-divider.py +79 -0
  122. inspice-1.6/examples/index.rst +11 -0
  123. inspice-1.6/examples/kicadrw/dump-netlist.py +28 -0
  124. inspice-1.6/examples/ngspice-shared/external-source.py +100 -0
  125. inspice-1.6/examples/ngspice-shared/index.rst +12 -0
  126. inspice-1.6/examples/ngspice-shared/ngspice-interpreter.py +87 -0
  127. inspice-1.6/examples/operational-amplifier/OperationalAmplifier-api-brainstorming.py +58 -0
  128. inspice-1.6/examples/operational-amplifier/OperationalAmplifier.py +59 -0
  129. inspice-1.6/examples/operational-amplifier/astable.py +57 -0
  130. inspice-1.6/examples/operational-amplifier/operational-amplifier.py +50 -0
  131. inspice-1.6/examples/passive/capacitor-inductor.py +116 -0
  132. inspice-1.6/examples/persistance/SimulateCircuit.py +39 -0
  133. inspice-1.6/examples/persistance/cache.py +40 -0
  134. inspice-1.6/examples/persistance/hdf5.py +40 -0
  135. inspice-1.6/examples/persistance/index.rst +5 -0
  136. inspice-1.6/examples/persistance/pickling.py +87 -0
  137. inspice-1.6/examples/persistance/test-diskcache.py +80 -0
  138. inspice-1.6/examples/power-supplies/HP54501A.py +28 -0
  139. inspice-1.6/examples/power-supplies/capacitive-half-wave-rectification-post-zener.py +74 -0
  140. inspice-1.6/examples/power-supplies/capacitive-half-wave-rectification-pre-zener.py +78 -0
  141. inspice-1.6/examples/power-supplies/hp54501a-cem.py +68 -0
  142. inspice-1.6/examples/power-supplies/kicad/capacitive-half-wave-rectification-pre-zener/capacitive-half-wave-rectification-pre-zener.cir +13 -0
  143. inspice-1.6/examples/power-supplies/rectification.py +152 -0
  144. inspice-1.6/examples/relay/relay.py +71 -0
  145. inspice-1.6/examples/resistor/resistor-bridge.py +32 -0
  146. inspice-1.6/examples/resistor/voltage-divider.py +37 -0
  147. inspice-1.6/examples/skywater/print_subcircuit_nodes.py +54 -0
  148. inspice-1.6/examples/spice-examples/ac-coupled-amplifier.cir +18 -0
  149. inspice-1.6/examples/spice-examples/ac-coupled-transistor-amplifier.cir +25 -0
  150. inspice-1.6/examples/spice-examples/astable.cir +33 -0
  151. inspice-1.6/examples/spice-examples/diode-ac.cir +11 -0
  152. inspice-1.6/examples/spice-examples/diode.cir +18 -0
  153. inspice-1.6/examples/spice-examples/low-pass-rc-filter.cir +12 -0
  154. inspice-1.6/examples/spice-examples/operational-amplifier-model-1.cir +31 -0
  155. inspice-1.6/examples/spice-examples/operational-amplifier-model-2.cir +56 -0
  156. inspice-1.6/examples/spice-examples/resistor-bridge.cir +15 -0
  157. inspice-1.6/examples/spice-examples/small-signal-amplifier-with-diodes.cir +26 -0
  158. inspice-1.6/examples/spice-examples/small-signal-amplifier.cir +16 -0
  159. inspice-1.6/examples/spice-examples/transform-less-power-supply.cir +48 -0
  160. inspice-1.6/examples/spice-examples/transistor.cir +14 -0
  161. inspice-1.6/examples/spice-examples/transistor2.cir +9 -0
  162. inspice-1.6/examples/spice-examples/voltage-divider.cir +7 -0
  163. inspice-1.6/examples/spice-parser/bootstrap-example.py +60 -0
  164. inspice-1.6/examples/spice-parser/index.rst +3 -0
  165. inspice-1.6/examples/spice-parser/kicad-example.py +151 -0
  166. inspice-1.6/examples/spice-parser/kicad-pyspice-example/kicad-pyspice-example.cir +17 -0
  167. inspice-1.6/examples/spice-parser/kicad-spice-example/netlist/kicad-spice-example.default.cir +28 -0
  168. inspice-1.6/examples/spice-parser/kicad-spice-example/netlist/kicad-spice-example.number-node.cir +28 -0
  169. inspice-1.6/examples/spice-parser/kicad-spice-example/netlist/kicad-spice-example.using-X.cir +28 -0
  170. inspice-1.6/examples/spice-parser/kicad-spice-example/spice/components.cir +31 -0
  171. inspice-1.6/examples/spice-parser/kicad-spice-example/spice/example.cir +25 -0
  172. inspice-1.6/examples/spice-parser/parse-ngspice-examples.py +98 -0
  173. inspice-1.6/examples/spice-parser/parse-subcircuit-example.py +35 -0
  174. inspice-1.6/examples/spice-parser/raw_spice_parser.py +104 -0
  175. inspice-1.6/examples/spice-parser/raw_spice_parser_LM358.py +78 -0
  176. inspice-1.6/examples/switched-power-supplies/buck-converter.py +131 -0
  177. inspice-1.6/examples/switched-power-supplies/buck-converter_ngshared.py +170 -0
  178. inspice-1.6/examples/transformer/Transformer.py +54 -0
  179. inspice-1.6/examples/transformer/transformer-example.py +55 -0
  180. inspice-1.6/examples/transistor/ac-coupled-amplifier.py +66 -0
  181. inspice-1.6/examples/transistor/nmos-transistor.py +63 -0
  182. inspice-1.6/examples/transistor/transistor.py +145 -0
  183. inspice-1.6/examples/transmission-lines/time-delay.py +43 -0
  184. inspice-1.6/examples/xspice/input_clipper.py +57 -0
  185. inspice-1.6/examples/xspice/xspice.py +167 -0
  186. inspice-1.6/pyproject.toml +54 -0
  187. inspice-1.6/setup.cfg +4 -0
  188. inspice-1.6/setup.py +53 -0
@@ -0,0 +1,174 @@
1
+ ####################################################################################################
2
+ #
3
+ # InSpice - A Spice Package for Python
4
+ # Copyright (C) 2021 Fabrice Salvaire
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ ####################################################################################################
20
+
21
+ # Simulation outputs should be identical if
22
+ # same simulator and version
23
+ # same inputs
24
+
25
+ __all__ = ["SimulationCache"]
26
+
27
+ ####################################################################################################
28
+
29
+ from pathlib import Path
30
+ import hashlib
31
+
32
+ # http://www.grantjenks.com/docs/diskcache
33
+ from diskcache import Cache
34
+
35
+ ####################################################################################################
36
+
37
+ class SpiceInclude:
38
+
39
+ INCLUDE_PREFIX = '.include '
40
+
41
+ ##############################################
42
+
43
+ def __init__(self, path: str | Path):
44
+ self._path = Path(path)
45
+ self._inner_includes = []
46
+ self._walk()
47
+ self._digest = self.sha1()
48
+ self._recursive_digest = self._compute_recursive_digest()
49
+
50
+ ##############################################
51
+
52
+ @property
53
+ def path(self) -> Path:
54
+ return self._path
55
+
56
+ ##############################################
57
+
58
+ def _compute_digest(self, func) -> str:
59
+ with open(self._path, 'rb') as fh:
60
+ _ = func(fh.read()).hexdigest()
61
+ return _
62
+
63
+ ##############################################
64
+
65
+ def sha1(self) -> str:
66
+ return self._compute_digest(hashlib.sha1)
67
+
68
+ ##############################################
69
+
70
+ @classmethod
71
+ def parse_include(self, line):
72
+ line = line.strip()
73
+ if line.startswith(self.INCLUDE_PREFIX):
74
+ path = line[len(self.INCLUDE_PREFIX):].strip()
75
+ if path:
76
+ return Path(path)
77
+ return None
78
+
79
+ ##############################################
80
+
81
+ def _walk(self) -> None:
82
+ with open(self._path, 'r') as fh:
83
+ for line in fh.readlines():
84
+ path = self.parse_include(line)
85
+ if path is not None:
86
+ include = SpiceInclude(path)
87
+ self._inner_includes.append(include)
88
+
89
+ ##############################################
90
+
91
+ def _compute_recursive_digest(self) -> str:
92
+ if self._inner_includes:
93
+ return self._digest + '[' + '/'.join([_.digest for _ in self._inner_includes]) + ']'
94
+ else:
95
+ return self._digest
96
+
97
+ ##############################################
98
+
99
+ @property
100
+ def digest(self) -> str:
101
+ return self._digest
102
+
103
+ @property
104
+ def recursive_digest(self) -> str:
105
+ return self._recursive_digest
106
+
107
+ @property
108
+ def inner_includes(self) -> str:
109
+ return iter(self._inner_includes)
110
+
111
+ ####################################################################################################
112
+
113
+ class SimulationCache:
114
+
115
+ ##############################################
116
+
117
+ def __init__(self, path: str | Path=None):
118
+ """
119
+ Cache directory will be set to a temporary directory like "/tmp/diskcache-...", if *Path* is None.
120
+ """
121
+ self._cache = Cache(path)
122
+
123
+ ##############################################
124
+
125
+ def __del__(self):
126
+ # Each thread that accesses a cache should also call close on the cache.
127
+ self._cache.close()
128
+
129
+ ##############################################
130
+
131
+ @property
132
+ def impl(self) -> Cache:
133
+ return self._cache
134
+
135
+ @property
136
+ def directory(self) -> str:
137
+ return self._cache.directory
138
+
139
+ ##############################################
140
+
141
+ def simulation_key(self, simulation) -> str:
142
+ raw_spice_code = str(simulation)
143
+ lines = []
144
+ # Replace .include lines by recursive digest
145
+ for line in raw_spice_code.splitlines():
146
+ # for path in simulation.circuit.includes:
147
+ path = SpiceInclude.parse_include(line)
148
+ if path is not None:
149
+ include = SpiceInclude(path)
150
+ lines.append(f'.include {include.path.name} {include.recursive_digest}')
151
+ else:
152
+ lines.append(line)
153
+ # Replace os.linesep to a portable separator
154
+ spice_code = '@@'.join(lines)
155
+ return f'{simulation.simulator_name}/{simulation.simulator_version}/{spice_code}'
156
+
157
+ ##############################################
158
+
159
+ def add(self, analysis):
160
+ pass
161
+
162
+ ##############################################
163
+
164
+ def get(self, simulation):
165
+ pass
166
+
167
+ ####################################################################################################
168
+
169
+ class CachedSimulation:
170
+
171
+ ##############################################
172
+
173
+ def __init__(self, spice_code):
174
+ pass
@@ -0,0 +1,65 @@
1
+ ####################################################################################################
2
+
3
+ from pathlib import Path
4
+
5
+ import sys
6
+
7
+ ####################################################################################################
8
+
9
+ from InSpice.Tools import PathTools
10
+
11
+ ####################################################################################################
12
+
13
+ class OsFactory:
14
+
15
+ ##############################################
16
+
17
+ def __init__(self):
18
+ if sys.platform.startswith('linux'):
19
+ self._name = 'linux'
20
+ elif sys.platform.startswith('win'):
21
+ self._name = 'windows'
22
+ elif sys.platform.startswith('darwin'):
23
+ self._name = 'osx'
24
+
25
+ ##############################################
26
+
27
+ @property
28
+ def name(self):
29
+ return self._name
30
+
31
+ @property
32
+ def on_linux(self):
33
+ return self._name == 'linux'
34
+
35
+ @property
36
+ def on_windows(self):
37
+ return self._name == 'windows'
38
+
39
+ @property
40
+ def on_osx(self):
41
+ return self._name == 'osx'
42
+
43
+ OS = OsFactory()
44
+
45
+ ####################################################################################################
46
+
47
+ _this_file = Path(__file__).absolute()
48
+
49
+ class Path:
50
+
51
+ InSpice_module_directory = _this_file.parents[1]
52
+ config_directory = _this_file.parent
53
+
54
+ ####################################################################################################
55
+
56
+ class Logging:
57
+
58
+ default_config_file = 'logging.yml'
59
+ directories = (Path.config_directory,)
60
+
61
+ ##############################################
62
+
63
+ @staticmethod
64
+ def find(config_file):
65
+ return PathTools.find(config_file, Logging.directories)
File without changes
@@ -0,0 +1,51 @@
1
+ ####################################################################################################
2
+ #
3
+ # ANSI Codes
4
+ #
5
+ # RESET \033[0m
6
+ # COLOR \033[1;%dm
7
+ # BOLD \033[1m
8
+ #
9
+ ####################################################################################################
10
+
11
+ version: 1
12
+
13
+ ####################################################################################################
14
+
15
+ formatters:
16
+
17
+ simple:
18
+ format: '%(asctime)s - %(name)s - %(module)s.%(levelname)s - %(message)s'
19
+
20
+ ansi:
21
+ format: '<ESC>[1;32m%(asctime)s<ESC>[0m - <ESC>[1;34m%(name)s.%(funcName)s<ESC>[0m - <ESC>[1;31m%(levelname)s<ESC>[0m - %(message)s'
22
+
23
+ ####################################################################################################
24
+
25
+ handlers:
26
+
27
+ console:
28
+ class: logging.StreamHandler
29
+ # level: INFO
30
+ # formatter: ansi
31
+ stream: ext://sys.stdout
32
+
33
+ ####################################################################################################
34
+
35
+ # InSpice.Doc.ExampleTools.find_libraries
36
+ root:
37
+ # level: CRITICAL
38
+ # level: ERROR
39
+ level: WARNING
40
+ # level: INFO
41
+ # level: DEBUG
42
+ handlers: [console]
43
+
44
+ ####################################################################################################
45
+
46
+ loggers:
47
+
48
+ InSpice:
49
+ # level: DEBUG
50
+ level: INFO
51
+ # level: WARNING
@@ -0,0 +1,105 @@
1
+ ####################################################################################################
2
+ #
3
+ # InSpice - A Spice Package for Python
4
+ # Copyright (C) 2017 Fabrice Salvaire
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ ####################################################################################################
20
+
21
+ ####################################################################################################
22
+
23
+ class Manufacturer:
24
+
25
+ ##############################################
26
+
27
+ def __init__(
28
+ self,
29
+ name,
30
+ url=None,
31
+ ):
32
+ self._name = name
33
+ self._url = url
34
+
35
+ ##############################################
36
+
37
+ @property
38
+ def name(self):
39
+ return self._name
40
+
41
+ @name.setter
42
+ def name(self, value):
43
+ self._name = value
44
+
45
+ @property
46
+ def url(self):
47
+ return self._url
48
+
49
+ @url.setter
50
+ def url(self, value):
51
+ self._url = value
52
+
53
+ ####################################################################################################
54
+
55
+ class Footprint:
56
+
57
+ ##############################################
58
+
59
+ def __init__(
60
+ self,
61
+ name,
62
+ ):
63
+ self._name = name
64
+
65
+ ##############################################
66
+
67
+ @property
68
+ def name(self):
69
+ return self._name
70
+
71
+ @name.setter
72
+ def name(self, value):
73
+ self._name = value
74
+
75
+ ####################################################################################################
76
+
77
+ class Device:
78
+
79
+ ##############################################
80
+
81
+ def __init__(
82
+ self,
83
+ name,
84
+ manufacturer,
85
+ datasheet_url=None,
86
+ model_url=None
87
+ ):
88
+ # part
89
+ # part_number
90
+ # footprint
91
+ # description
92
+ # device_category x/y
93
+ # pins
94
+ # features / parameters
95
+ self._name = name
96
+
97
+ ##############################################
98
+
99
+ @property
100
+ def name(self):
101
+ return self._name
102
+
103
+ @name.setter
104
+ def name(self, value):
105
+ self._name = value
@@ -0,0 +1,49 @@
1
+ ####################################################################################################
2
+ #
3
+ # InSpice - A Spice Package for Python
4
+ # Copyright (C) 2017 Fabrice Salvaire
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ ####################################################################################################
20
+
21
+ __all__ = ['find_libraries', 'LIBRARY_PATH']
22
+
23
+ ####################################################################################################
24
+
25
+ from pathlib import Path
26
+ import logging
27
+ import os
28
+ import sys
29
+
30
+ ####################################################################################################
31
+
32
+ _module_logger = logging.getLogger(__name__)
33
+
34
+ ####################################################################################################
35
+
36
+ LIBRARY_PATH = 'spice-library'
37
+
38
+ def find_libraries(root: str='examples') -> Path:
39
+ try:
40
+ library_path = os.environ['InSpiceLibraryPath']
41
+ except KeyError:
42
+ examples_root = Path(sys.argv[0]).resolve() # path of the Python file
43
+ while True:
44
+ examples_root = examples_root.parents[1]
45
+ if examples_root.name == root:
46
+ break
47
+ library_path = examples_root.joinpath(LIBRARY_PATH)
48
+ _module_logger.info(f'SPICE library path is {library_path}')
49
+ return library_path
File without changes
@@ -0,0 +1,126 @@
1
+ ####################################################################################################
2
+ #
3
+ # InSpice - A Spice Package for Python
4
+ # Copyright (C) 2021 Fabrice Salvaire
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ ####################################################################################################
20
+
21
+ __all__ = ["Hdf5File"]
22
+
23
+ ####################################################################################################
24
+
25
+ # File structure
26
+ # using h5ls -r simulation.hdf5
27
+ #
28
+ # / Group
29
+ # /version Dataset {SCALAR}
30
+ # /simulation Group
31
+ # /abscissas Group
32
+ # /abscissas/time Dataset {10038}
33
+ # /branches Group
34
+ # /branches/e.xdz.ev1 Dataset {10038}
35
+ # /branches/...
36
+ # /elements Group
37
+ # /internal_parameters Group
38
+ # /nodes Group
39
+ # /nodes/1 Dataset {10038}
40
+ # /nodes/...
41
+
42
+ # h5dump -g "/simulation" simulation.hdf5
43
+ # h5dump -d "/abscissas/time" simulation.hdf5
44
+ # h5dump -d "/nodes/1" simulation.hdf5
45
+
46
+ ####################################################################################################
47
+
48
+ import pickle
49
+
50
+ import numpy as np
51
+
52
+ # https://docs.h5py.org/en/stable/index.html
53
+ import h5py
54
+
55
+ ####################################################################################################
56
+
57
+ class Hdf5File:
58
+
59
+ _VERSION = 1
60
+
61
+ ##############################################
62
+
63
+ @classmethod
64
+ def save(cls, analysis, path):
65
+ self = cls(path, 'w')
66
+ self._save(analysis)
67
+
68
+ ##############################################
69
+
70
+ def __init__(self, path, mode=None):
71
+ self._file = h5py.File(path, mode)
72
+
73
+ ##############################################
74
+
75
+ def _save(self, analysis):
76
+ self._file["version"] = self._VERSION
77
+
78
+ simulation = analysis.simulation
79
+ group = self._file.create_group("simulation")
80
+ attrs = group.attrs
81
+ attrs["simulator"] = simulation.simulator.SIMULATOR
82
+ attrs["simulator_version"] = simulation.simulator_version
83
+ attrs["simulation_date"] = str(simulation.simulation_date)
84
+ attrs["simulation_duration"] = str(simulation.simulation_duration)
85
+ attrs["spice_circuit"] = str(simulation.circuit)
86
+ attrs["spice_simulation"] = str(simulation) # Fixme: remove desk
87
+ # https://docs.h5py.org/en/stable/strings.html#how-to-store-raw-binary-data
88
+ attrs["pickled_simulation"] = np.void(pickle.dumps(simulation))
89
+
90
+ self._abscissa = self._file.create_group("abscissas")
91
+ for list_name in ("nodes", "branches", "elements", "internal_parameters"):
92
+ group = self._file.create_group(list_name)
93
+ for waveform in getattr(analysis, list_name).values():
94
+ self._add_waveform(group, waveform)
95
+
96
+ ##############################################
97
+
98
+ def _add_waveform_common(self, group, waveform):
99
+ dset = group.create_dataset(
100
+ waveform.name,
101
+ data=waveform,
102
+ compression="gzip", compression_opts=9
103
+ # compression="lzf
104
+ )
105
+ attrs = dset.attrs
106
+ attrs["unit"] = str(waveform.unit)
107
+ return dset
108
+
109
+ ##############################################
110
+
111
+ def _add_abscissa(self, abscissa):
112
+ # Fixme: is time always unique ???
113
+ # See https://docs.h5py.org/en/stable/high/group.html#hard-links
114
+ if abscissa.name not in self._abscissa:
115
+ # self._abscissa[abscissa.name] = abscissa
116
+ self._add_waveform_common(self._abscissa, abscissa)
117
+ return self._abscissa[abscissa.name]
118
+
119
+ ##############################################
120
+
121
+ def _add_waveform(self, group, waveform):
122
+ dset = self._add_waveform_common(group, waveform)
123
+ attrs = dset.attrs
124
+ if waveform.title:
125
+ attrs["title"] = waveform.title
126
+ attrs["abscissa"] = self._add_abscissa(waveform.abscissa).ref
File without changes