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 PyQt5 import QtGui, QtCore, QtWidgets
from decimal import Decimal, getcontext
from matplotlib.backends.backend_qt4agg\
import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg\
import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from configuration.Appconfig import Appconfig
import numpy as np
# This class creates Python Plotting window
class plotWindow(QtWidgets.QMainWindow):
"""
This class defines python plotting window, its features, buttons,
colors, AC and DC analysis, plotting etc.
"""
def __init__(self, fpath, projectName):
"""This create constructor for plotWindow class."""
QtWidgets.QMainWindow.__init__(self)
self.fpath = fpath
self.projectName = projectName
self.obj_appconfig = Appconfig()
print("Complete Project 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 = QtWidgets.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 = QtWidgets.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 = QtWidgets.QVBoxLayout()
self.right_grid = QtWidgets.QGridLayout()
self.top_grid = QtWidgets.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 :
# ,(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.full_colors = ['r', 'b', 'g', 'y', 'c', 'm', 'k']
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 = QtWidgets.QLabel()
self.top_grid.addWidget(self.analysisType, 0, 0)
self.listNode = QtWidgets.QLabel()
self.top_grid.addWidget(self.listNode, 1, 0)
self.listBranch = QtWidgets.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(QtWidgets.QCheckBox(self.obj_dataext.NBList[i]))
self.chkbox[i].setStyleSheet('color')
self.chkbox[i].setToolTip('Check To Plot')
self.top_grid.addWidget(self.chkbox[i], i + 2, 0)
self.colorLab = QtWidgets.QLabel()
self.colorLab.setText('____')
self.colorLab.setStyleSheet(
self.colorName(
self.color[i]) +
'; font-weight = bold;')
self.top_grid.addWidget(self.colorLab, i + 2, 1)
for i in range(self.a[1], self.a[0] - 1): # a[0]-1
self.chkbox.append(QtWidgets.QCheckBox(self.obj_dataext.NBList[i]))
self.chkbox[i].setToolTip('Check To Plot')
self.top_grid.addWidget(self.chkbox[i], i + 3, 0)
self.colorLab = QtWidgets.QLabel()
self.colorLab.setText('____')
self.colorLab.setStyleSheet(
self.colorName(
self.color[i]) +
'; font-weight = bold;')
self.top_grid.addWidget(self.colorLab, i + 3, 1)
# Buttons for Plot, multimeter, plotting function.
self.clear = QtWidgets.QPushButton("Clear")
self.warnning = QtWidgets.QLabel()
self.funcName = QtWidgets.QLabel()
self.funcExample = QtWidgets.QLabel()
self.plotbtn = QtWidgets.QPushButton("Plot")
self.plotbtn.setToolTip('Press to Plot')
self.multimeterbtn = QtWidgets.QPushButton("Multimeter")
self.multimeterbtn.setToolTip(
'RMS value of the current and voltage is displayed')
self.text = QtWidgets.QLineEdit()
self.funcLabel = QtWidgets.QLabel()
self.palette1 = QtGui.QPalette()
self.palette2 = QtGui.QPalette()
self.plotfuncbtn = QtWidgets.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)
# Widgets for grid, plot button and multimeter button.
self.right_vbox.addLayout(self.top_grid)
self.right_vbox.addWidget(self.plotbtn)
self.right_vbox.addWidget(self.multimeterbtn)
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 = QtWidgets.QHBoxLayout()
self.hbox.addLayout(self.left_vbox)
self.hbox.addLayout(self.right_vbox)
self.widget = QtWidgets.QWidget()
self.widget.setLayout(self.hbox) # finalvbox
self.scrollArea = QtWidgets.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.widget)
'''
Right side box containing checkbox for different inputs and
options of plot, multimeter and plot function.
'''
self.finalhbox = QtWidgets.QHBoxLayout()
self.finalhbox.addWidget(self.scrollArea)
# Right side window frame showing list of nodes and branches.
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(
"Standard functions\
Addition:
Subtraction:
\
Multiplication:
Division:
Comparison:"
)
self.funcExample.setText(
"\n\nNode1 + Node2\nNode1 - Node2\nNode1 * Node2\nNode1 / Node2\
\nNode1 vs Node2")
# Connecting to plot and clear function
self.clear.clicked.connect(self.pushedClear)
self.plotfuncbtn.clicked.connect(self.pushedPlotFunc)
self.multimeterbtn.clicked.connect(self.multiMeter)
# for AC analysis
if self.plotType[0] == 0:
self.analysisType.setText("AC Analysis")
if self.plotType[1] == 1:
self.plotbtn.clicked.connect(self.onPush_decade)
else:
self.plotbtn.clicked.connect(self.onPush_ac)
# for transient analysis
elif self.plotType[0] == 1:
self.analysisType.setText("Transient Analysis")
self.plotbtn.clicked.connect(self.onPush_trans)
else:
# For DC analysis
self.analysisType.setText("DC Analysis")
self.plotbtn.clicked.connect(self.onPush_dc)
self.setCentralWidget(self.mainFrame)
# definition of functions pushedClear, pushedPlotFunc.
def pushedClear(self):
self.text.clear()
self.axes.cla()
self.canvas.draw()
def pushedPlotFunc(self):
self.parts = str(self.text.text())
self.parts = self.parts.split(" ")
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!")
QtWidgets.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)):
if i % 2 == 0:
for j in range(len(self.obj_dataext.NBList)):
if self.parts[i] == self.obj_dataext.NBList[j]:
a.append(j)
if len(a) != len(self.parts) // 2 + 1:
QtWidgets.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):
QtWidgets.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!!")
QtWidgets.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:
QtWidgets.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:
QtWidgets.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 = []
# definition of functions onPush_decade, onPush_ac, onPush_trans,\
# onPush_dc, color and multimeter and getRMSValue.
def onPush_decade(self):
boxCheck = 0
self.axes.cla()
for i, j in zip(self.chkbox, list(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:
QtWidgets.QMessageBox.about(
self, "Warning!!", "Please select at least one Node OR Branch")
self.canvas.draw()
def onPush_ac(self):
self.axes.cla()
boxCheck = 0
for i, j in zip(self.chkbox, list(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:
QtWidgets.QMessageBox.about(
self, "Warning!!", "Please select at least one Node OR Branch")
self.canvas.draw()
def onPush_trans(self):
self.axes.cla()
boxCheck = 0
for i, j in zip(self.chkbox, list(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:
QtWidgets.QMessageBox.about(
self, "Warning!!", "Please select at least one Node OR Branch")
self.canvas.draw()
def onPush_dc(self):
boxCheck = 0
self.axes.cla()
for i, j in zip(self.chkbox, list(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:
QtWidgets.QMessageBox.about(
self, "Warning!!", "Please select atleast one Node OR Branch")
self.canvas.draw()
def colorName(self, letter):
return {
'r': 'color:red',
'b': 'color:blue',
'g': 'color:green',
'y': 'color:yellow',
'c': 'color:cyan',
'm': 'color:magenta',
'k': 'color:black'
}[letter]
def multiMeter(self):
print("Function : MultiMeter")
self.obj = {}
boxCheck = 0
loc_x = 300
loc_y = 300
for i, j in zip(self.chkbox, list(range(len(self.chkbox)))):
if i.isChecked():
print("Check box", self.obj_dataext.NBList[j])
boxCheck += 1
if self.obj_dataext.NBList[j] in self.obj_dataext.NBIList:
voltFlag = False
else:
voltFlag = True
# Initializing Multimeter
self.obj[j] = MultimeterWidgetClass(
self.obj_dataext.NBList[j], self.getRMSValue(
self.obj_dataext.y[j]), loc_x, loc_y, voltFlag)
loc_x += 50
loc_y += 50
# Adding object of multimeter to dictionary
(
self.obj_appconfig.
dock_dict[
self.obj_appconfig.current_project['ProjectName']].
append(self.obj[j])
)
if boxCheck == 0:
QtWidgets.QMessageBox.about(
self, "Warning!!", "Please select at least one Node OR Branch")
def getRMSValue(self, dataPoints):
getcontext().prec = 5
return np.sqrt(np.mean(np.square(dataPoints)))
class MultimeterWidgetClass(QtWidgets.QWidget):
def __init__(self, node_branch, rmsValue, loc_x, loc_y, voltFlag):
QtWidgets.QWidget.__init__(self)
self.multimeter = QtWidgets.QWidget(self)
if voltFlag:
self.node_branchLabel = QtWidgets.QLabel("Node")
self.rmsValue = QtWidgets.QLabel(str(rmsValue) + " Volts")
else:
self.node_branchLabel = QtWidgets.QLabel("Branch")
self.rmsValue = QtWidgets.QLabel(str(rmsValue) + " Amp")
self.rmsLabel = QtWidgets.QLabel("RMS Value")
self.nodeBranchValue = QtWidgets.QLabel(str(node_branch))
self.layout = QtWidgets.QGridLayout(self)
self.layout.addWidget(self.node_branchLabel, 0, 0)
self.layout.addWidget(self.rmsLabel, 0, 1)
self.layout.addWidget(self.nodeBranchValue, 1, 0)
self.layout.addWidget(self.rmsValue, 1, 1)
self.multimeter.setLayout(self.layout)
self.setGeometry(loc_x, loc_y, 200, 100)
self.setGeometry(loc_x, loc_y, 300, 100)
self.setWindowTitle("MultiMeter")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.show()
class DataExtraction:
def __init__(self):
self.obj_appconfig = Appconfig()
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
# 'npv' gives the no of partitions for a single voltage node
# 'vnumber' gives total number of voltage
# 'inumber' gives total number of current
p = npv = vnumber = inumber = 0
# Finding totla number of voltage node
for i in self.voltData[3:]:
# it has possible names of voltage nodes in NgSpice
if "Index" in i: # "V(" in i or "x1" in i or "u3" in i:
vnumber += 1
# 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")
# Finding Number of Branch
for i in self.currentData[3:]:
if "#branch" in i:
inumber += 1
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:
npv += 1
# 'npv' gives the no of partitions for a single voltage node
# print("npv:", npv)
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:
npv += 1
# 'npv' gives the no of partitions for a single voltage node
# print("npv:", npv)
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:
npv += 1
# 'npv' gives the no of partitions for a single voltage node
# print("npv:", npv)
if "DC" in i: # DC for dc files and AC for ac ones
break
vnumber = vnumber // npv # vnumber gives the no of voltage nodes
inumber = inumber // npv # inumber gives the no of branches
p = [p, vnumber, self.analysisType, self.dec, inumber]
return p
def openFile(self, fpath):
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 = QtWidgets.QErrorMessage()
self.msg.setModal(True)
self.msg.setWindowTitle("Error Message")
self.msg.showMessage('Unable to open plot data files.')
self.msg.exec_()
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)
except Exception as e:
print("Exception Message : ", str(e))
self.obj_appconfig.print_error('Exception Message :' + str(e))
self.msg = QtWidgets.QErrorMessage()
self.msg.setModal(True)
self.msg.setWindowTitle("Error Message")
self.msg.showMessage('Unable to read Analysis File.')
self.msg.exec_()
d = self.numberFinder(fpath)
d1 = int(d[0] + 1)
d2 = int(d[1])
d3 = d[2]
d4 = d[4]
dec = [d3, d[3]]
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")
j2.pop(0)
j2.pop(0)
j2.pop()
if d3 == 0: # not in trans
j2.pop()
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
full_data.append(j2)
k += 1
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]
m += 1
j = "\t".join(j[1:])
j = j.replace(",", "")
ivals.append(j)
p += 1
self.data = ivals
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"))
return [b, a]
def computeAxes(self):
nums = len(self.data[0].split("\t"))
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]))