From fd8107b2f5662851dd5d3a7388e46d6be1eb5125 Mon Sep 17 00:00:00 2001 From: nilshah98 Date: Fri, 7 Jun 2019 19:01:08 +0530 Subject: kicadtoNgspice documentation added --- src/kicadtoNgspice/Analysis.py | 99 ++++++++++++++++++++------------- src/kicadtoNgspice/Convert.py | 10 ++-- src/kicadtoNgspice/DeviceModel.py | 15 ++++- src/kicadtoNgspice/KicadtoNgspice.py | 103 ++++++++++++++++++++++++++--------- src/kicadtoNgspice/Model.py | 25 +++++---- src/kicadtoNgspice/Processing.py | 42 ++++++++++---- src/kicadtoNgspice/Source.py | 30 +++++----- src/kicadtoNgspice/SubcircuitTab.py | 23 +++++++- 8 files changed, 235 insertions(+), 112 deletions(-) (limited to 'src') diff --git a/src/kicadtoNgspice/Analysis.py b/src/kicadtoNgspice/Analysis.py index a60a2286..c5981f4d 100644 --- a/src/kicadtoNgspice/Analysis.py +++ b/src/kicadtoNgspice/Analysis.py @@ -36,6 +36,14 @@ class Analysis(QtGui.QWidget): self.createAnalysisWidget() def createAnalysisWidget(self): + """ + - Create the main anaylsis widget overwiew + - - Checkbox for analysis type + - - Respective analysis type group, AC, DC, TRAN... + - Check for `analysis` file, if any in projDir, extract data from it + - Else set the default checkbox to `TRAN` + - Accordingly set state for track widget options + """ self.grid = QtGui.QGridLayout() self.grid.addWidget(self.createCheckBox(), 0, 0) self.grid.addWidget(self.createACgroup(), 1, 0) @@ -100,13 +108,12 @@ class Analysis(QtGui.QWidget): self.setLayout(self.grid) self.show() - ''' - - Create the checkboxes for analysis type, under analysis tab - - checkbox > checkgrid > checkgroupbtn > checkAC | checkDC | checkTRAN - - Trigger enableBox on clicking - ''' - def createCheckBox(self): + """ + - Create the checkboxes for analysis type, under analysis tab + - checkbox > checkgrid > checkgroupbtn > checkAC | checkDC | checkTRAN + - Trigger enableBox on clicking + """ self.checkbox = QtGui.QGroupBox() self.checkbox.setTitle("Select Analysis Type") self.checkgrid = QtGui.QGridLayout() @@ -129,12 +136,11 @@ class Analysis(QtGui.QWidget): return self.checkbox - ''' - - Activate deactive analysis areas according to type - - Add analysis data to track_obj from TrackWidget - ''' - def enableBox(self): + """ + - Activate deactive analysis areas according to type + - Add analysis data to track_obj from TrackWidget + """ if self.checkAC.isChecked(): self.acbox.setDisabled(False) self.dcbox.setDisabled(True) @@ -153,15 +159,14 @@ class Analysis(QtGui.QWidget): self.dcbox.setDisabled(True) self.track_obj.set_CheckBox["ITEMS"] = "TRAN" - ''' - - Designing of AC group in analysis tab - - 3 radio buttons - Lin | Dec | Oct - - 3 input boxes, with top 2 combos\ - - If previous values exist then fill default values from - previous value json file - ''' - def createACgroup(self): + """ + - Designing of AC group in analysis tab + - 3 radio buttons - Lin | Dec | Oct + - 3 input boxes, with top 2 combos\ + - If previous values exist then fill default values from + previous value json file + """ kicadFile = self.clarg1 (projpath, filename) = os.path.split(kicadFile) project_name = os.path.basename(projpath) @@ -315,16 +320,25 @@ class Analysis(QtGui.QWidget): ''' def start_combovalue(self, text): + """ + - Handle start_fre_combo box event + - Check where it is Hz, MHz, etc. + - Accordingly set ac_parameter + """ self.ac_parameter[0] = str(text) def stop_combovalue(self, text): + """ + - Handle stop_fre_combo box event + - Check where it is Hz, MHz, etc. + - Accordingly set ac_parameter + """ self.ac_parameter[1] = str(text) - ''' - - Set track object for AC, according to the type of radio box selected - ''' - def set_ac_type(self): + """S + - Set track object for AC, according to the type of radio box selected + """ self.parameter_cnt = 0 if self.Lin.isChecked(): @@ -336,11 +350,17 @@ class Analysis(QtGui.QWidget): else: pass - ''' - - Create DC area under analysis tab - ''' - def createDCgroup(self): + """ + - Create DC area under analysis tab + - Source 1 and 2, each having 4 input boxes as follows + - - Source + - - Start + - - Increment + - - Stop + - The last 3 have combo box pertaining to their unit as well + - Also in the end a checkbox, for operating system point analysis + """ kicadFile = self.clarg1 (projpath, filename) = os.path.split(kicadFile) project_name = os.path.basename(projpath) @@ -612,10 +632,7 @@ class Analysis(QtGui.QWidget): return self.dcbox - ''' - - Below 6 functions to handle combo boxes for the DC group - ''' - + # Below 6 functions to handle combo boxes for the DC group def start_changecombo(self, text): self.dc_parameter[0] = str(text) @@ -634,21 +651,25 @@ class Analysis(QtGui.QWidget): def stop_changecombo2(self, text): self.dc_parameter[5] = str(text) - ''' - - Handles the Operating point analysis checkbox - ''' - def setflag(self): + """ + - Handles the Operating point analysis checkbox + """ if self.check.isChecked(): self.track_obj.op_check.append(1) else: self.track_obj.op_check.append(0) - ''' - - Creating transient group under analysis and creating it's components - ''' - def createTRANgroup(self): + """ + - Creating transient group under analysis and creating it's components + - Contains 3 inout and combo boxes for - + - - Start time + - - Step time + - - Stop time + - Input boxes for values, combo boxes for unit + - Accordingly also event handleres for combo boxes, creates 3 functions + """ kicadFile = self.clarg1 (projpath, filename) = os.path.split(kicadFile) project_name = os.path .basename(projpath) diff --git a/src/kicadtoNgspice/Convert.py b/src/kicadtoNgspice/Convert.py index 51daa1de..725a6909 100644 --- a/src/kicadtoNgspice/Convert.py +++ b/src/kicadtoNgspice/Convert.py @@ -8,7 +8,7 @@ from xml.etree import ElementTree as ET class Convert: """ - This class has all the necessary function required to convert + - This class has all the necessary function required to convert kicad netlist to ngspice netlist. """ @@ -22,7 +22,7 @@ class Convert: def addSourceParameter(self): """ - This function add the source details to schematicInfo + - This function add the source details to schematicInfo """ self.start = 0 @@ -205,6 +205,8 @@ class Convert: self.direct = self.clarg1 (filepath, filemname) = os.path.split(self.direct) self.Fileopen = os.path.join(filepath, "analysis") + print("======================================================") + print("FILEOPEN CONVERT ANALYS", self.Fileopen) self.writefile = open(self.Fileopen, "w") if self.variable == 'AC': self.no = 0 @@ -441,8 +443,8 @@ class Convert: default = 0 # Cheking if value is iterable.its for vector if ( - hasattr(value, '__iter__') - and type(value) is not str + hasattr(value, '__iter__') and + type(value) is not str ): addmodelLine += param + "=[" for lineVar in value: diff --git a/src/kicadtoNgspice/DeviceModel.py b/src/kicadtoNgspice/DeviceModel.py index 909756b5..30ad6985 100644 --- a/src/kicadtoNgspice/DeviceModel.py +++ b/src/kicadtoNgspice/DeviceModel.py @@ -7,9 +7,18 @@ from . import TrackWidget class DeviceModel(QtGui.QWidget): """ - This class creates Device Library Tab in KicadtoNgspice Window - It dynamically creates the widget for device like diode,mosfet, - transistor and jfet. + - This class creates Device Library Tab in KicadtoNgspice Window + It dynamically creates the widget for device like diode,mosfet, + transistor and jfet. + - Same function as the subCircuit file, except for + this takes different parameters in the if block + - - q TRANSISTOR + - - d DIODE + - - j JFET + - - m MOSFET + - Other 2 functions same as the ones in subCircuit + - - trackLibrary + - - trackLibraryWithoutButton """ def __init__(self, schematicInfo, clarg1): diff --git a/src/kicadtoNgspice/KicadtoNgspice.py b/src/kicadtoNgspice/KicadtoNgspice.py index 833bd6cc..9624fc82 100644 --- a/src/kicadtoNgspice/KicadtoNgspice.py +++ b/src/kicadtoNgspice/KicadtoNgspice.py @@ -41,7 +41,6 @@ class MainWindow(QtGui.QWidget): - clarg1 is the path to the .cir file - clarg2 is either None or "sub" depending on the analysis type """ - def __init__(self, clarg1, clarg2=None): QtGui.QWidget.__init__(self) print("==================================") @@ -115,10 +114,10 @@ class MainWindow(QtGui.QWidget): print("Model available in the Schematic :", modelList) """ - Checking if any unknown model is used in schematic which is not - recognized by NgSpice. - Also if the two model of same name is present under - modelParamXML directory + - Checking if any unknown model is used in schematic which is not + recognized by NgSpice. + - Also if the two model of same name is present under + modelParamXML directory """ if unknownModelList: print("Unknown Model List is : ", unknownModelList) @@ -139,11 +138,13 @@ class MainWindow(QtGui.QWidget): else: self.createMainWindow() - """ - This function create main window of Kicad to Ngspice converter - """ - def createMainWindow(self): + """ + - This function create main window of Kicad to Ngspice converter + - Two components + - - createcreateConvertWidget + - - Convert button => callConvert + """ self.vbox = QtGui.QVBoxLayout(self) self.hbox = QtGui.QHBoxLayout(self) self.hbox.addStretch(1) @@ -158,6 +159,26 @@ class MainWindow(QtGui.QWidget): self.show() def createcreateConvertWidget(self): + """ + - Contains the tabs for various convertor elements + - - Analysis => obj_analysis + => Analysis.Analysis(`path_to_projFile`) + + - - Source Details => obj_source + => Source.Source(`sourcelist`,`sourcelisttrack`,`path_to_projFile`) + + - - NgSpice Model => obj_model + => Model.Model(`schematicInfo`,`modelList`,`path_to_projFile`) + + - - Device Modelling => obj_devicemodel + => DeviceModel.DeviceModel(`schematicInfo`,`path_to_projFile`) + + - - Subcircuits => obj_subcircuitTab + => SubcircuitTab.SubcircuitTab(`schematicInfo`,`path_to_projFile`) + + - Finally pass each of these objects, to widgets + - convertWindow > mainLayout > tabWidgets > AnalysisTab, SourceTab .... + """ global obj_analysis self.convertWindow = QtGui.QWidget() self.analysisTab = QtGui.QScrollArea() @@ -206,7 +227,11 @@ class MainWindow(QtGui.QWidget): def callConvert(self): """ - Calling Convert Class Constructor + - This function called when convert button clicked + - Extracting data from the objs created above + - Pushing this data to json, and dumping it finally + - Written to a ..._Previous_Valuse.json file in the projDirectory + - Finally, call createNetListFile, with the converted schematic """ global schematicInfo global analysisoutput @@ -215,18 +240,18 @@ class MainWindow(QtGui.QWidget): (projpath, filename) = os.path.split(self.kicadFile) project_name = os.path.basename(projpath) + # Opening previous value file pertaining to the selected project fw = open( os.path.join( projpath, project_name + "_Previous_Values.json"), 'w') - json_data = {} - """ - Writing Analysis values - """ + # Creating a dictionary to map the json data + json_data = {} + # Writing analysis values json_data["analysis"] = {} json_data["analysis"]["ac"] = {} @@ -313,10 +338,7 @@ class MainWindow(QtGui.QWidget): obj_analysis.tran_parameter[2] ) - """ - Writing Source values - """ - + # Writing source values json_data["source"] = {} count = 1 @@ -442,9 +464,7 @@ class MainWindow(QtGui.QWidget): else: pass - """ - Writing Model values - """ + # Writing Model values i = 0 json_data["model"] = {} @@ -480,9 +500,7 @@ class MainWindow(QtGui.QWidget): json_data["model"][line[3]]["values"].append(fields) i = i + 1 - """ - Writing Device Model values - """ + # Writing Device Model values json_data["deviceModel"] = {} @@ -496,9 +514,7 @@ class MainWindow(QtGui.QWidget): str(obj_devicemodel.entry_var[it].text())) it = it + 1 - """ - Writing Subcircuit values - """ + # Writing Subcircuit values json_data["subcircuit"] = {} for subckt in obj_subcircuitTab.subcircuit_dict_beg: @@ -511,9 +527,20 @@ class MainWindow(QtGui.QWidget): str(obj_subcircuitTab.entry_var[it].text())) it = it + 1 + # json dumped and written to previous value file for the project write_data = json.dumps(json_data) fw.write(write_data) + # Create Convert object with the source details & the schematic details + print("=============================================================") + print("SOURCE LIST TRACK") + print(self.obj_track.sourcelisttrack["ITEMS"]) + print("SOURCE ENTRY VAR") + print(self.obj_track.source_entry_var["ITEMS"]) + print("SCHEMATIC INFO") + print(store_schematicInfo) + print("=============================================================") + self.obj_convert = Convert.Convert( self.obj_track.sourcelisttrack["ITEMS"], self.obj_track.source_entry_var["ITEMS"], @@ -561,6 +588,10 @@ class MainWindow(QtGui.QWidget): print("Analysis OutPut ", analysisoutput) # Calling netlist file generation function + print("=========================================================") + print("STORE SCHEMATIC INFO") + print(store_schematicInfo) + print("=========================================================") self.createNetlistFile(store_schematicInfo, plotText) self.msg = "The Kicad to Ngspice Conversion completed\ @@ -576,10 +607,24 @@ class MainWindow(QtGui.QWidget): # Generate .sub file from .cir.out file if it is a subcircuit subPath = os.path.splitext(self.kicadFile)[0] + # If sub argument passed, create subCircuit file as well if self.clarg2 == "sub": self.createSubFile(subPath) def createNetlistFile(self, store_schematicInfo, plotText): + """ + - Creating .cir.out file + - If analysis file present uses that and extract + - - Simulator + - - Initial + - - Analysis + - Finally add the following components to .cir.out file + - - SimulatorOption + - - InitialCondOption + - - Store_SchematicInfo + - - AnalysisOption + - In the end add control statements and allv, alli, end statements + """ print("=============================================================") print("Creating Final netlist") # print "INFOLINE",infoline @@ -686,6 +731,10 @@ class MainWindow(QtGui.QWidget): out.close() def createSubFile(self, subPath): + """ + - To create subcircuit file + - Extract data from .cir.out file + """ self.project = subPath self.projName = os.path.basename(self.project) if os.path.exists(self.project + ".cir.out"): diff --git a/src/kicadtoNgspice/Model.py b/src/kicadtoNgspice/Model.py index 9af7cbfb..dc94d9de 100644 --- a/src/kicadtoNgspice/Model.py +++ b/src/kicadtoNgspice/Model.py @@ -79,11 +79,14 @@ class Model(QtGui.QWidget): for mod in json_data["model"]: if json_data["model"][mod]["type"] ==\ line[2] and mod == line[3]: - self.obj_trac.model_entry_var - [self.nextcount].setText( - str(list( - json_data["model"][mod]["values"] - [i].values())[0])) + ( + self.obj_trac.model_entry_var + [self.nextcount].setText( + str(list( + json_data + ["model"][mod]["values"] + [i].values())[0])) + ) i = i + 1 except BaseException: pass @@ -108,11 +111,13 @@ class Model(QtGui.QWidget): for mod in json_data["model"]: if json_data["model"][mod]["type"] ==\ line[2] and mod == line[3]: - self.obj_trac.model_entry_var - [self.nextcount].setText( - str(list(json_data - ["model"][mod]["values"] - [i].values())[0])) + ( + self.obj_trac.model_entry_var + [self.nextcount].setText( + str(list(json_data + ["model"][mod]["values"] + [i].values())[0])) + ) i = i + 1 except BaseException: pass diff --git a/src/kicadtoNgspice/Processing.py b/src/kicadtoNgspice/Processing.py index bd1b45dc..ebbd3429 100644 --- a/src/kicadtoNgspice/Processing.py +++ b/src/kicadtoNgspice/Processing.py @@ -5,8 +5,8 @@ from xml.etree import ElementTree as ET class PrcocessNetlist: """ - This class include all the function required for pre-proccessing of netlist - before converting to Ngspice Netlist. + - This class include all the function required for pre-proccessing of + netlist before converting to Ngspice Netlist. """ modelxmlDIR = '../modelParamXML' @@ -16,7 +16,6 @@ class PrcocessNetlist: """ - Read the circuit file and return splitted lines """ - def readNetlist(self, filename): f = open(filename) data = f.read() @@ -32,7 +31,6 @@ class PrcocessNetlist: - Read Parameter information and store it into dictionary - kicadNetlis is the .cir file content """ - def readParamInfo(self, kicadNetlis): param = {} print("=========================KICADNETLIST========================") @@ -55,8 +53,8 @@ class PrcocessNetlist: """ - Preprocess netlist (replace parameters) + - Separate infoline (first line) from the rest of netlist """ - def preprocessNetlist(self, kicadNetlis, param): netlist = [] for eachline in kicadNetlis: @@ -97,6 +95,13 @@ class PrcocessNetlist: return netlist, infoline def separateNetlistInfo(self, netlist): + """ + - Remove the options such as .end, .param, starting wtih "." + from the netlist file + - This is stored as option info, whereas rest is stored as + schematicInfo + - Rest from the `* Sheet Name:` line stored as schematicInfo + """ optionInfo = [] schematicInfo = [] for eachline in netlist: @@ -116,9 +121,10 @@ class PrcocessNetlist: """ - Insert Special source parameter - - As per the parameters passed create source list + - As per the parameters passed create source list, start with v or i + - Then check for type whether ac, dc, sine, etc... + - Handle starting with h and f as well """ - def insertSpecialSourceParam(self, schematicInfo, sourcelist): schematicInfo1 = [] print("=============================================================") @@ -219,6 +225,16 @@ class PrcocessNetlist: def convertICintoBasicBlocks( self, schematicInfo, outputOption, modelList, plotText): + """ + - Parses the schematicInfo and returns + - - SchematicInfo + - - Output Option + - - Model List + - - Unkown Model List + - - Multiple Model List + - - Plot text + - Parsing info is provided below + """ print("=============================================================") print("Reading Schematic info for Model") # Insert details of Ngspice model @@ -425,8 +441,8 @@ class PrcocessNetlist: words = compline.split() # Adding zero voltage source to netlist schematicInfo.append( - "v_" + words[0] + " " - + words[1] + " " + words[2] + " " + "0") + "v_" + words[0] + " " + + words[1] + " " + words[2] + " " + "0") plotText.append("plot i(v_" + words[0] + ")") elif compType == 'plot_log': words = compline.split() @@ -442,9 +458,11 @@ class PrcocessNetlist: schematicInfo.insert(index, "* " + compline) # For Primary Couple - modelLine = "a" + str(k) - + " (" + words[1] + " " + words[2] + ") (interNode_" + str( - interMediateNodeCount) + " " + words[3] + ") " + modelLine = ( + "a" + str(k) + " (" + words[1] + " " + + words[2] + ") (interNode_" + + str(interMediateNodeCount) + " " + words[3] + ") " + ) modelLine += compName + "_primary" schematicInfo.append(modelLine) k = k + 1 diff --git a/src/kicadtoNgspice/Source.py b/src/kicadtoNgspice/Source.py index d8e39af4..c9d50a26 100644 --- a/src/kicadtoNgspice/Source.py +++ b/src/kicadtoNgspice/Source.py @@ -25,22 +25,24 @@ class Source(QtGui.QWidget): # Creating Source Widget self.createSourceWidget(sourcelist, sourcelisttrack) - """ - - This function dynamically create source widget in the - Source tab of KicadtoNgSpice window - - Depending on the type of source, ac, dc, sine, pwl, etc... - source tab is created - - All the entry fields, are kept into the entry_var - tracked by self.count - - Finally after each of the sourcelist is mapped to its input component - we move to adding these to the track widget - - Also check if any default values present from previous analysis and add - them by default - """ - def createSourceWidget(self, sourcelist, sourcelisttrack): + """ + - This function dynamically create source widget in the + Source tab of KicadtoNgSpice window + - Depending on the type of source, ac, dc, sine, pwl, etc... + source tab is created + - All the entry fields, are kept into the entry_var + tracked by self.count + - Finally after each of the sourcelist is mapped to its input component + we move to adding these to the track widget + - Also check if any default values present from previous analysis & add + them by default + - Each line in sourcelist corresponds to a source + - According to the source type modify the source and add it to the tab + """ print("============================================================") - print("SOURCELISTTRACK", sourcelisttrack) + print("SOURCE LIST TRACK", sourcelisttrack) + print("SOURCE LIST", sourcelist) print("============================================================") kicadFile = self.clarg1 (projpath, filename) = os.path.split(kicadFile) diff --git a/src/kicadtoNgspice/SubcircuitTab.py b/src/kicadtoNgspice/SubcircuitTab.py index b9c6402b..da6e5c57 100644 --- a/src/kicadtoNgspice/SubcircuitTab.py +++ b/src/kicadtoNgspice/SubcircuitTab.py @@ -8,8 +8,14 @@ import os class SubcircuitTab(QtGui.QWidget): """ - This class creates Subcircuit Tab in KicadtoNgspice Window - It dynamically creates the widget for subcircuits. + - This class creates Subcircuit Tab in KicadtoNgspice Window + - It dynamically creates the widget for subcircuits, + according to the .cir file + - Creates `lineEdit` and `Add` button, which triggers `fileSelector` + - Also, checks `Previous_value.json` for previous subcircuit value + to autofill, the `lineEdit` + - Add button is bind to `trackSubcircuit` + - Also `trackSubcircuit` without button is triggered if `lineEdit` filled """ def __init__(self, schematicInfo, clarg1): @@ -124,7 +130,13 @@ class SubcircuitTab(QtGui.QWidget): def trackSubcircuit(self): """ - This function is use to keep track of all Subcircuit widget + - This function is use to keep track of all Subcircuit widget + - Here the number of ports is tracked using the numPorts + and `Add` button objectName property, which is refered using `sender` + - Once a file is selected using the `QFileDialog` validate it + - Pass the path of subciruit and the number of ports + - According to validation state take further steps + - If validated correctly, add to TrackWidget """ sending_btn = self.sender() # print "Object Called is ",sending_btn.objectName() @@ -160,6 +172,11 @@ class SubcircuitTab(QtGui.QWidget): self.msg.show() def trackSubcircuitWithoutButton(self, iter_value, path_value): + """ + - Same as trackSubcircuit, but here the count value is passed directly + without using any button as in `Add` + - This is triggered only once, initally + """ self.widgetObjCount = iter_value -- cgit