from pylab import *



class Circuit(object):



    def nodenumber(self, node):
        if node in self.nodes:
            return self.nodes.index(node) + 1
        else:
            self.nodes.append(node)
            self.nn = len(self.nodes)
            return self.nn



    def branchnumber(self, branchname):
        self.nb += 1
        self.branches = branchname
        return self.nb


            
    def elementvalue(self, value):
        try:
            return float(value)
        except:
            return False



    def __init__(self, name):
    
        self.name = name # netlist file name
        
        self.lines = [] # lines of the netlist file
        self.slines = [] # splitted lines of the netlist file
        self.line_number = [] # line numbers in original file
        
        self.nb = 0 # number of branches
        self.nn = 0 # number of nodes
        
        self.ni = 0 # number of current sources
        self.iname = []
        self.inode1 = []
        self.inode2 = []
        self.ibranch = []
        self.ival = []
        
        self.nv = 0 # number of voltage sources
        self.vname = []
        self.vnode1 = []
        self.vnode2 = []
        self.vbranch = []
        self.vvalue = []
        
        self.nr = 0 # number of resistors
        self.rname = []
        self.rnode1 = []
        self.rnode2 = []
        self.rbranch = []
        self.rvalue = []
        
        self.nc = 0 # number of capacitors
        self.cname = []
        self.cnode1 = []
        self.cnode2 = []
        self.cbranch = []
        self.cvalue = []
        
        self.nl = 0 # number of inductors
        self.lname = []
        self.lnode1 = []
        self.lnode2 = []
        self.lbranch = []
        self.lvalue = []
        
        self.branches = []
        self.bcon = []
        self.nb = 0
        
        self.nodes = []
        self.nn = 0
        
        self.status = False
        
        try:
            f = open(name, 'r')
        except:
            print 'cannot open file'
            return False
            
        lc = 0 # line counter
        for line in f:
        
            lc += 1
            if line != '':
            
                self.line_number.append(lc)
                self.lines.append(line)
                self.slines.append(line.split())
                
                name = self.slines[-1][0]
                element = name[0].lower()
                
                if element == 'i':
                    self.ni += 1
                    self.iname.append(name)
                    self.inode1.append(self.nodenumber(self.slines[-1][1]))
                    self.inode2.append(self.nodenumber(self.slines[-1][2]))
                    self.ivalue.append(self.elementvalue(self.slines[-1][3]))
                    self.ibranch.append(self.branchnumber(name))
                    self.bcon.append([self.inode1[-1], self.inode2[-1]])
                    
                if element == 'v':
                    self.nv += 1
                    self.vname.append(name)
                    self.vnode1.append(self.nodenumber(self.slines[-1][1]))
                    self.vnode2.append(self.nodenumber(self.slines[-1][2]))
                    self.vvalue.append(self.elementvalue(self.slines[-1][3]))
                    self.vbranch.append(self.branchnumber(name))
                    self.bcon.append([self.vnode1[-1], self.vnode2[-1]])

                if element == 'r':
                    self.nr += 1
                    self.rname.append(name)
                    self.rnode1.append(self.nodenumber(self.slines[-1][1]))
                    self.rnode2.append(self.nodenumber(self.slines[-1][2]))
                    self.rvalue.append(self.elementvalue(self.slines[-1][3]))
                    self.rbranch.append(self.branchnumber(name))
                    self.bcon.append([self.rnode1[-1], self.rnode2[-1]])
                    
                if element == 'c':
                    self.nc += 1
                    self.cname.append(name)
                    self.cnode1.append(self.nodenumber(self.slines[-1][1]))
                    self.cnode2.append(self.nodenumber(self.slines[-1][2]))
                    self.cvalue.append(self.elementvalue(self.slines[-1][3]))
                    self.cbranch.append(self.branchnumber(name))
                    self.bcon.append([self.cnode1[-1], self.cnode2[-1]])

                if element == 'l':
                    self.nl += 1
                    self.lname.append(name)
                    self.lnode1.append(self.nodenumber(self.slines[-1][1]))
                    self.lnode2.append(self.nodenumber(self.slines[-1][2]))
                    self.lvalue.append(self.elementvalue(self.slines[-1][3]))
                    self.lbranch.append(self.branchnumber(name))
                    self.bcon.append([self.lnode1[-1], self.lnode2[-1]])

        self.status = True



    def incidencefull(self):
        self.a = zeros((self.nn, self.nb), dtype = int)
        for b in range(self.nb):
            self.a[self.bcon[b][0] - 1, b] = 1
            self.a[self.bcon[b][1] - 1, b] = -1
        return self.a



    def incidence(self, refnode):
        if refnode in self.nodes:
            refnodeindex = self.nodes.index(refnode)
        else:
            print 'no such refnode'
            return False
        self.A = empty((self.nn - 1, self.nb), dtype = int)
        for i in range(refnodeindex):
            self.A[i, :] = self.a[i, :]
        for i in range(refnodeindex, self.nn - 1):
            self.A[i, :] = self.a[i + 1, :]
        return self.A
        
