from __future__ import division # Used for decimal division eg 2/3=0.66 and not '0' 6/2=3.0 and 6//2=3 import os from PyQt4 import QtGui, QtCore from decimal import Decimal from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar from matplotlib.figure import Figure from configuration.Appconfig import Appconfig class plotWindow(QtGui.QMainWindow): def __init__(self,fpath,projectName): QtGui.QMainWindow.__init__(self) self.fpath = fpath#+".cir.out" self.projectName = projectName self.obj_appconfig = Appconfig() print "Path : ",self.fpath print "Project Name : ",self.projectName self.obj_appconfig.print_info('Ngspice simulation is called : ' + self.fpath) self.obj_appconfig.print_info('PythonPlotting is called : ' + self.fpath) self.combo = [] self.combo1 = [] self.combo1_rev = [] #Creating Frame self.createMainFrame() def createMainFrame(self): self.mainFrame = QtGui.QWidget() self.dpi = 100 self.fig = Figure((7.0, 7.0), dpi=self.dpi) #Creating Canvas which will figure self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.mainFrame) self.axes = self.fig.add_subplot(111) self.navToolBar = NavigationToolbar(self.canvas, self.mainFrame) #LeftVbox hold navigation tool bar and canvas self.left_vbox = QtGui.QVBoxLayout() self.left_vbox.addWidget(self.navToolBar) self.left_vbox.addWidget(self.canvas) #right VBOX is main Layout which hold right grid(bottom part) and top grid(top part) self.right_vbox = QtGui.QVBoxLayout() self.right_grid = QtGui.QGridLayout() self.top_grid = QtGui.QGridLayout() #Get DataExtraction Details self.obj_dataext = DataExtraction() self.plotType = self.obj_dataext.openFile(self.fpath) self.obj_dataext.computeAxes() self.a = self.obj_dataext.numVals() self.chkbox=[] ########### Generating list of colors : self.full_colors = ['r','b','g','y','c','m','k']#,(0.4,0.5,0.2),(0.1,0.4,0.9),(0.4,0.9,0.2),(0.9,0.4,0.9)] self.color = [] for i in range(0,self.a[0]-1): if i%7 == 0: self.color.append(self.full_colors[0]) elif (i-1)%7 == 0: self.color.append(self.full_colors[1]) elif (i-2)%7 == 0: self.color.append(self.full_colors[2]) elif (i-3)%7 == 0: self.color.append(self.full_colors[3]) elif (i-4)%7 == 0: self.color.append(self.full_colors[4]) elif (i-5)%7 == 0: self.color.append(self.full_colors[5]) elif (i-6)%7 == 0: self.color.append(self.full_colors[6]) ###########Color generation ends here #Total number of voltage source self.volts_length = self.a[1] self.analysisType = QtGui.QLabel() self.top_grid.addWidget(self.analysisType,0,0) self.listNode = QtGui.QLabel() self.top_grid.addWidget(self.listNode,1,0) self.listBranch = QtGui.QLabel() self.top_grid.addWidget(self.listBranch,self.a[1]+2,0) for i in range(0,self.a[1]):#a[0]-1 self.chkbox.append(QtGui.QCheckBox(self.obj_dataext.NBList[i])) self.chkbox[i].setToolTip('Check To Plot' ) self.top_grid.addWidget(self.chkbox[i],i+2,0) for i in range(self.a[1],self.a[0]-1):#a[0]-1 self.chkbox.append(QtGui.QCheckBox(self.obj_dataext.NBList[i])) self.chkbox[i].setToolTip('Check To Plot' ) self.top_grid.addWidget(self.chkbox[i],i+3,0) self.clear = QtGui.QPushButton("Clear") self.warnning = QtGui.QLabel() self.funcName = QtGui.QLabel() self.funcExample = QtGui.QLabel() self.plotbtn = QtGui.QPushButton("Plot") self.plotbtn.setToolTip('Press to Plot' ) self.text = QtGui.QLineEdit() self.funcLabel = QtGui.QLabel() self.palette1 = QtGui.QPalette() self.palette2 = QtGui.QPalette() self.plotfuncbtn = QtGui.QPushButton("Plot Function") self.plotfuncbtn.setToolTip('Press to Plot the function' ) self.palette1.setColor(QtGui.QPalette.Foreground,QtCore.Qt.blue) self.palette2.setColor(QtGui.QPalette.Foreground,QtCore.Qt.red) self.funcName.setPalette(self.palette1) self.funcExample.setPalette(self.palette2) self.right_vbox.addLayout(self.top_grid) self.right_vbox.addWidget(self.plotbtn) self.right_grid.addWidget(self.funcLabel,1,0) self.right_grid.addWidget(self.text,1,1) self.right_grid.addWidget(self.plotfuncbtn,2,1) self.right_grid.addWidget(self.clear,2,0) self.right_grid.addWidget(self.warnning,3,0) self.right_grid.addWidget(self.funcName,4,0) self.right_grid.addWidget(self.funcExample,4,1) self.right_vbox.addLayout(self.right_grid) self.hbox = QtGui.QHBoxLayout() self.hbox.addLayout(self.left_vbox) self.hbox.addLayout(self.right_vbox) self.widget = QtGui.QWidget() self.widget.setLayout(self.hbox)#finalvbox self.scrollArea = QtGui.QScrollArea() self.scrollArea.setWidgetResizable(True) self.scrollArea.setWidget(self.widget) self.finalhbox = QtGui.QHBoxLayout() self.finalhbox.addWidget(self.scrollArea) self.mainFrame.setLayout(self.finalhbox) self.showMaximized() self.listNode.setText("List of Nodes:") self.listBranch.setText("List of Branches:") self.funcLabel.setText("Function:") self.funcName.setText("Examples:\

Addition:
Subtraction:
Multiplication:
Division:
Comparison:") self.funcExample.setText("\n\nV(1) + V(2)\nV(1) - V(2)\nV(1) * V(2)\nV(1) / V(2)\nV(1) vs V(2)") #Connecting to plot and clear function self.connect(self.clear,QtCore.SIGNAL('clicked()'),self.pushedClear) self.connect(self.plotfuncbtn,QtCore.SIGNAL('clicked()'), self.pushedPlotFunc) if self.plotType[0]==0: self.analysisType.setText("AC Analysis") if self.plotType[1]==1: self.connect(self.plotbtn, QtCore.SIGNAL('clicked()'), self.onPush_decade) else: self.connect(self.plotbtn, QtCore.SIGNAL('clicked()'), self.onPush_ac) elif self.plotType[0]==1: self.analysisType.setText("Transient Analysis") self.connect(self.plotbtn, QtCore.SIGNAL('clicked()'), self.onPush_trans) else: self.analysisType.setText("DC Analysis") self.connect(self.plotbtn, QtCore.SIGNAL('clicked()'), self.onPush_dc) self.setCentralWidget(self.mainFrame) def pushedClear(self): #print "Calling Clear Canvas function" self.text.clear() self.axes.cla() self.canvas.draw() QtCore.SLOT('quit()') def pushedPlotFunc(self): #print "Calling Plot function" self.parts = str(self.text.text()) self.parts = self.parts.split(" ") #print "Parts :",self.parts if self.parts[len(self.parts)-1] == '': self.parts = self.parts[0:-1] self.values = self.parts self.comboAll = [] self.axes.cla() self.plotType2 = self.obj_dataext.openFile(self.fpath) if len(self.parts) <= 2: self.warnning.setText("Too few arguments!\nRefer syntax below!") QtGui.QMessageBox.about(self, "Warning!!", "Too Few Arguments/SYNTAX Error!\n Refer Examples") else: self.warnning.setText("") a = [] finalResult = [] p = 0 for i in range(len(self.parts)): #print "I",i if i%2 == 0: #print "I'm in:" for j in range(len(self.obj_dataext.NBList)): if self.parts[i]==self.obj_dataext.NBList[j]: #print "I got you:",self.parts[i] a.append(j) if len(a) != len(self.parts)//2 + 1: QtGui.QMessageBox.about(self, "Warning!!", "One of the operands doesn't belong to the above list of Nodes!!") for i in a: self.comboAll.append(self.obj_dataext.y[i]) for i in range(len(a)): if a[i] == len(self.obj_dataext.NBList): QtGui.QMessageBox.about(self, "Warning!!", "One of the operands doesn't belong to the above list!!") self.warnning.setText("To Err Is Human!
One of the operands doesn't belong to the above list!!
") if self.parts[1] == 'vs': if len(self.parts) > 3: self.warnning.setText("Enter two operands only!!") QtGui.QMessageBox.about(self, "Warning!!", "Recheck the expression syntax!") else: self.axes.cla() for i in range(len(self.obj_dataext.y[a[0]])): self.combo.append(self.obj_dataext.y[a[0]][i]) self.combo1.append(self.obj_dataext.y[a[1]][i]) self.axes.plot(self.combo,self.combo1,c=self.color[1],label=str(2))#_rev if max(a) < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') self.axes.set_xlabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') self.axes.set_ylabel('Current(I)-->') elif max(a) >= self.volts_length and min(a) < self.volts_length: QtGui.QMessageBox.about(self, "Warning!!", "Do not combine Voltage and Current!!") else: for j in range(len(self.comboAll[0])): for i in range(len(self.values)): if i%2==0: self.values[i] = str(self.comboAll[i//2][j]) re = " ".join(self.values[:]) try: finalResult.append(eval(re)) except ArithmeticError: QtGui.QMessageBox.about(self, "Warning!!", "Dividing by zero!!") if self.plotType2[0]==0: #self.setWindowTitle('AC Analysis') if self.plotType2[1]==1: self.axes.semilogx(self.obj_dataext.x,finalResult,c=self.color[0],label=str(1)) else: self.axes.plot(self.obj_dataext.x,finalResult,c=self.color[0],label=str(1)) self.axes.set_xlabel('freq-->') if max(a) < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') elif self.plotType2[0]==1: #self.setWindowTitle('Transient Analysis') self.axes.plot(self.obj_dataext.x,finalResult,c=self.color[0],label=str(1)) self.axes.set_xlabel('time-->') if max(a) < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') else: #self.setWindowTitle('DC Analysis') self.axes.plot(self.obj_dataext.x,finalResult,c=self.color[0],label=str(1)) self.axes.set_xlabel('I/P Voltage-->') if max(a) < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') self.axes.grid(True) self.canvas.draw() self.combo = [] self.combo1 = [] self.combo1_rev = [] def onPush_decade(self): #print "Calling on push Decade" boxCheck = 0 self.axes.cla() for i,j in zip(self.chkbox,range(len(self.chkbox))): if i.isChecked(): boxCheck += 1 self.axes.semilogx(self.obj_dataext.x,self.obj_dataext.y[j],c=self.color[j],label=str(j+1)) self.axes.set_xlabel('freq-->') if j < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') self.axes.grid(True) if boxCheck == 0: QtGui.QMessageBox.about(self, "Warning!!","Please select at least one Node OR Branch") self.canvas.draw() def onPush_ac(self): #print "Calling on push ac" self.axes.cla() boxCheck = 0 for i,j in zip(self.chkbox,range(len(self.chkbox))): if i.isChecked(): boxCheck += 1 self.axes.plot(self.obj_dataext.x,self.obj_dataext.y[j],c=self.color[j],label=str(j+1)) self.axes.set_xlabel('freq-->') if j < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') self.axes.grid(True) if boxCheck == 0: QtGui.QMessageBox.about(self, "Warning!!","Please select at least one Node OR Branch") self.canvas.draw() def onPush_trans(self): #print "Calling on push trans" self.axes.cla() boxCheck = 0 for i,j in zip(self.chkbox,range(len(self.chkbox))): if i.isChecked(): boxCheck += 1 self.axes.plot(self.obj_dataext.x,self.obj_dataext.y[j],c=self.color[j],label=str(j+1)) self.axes.set_xlabel('time-->') if j < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') self.axes.grid(True) if boxCheck == 0: QtGui.QMessageBox.about(self, "Warning!!","Please select at least one Node OR Branch") self.canvas.draw() def onPush_dc(self): #print "Calling on push dc" boxCheck = 0 self.axes.cla() for i,j in zip(self.chkbox,range(len(self.chkbox))): if i.isChecked(): boxCheck += 1 self.axes.plot(self.obj_dataext.x,self.obj_dataext.y[j],c=self.color[j],label=str(j+1)) self.axes.set_xlabel('Voltage Sweep(V)-->') if j < self.volts_length: self.axes.set_ylabel('Voltage(V)-->') else: self.axes.set_ylabel('Current(I)-->') self.axes.grid(True) if boxCheck == 0: QtGui.QMessageBox.about(self,"Warning!!", "Please select atleast one Node OR Branch") self.canvas.draw() class DataExtraction: def __init__(self): self.obj_appconfig = Appconfig() print "Initialization" self.data=[] #consists of all the columns of data belonging to nodes and branches self.y=[] #stores y-axis data self.x=[] #stores x-axis data def numberFinder(self,fpath): #Opening ANalysis file with open(os.path.join(fpath,"analysis")) as f3: self.analysisInfo = f3.read() self.analysisInfo = self.analysisInfo.split(" ") #Reading data file for voltage with open(os.path.join(fpath,"plot_data_v.txt")) as f2: self.voltData = f2.read() self.voltData = self.voltData.split("\n") #Initializing variable #'p' gives no. of lines of data for each node/branch # 'l' gives the no of partitions for a single voltage node #'vnumber' gives total number of voltage #'inumber' gives total number of current p = l = vnumber = inumber = 0 #print "VoltsData : ",self.voltData #Finding totla number of voltage node for i in self.voltData[3:]: #it has possible names of voltage nodes in NgSpice if "V(" in i or "x1" in i or "u3" in i: vnumber+=1 #print "Voltage Number :",vnumber #Reading Current Source Data with open (os.path.join(fpath,"plot_data_i.txt")) as f1: self.currentData = f1.read() self.currentData = self.currentData.split("\n") #print "CurrentData : ",self.currentData #Finding Number of Branch for i in self.currentData[3:]: if "#branch" in i: inumber+=1 #print "Current Number :",inumber self.dec = 0 #For AC if self.analysisInfo[0][-3:]==".ac": self.analysisType = 0 if "dec" in self.analysisInfo: self.dec = 1 for i in self.voltData[3:]: p+=1 #'p' gives no. of lines of data for each node/branch if "Index" in i: l+=1 # 'l' gives the no of partitions for a single voltage node #print "l:",l if "AC" in i: #DC for dc files and AC for ac ones break elif ".tran" in self.analysisInfo: self.analysisType = 1 for i in self.voltData[3:]: p+=1 if "Index" in i: l+=1 # 'l' gives the no of partitions for a single voltage node #print "l:",l if "Transient" in i: #DC for dc files and AC for ac ones break # For DC: else: self.analysisType = 2 for i in self.voltData[3:]: p+=1 if "Index" in i: l+=1 # 'l' gives the no of partitions for a single voltage node #print "l:",l if "DC" in i: #DC for dc files and AC for ac ones break #print "VoltNumber",vnumber #print "CurrentNumber",inumber vnumber = vnumber//l #vnumber gives the no of voltage nodes inumber = inumber//l #inumber gives the no of branches #print "VoltNumber",vnumber #print "CurrentNumber",inumber p=[p,vnumber,self.analysisType,self.dec,inumber] return p def openFile(self,fpath): #print "Calling Open File" try: with open (os.path.join(fpath,"plot_data_i.txt")) as f2: alli = f2.read() alli = alli.split("\n") self.NBIList = [] with open (os.path.join(fpath,"plot_data_v.txt")) as f1: allv = f1.read() except Exception as e: print "Exception Message : ",str(e) self.obj_appconfig.print_error('Exception Message :' + str(e)) self.msg = QtGui.QErrorMessage(None) self.msg.showMessage('Unable to open plot data files.') self.msg.setWindowTitle("Error Message:openFile") try: for l in alli[3].split(" "): if len(l)>0: self.NBIList.append(l) self.NBIList = self.NBIList[2:] len_NBIList = len(self.NBIList) #print "NBILIST : ",self.NBIList except Exception as e: print "Exception Message : ",str(e) self.obj_appconfig.print_error('Exception Message :' + str(e)) self.msg = QtGui.QErrorMessage(None) self.msg.showMessage('Error in Analysis File.') self.msg.setWindowTitle("Error Message:openFile") d = self.numberFinder(fpath) d1 = int(d[0] + 1) d2 = int(d[1]) d3 = d[2] d4 = d[4] dec = [d3,d[3]] #print "No. of Nodes:", d2 self.NBList = [] allv=allv.split("\n") for l in allv[3].split(" "): if len(l)>0: self.NBList.append(l) self.NBList=self.NBList[2:] len_NBList = len(self.NBList) #print "NBLIST",self.NBList ivals=[] inum = len(allv[5].split("\t")) inum_i = len(alli[5].split("\t")) full_data = [] # Creating list of data: if d3 < 3 : for i in range(1,d2): for l in allv[3+i*d1].split(" "): if len(l)>0: self.NBList.append(l) self.NBList.pop(len_NBList) self.NBList.pop(len_NBList) len_NBList = len(self.NBList) for n in range(1,d4): for l in alli[3+n*d1].split(" "): if len(l)>0: self.NBIList.append(l) self.NBIList.pop(len_NBIList) self.NBIList.pop(len_NBIList) len_NBIList = len(self.NBIList) p=0 k = 0 m=0 for i in alli[5:d1-1]: if len(i.split("\t"))==inum_i: j2=i.split("\t") #print j2 j2.pop(0) j2.pop(0) j2.pop() if d3 == 0: #not in trans j2.pop() #print j2 for l in range(1,d4): j3 = alli[5+l*d1+k].split("\t") j3.pop(0) j3.pop(0) if d3==0: j3.pop() #not required for dc j3.pop() j2 = j2 + j3 #print j2 full_data.append(j2) k+=1 #print "FULL DATA :",full_data for i in allv[5:d1-1]: if len(i.split("\t"))==inum: j=i.split("\t") j.pop() if d3==0: j.pop() for l in range(1,d2): j1 = allv[5+l*d1+p].split("\t") j1.pop(0) j1.pop(0) if d3==0: j1.pop() #not required for dc if self.NBList[len(self.NBList)-1] == 'v-sweep': self.NBList.pop() j1.pop() j1.pop() j = j + j1 j = j + full_data[m] #print j m+=1 #print j[:20] j = "\t".join(j[1:]) j = j.replace(",","") ivals.append(j) p+=1 self.data = ivals #print "volts:",self.butnames self.volts_length = len(self.NBList) self.NBList = self.NBList + self.NBIList print dec return dec def numVals(self): a = self.volts_length # No of voltage nodes b = len(self.data[0].split("\t")) #print "numvals:",b return [b,a] def computeAxes(self): nums = len(self.data[0].split("\t")) #print "i'm nums:",nums self.y=[] var=self.data[0].split("\t") for i in range(1,nums): self.y.append([Decimal(var[i])]) for i in self.data[1:]: temp=i.split("\t") for j in range(1,nums): self.y[j-1].append(Decimal(temp[j])) for i in self.data: temp=i.split("\t") self.x.append(Decimal(temp[0]))