## 1. Introduction

The SPICE program (Simulated Program with Integrated Circuit Emphasis) performs simulations of analog electronic circuits. The reference version (spice 2g6, 1983) is written in FORTRAN. A more recent version (spice 3, 1985) is written in C. Many commercial simulation software uses the SPICE calculation engine, adding additional functions.

We are interested here in the free versions of spice, ngspice and SpiceOpus, which are based on spice3f5. These two programs read a text file comprising a description of the circuit and various commands. The print command allows you to export the results to a text file. The plot command allows you to plot curves. In order to obtain high quality graphics output, or to perform various data processing operations, it may be useful to import into Python the data exported by SPICE with the print command. This page presents a python function doing this import.

## 2. Import python function

To export data to a text file, the spice command is: PRINT v1 v2 …> file.txt, where v1 v2 … are the names of the data vectors to export.

The following function imports the data from the file, which it returns in the form of a dictionary whose keys are the names of the fields. The numpy arrays obtained are arrays of reals or complexes. LectureSpicePrint.py

import re import numpy def lectureSpicePrint(filename): f = open(filename,"r") lignes = f.readlines() k = 0 while not re.match("-+",lignes[k]): print(lignes[k]) k += 1 k += 1 entete =lignes[k].strip() champs = re.split("\s+",entete) print(champs) k += 2 ligne = lignes[k].strip() valeurs = re.split("\s+",ligne) complexes = [] data = {} j = 0 for i in range(len(champs)): valeurs[i] = valeurs[i].strip() if valeurs[j][len(valeurs[j])-1] == ",": complexes.append(True) j += 2 data[champs[i]] = numpy.zeros(0,numpy.complex128) else: complexes.append(False) j += 1 data[champs[i]] = numpy.zeros(0,numpy.float64) index = 0 while k < len(lignes): ligne = lignes[k].strip() if re.match("^[\d+]",ligne): valeurs = re.split("\s+",ligne) j = 0 for i in range(len(champs)): if complexes[i]: valeurs[j]= valeurs[j][:len(valeurs[2])-1] valeurs[j]= valeurs[j].replace(",",".") valeurs[j+1]= valeurs[j+1].replace(",",".") data[champs[i]] = numpy.append(data[champs[i]],complex(float(valeurs[j]),float(valeurs[j+1]))) j += 2 else: valeurs[j]= valeurs[j].replace(",",".") data[champs[i]] = numpy.append(data[champs[i]],float(valeurs[j])) j += 1 k += 1 f.close() return data

## 3. Example

We consider an RC circuit:

The file below describes this circuit and does an AC (frequency response) analysis. The exported data are the voltage in decibels and the phase on node 2.

RC circuit v1 1 0 dc 0 ac 1 r1 1 2 1k c1 2 0 100n r2 2 0 1MEG .control ac dec 10 10Hz 100kHz print vdb(2) vp(2)> export-1.txt .endc .end

Here is the command executed:

ngspice -b circuitRC-1.cir

and importing data into python:

from lectureSpicePrint import lectureSpicePrint from matplotlib.pyplot import * data = lectureSpicePrint("export-1.txt") f = data["frequency"] vdb2 = data["vdb(2)"] vp2 = data["vp(2)"] figure(figsize=(10,10)) subplot("211") plot(f,vdb2) xscale('symlog') xlabel('f (Hz)') ylabel('GdB') grid() subplot("212") plot(f,vp2) xscale('symlog') xlabel('f (Hz)') ylabel('phi (rad)') grid()

Let’s do a transient analysis with the same circuit:

RC circuit v1 1 0 dc 1 r1 1 2 1k c1 2 0 100n ic=0 r2 2 0 1MEG .control tran 1Us 1ms uic print v(2)> export-2.txt .endc .end

ngspice -b circuitRC-2.cir

data = lectureSpicePrint("export-2.txt") t = data["time"]*1000 v2 = data["v(2)"] figure(figsize=(10,5)) plot(t,v2) xlabel("t (ms)") ylabel("v2 (V)") grid()