def save_setting(self): """ This function saves the user setting to an INI file. Parameter ---------- self Return ------- None Example -------- .. code:: python self.save_setting() """ print(gsyIO.date_time_now() + 'Saving settings...') # form INI file content str_setting = '[User settings]\n' str_setting += 'ledt_inkscape_dir=' + self.ledt_inkscape_dir.text() + '\n' str_setting += 'ledt_svg_dir=' + self.ledt_svg_dir.text() + '\n' str_setting += 'ledt_emf_dir=' + self.ledt_emf_dir.text() + '\n' str_setting += 'checkBox=' + str(self.checkBox.isChecked()) # form INI file path str_ini_file_path = os.path.join(os.getcwd(), CONST_INI_FILENAME) # save INI file gsyINI.write_ini(str_ini_file_path, str_setting)
def read_setting(self): """ This function reads the user setting from an INI file and then assigns them to the objects. Parameter ---------- self Return ------- None Example -------- .. code:: python self.read_setting() """ # get INI file path str_ini_file_path = os.path.join(os.getcwd(), CONST_INI_FILENAME) # read INI file bool_ini_exist, str_setting = gsyINI.read_ini(str_ini_file_path) # if INI file not found, return False if bool_ini_exist == False: print(gsyIO.date_time_now() + 'Read user setting failed.') return False else: pass try: # get rid of the line breaks str_setting = [item.strip('\n') for item in str_setting] str_setting = [item.strip('\r') for item in str_setting] # list for QLineEdit list_widget = [self.ledt_inkscape_dir, self.ledt_svg_dir, self.ledt_emf_dir] # assign values for item in str_setting: # keep the left of "=" index = item.find('=') str_temp_setting = item[:index] # assign the checkbox if str_temp_setting == 'checkBox': str_temp = item[(index + 1):] if str_temp == 'True': self.checkBox.setChecked(True) else: self.checkBox.setChecked(False) # assign the QLineEdit for j in list_widget: if str_temp_setting == j.objectName(): j.setText(item[(index + 1):]) # if found, remove from list list_widget.pop(list_widget.index(j)) break else: pass print(gsyIO.date_time_now() + 'Read user setting complete') return True except: print(gsyIO.date_time_now() + 'Read user setting failed.') return False
def save_data(self): ''' Save the generated data in CSV. ''' print(gsyIO.date_time_now() + 'Updating data before save') self.print_info('Saving data as CSV...') bool_temp = self.update_data() if bool_temp == False: root = tk.Tk() root.withdraw() msgbox.showerror( 'Error', 'Error when making phase data. Time cannot be zero.') root.destroy() return False header = [ 'time', 'Phase-A Mag', 'Phase-A Omega', 'Phase-A Phi', 'Phase-A DC', 'Phase-A Real', 'Phase-A Imag', 'Phase-A Radius', 'Phase-A Angle', 'Phase-B Mag', 'Phase-B Omega', 'Phase-B Phi', 'Phase-B DC', 'Phase-B Real', 'Phase-B Imag', 'Phase-B Radius', 'Phase-B Angle', 'Phase-C Mag', 'Phase-C Omega', 'Phase-C Phi', 'Phase-C DC', 'Phase-C Real', 'Phase-C Imag', 'Phase-C Radius', 'Phase-C Angle', 'Phase-A + Real', 'Phase-A + Imag', 'Phase-A + Radius', 'Phase-A + Angle', 'Phase-B + Real', 'Phase-B + Imag', 'Phase-B + Radius', 'Phase-B + Angle', 'Phase-C + Real', 'Phase-C + Imag', 'Phase-C + Radius', 'Phase-C + Angle', 'Phase-A - Real', 'Phase-A - Imag', 'Phase-A - Radius', 'Phase-A - Angle', 'Phase-B - Real', 'Phase-B - Imag', 'Phase-B - Radius', 'Phase-B - Angle', 'Phase-C - Real', 'Phase-C - Imag', 'Phase-C - Radius', 'Phase-C - Angle', 'Zero Real', 'Zero Imag', 'Zero Radius', 'Zero Angle', 'Alpha Real', 'Alpha Imag', 'Alpha Radius', 'Alpha Angle', 'Beta Real', 'Beta Imag', 'Beta Radius', 'Beta Angle', 'Alpha + Real', 'Alpha + Image', 'Alpha + Radius', 'Alpha + Angle', 'Beta + Real', 'Beta + Image', 'Beta + Radius', 'Beta + Angle', 'Alpha - Real', 'Alpha - Imag', 'Alpha - Radius', 'Alpha - Angle', 'Beta - Real', 'Beta - Imag', 'Beta - Radius', 'Beta - Angle', 'd Real', 'd Imag', 'd Radius', 'd Angle', 'q Real', 'q Imag', 'q Radius', 'q Angle', 'd + Real', 'd + Imag', 'd + Radius', 'd + Angle', 'q + Real', 'q + Imag', 'q + Radius', 'q + Angle', 'd - Real', 'd - Imag', 'd - Radius', 'd - Angle', 'q - Real', 'q - Imag', 'q - Radius', 'q - Angle', 'PLL Omega', 'PLL Phi', 'PLL theta' ] # data length needs to be the same phase_a_mag = [self.phaseAMag] * len(self.time_samples) phase_a_omega = [self.phaseAOmega] * len(self.time_samples) phase_a_phi = [self.phaseAPhi] * len(self.time_samples) phase_a_dc = [self.phaseADC] * len(self.time_samples) phase_b_mag = [self.phaseBMag] * len(self.time_samples) phase_b_omega = [self.phaseBOmega] * len(self.time_samples) phase_b_phi = [self.phaseBPhi] * len(self.time_samples) phase_b_dc = [self.phaseBDC] * len(self.time_samples) phase_c_mag = [self.phaseCMag] * len(self.time_samples) phase_c_omega = [self.phaseCOmega] * len(self.time_samples) phase_c_phi = [self.phaseCPhi] * len(self.time_samples) phase_c_dc = [self.phaseCDC] * len(self.time_samples) pll_omega = [self.pllOmega] * len(self.time_samples) pll_phi = [self.pllPhi] * len(self.time_samples) data_sets = [ self.time_samples, phase_a_mag, phase_a_omega, phase_a_phi, phase_a_dc, self.phaseAdata.real, self.phaseAdata.imag, abs(self.phaseAdata), np.angle(self.phaseAdata), phase_b_mag, phase_b_omega, phase_b_phi, phase_b_dc, self.phaseBdata.real, self.phaseBdata.imag, abs(self.phaseBdata), np.angle(self.phaseBdata), phase_c_mag, phase_c_omega, phase_c_phi, phase_c_dc, self.phaseCdata.real, self.phaseCdata.imag, abs(self.phaseCdata), np.angle(self.phaseCdata), self.phaseA_pos.real, self.phaseA_pos.imag, abs(self.phaseA_pos), np.angle(self.phaseA_pos), self.phaseB_pos.real, self.phaseB_pos.imag, abs(self.phaseB_pos), np.angle(self.phaseB_pos), self.phaseC_pos.real, self.phaseC_pos.imag, abs(self.phaseC_pos), np.angle(self.phaseC_pos), self.phaseA_neg.real, self.phaseA_neg.imag, abs(self.phaseA_neg), np.angle(self.phaseA_neg), self.phaseB_neg.real, self.phaseB_neg.imag, abs(self.phaseB_neg), np.angle(self.phaseB_neg), self.phaseC_neg.real, self.phaseC_neg.imag, abs(self.phaseC_neg), np.angle(self.phaseC_neg), self.phaseZero.real, self.phaseZero.imag, abs(self.phaseZero), np.angle(self.phaseZero), self.alpha.real, self.alpha.imag, abs(self.alpha), np.angle(self.alpha), self.beta.real, self.beta.imag, abs(self.beta), np.angle(self.beta), self.alpha_pos.real, self.alpha_pos.imag, abs(self.alpha_pos), np.angle(self.alpha_pos), self.beta_pos.real, self.beta_pos.imag, abs(self.beta_pos), np.angle(self.beta_pos), self.alpha_neg.real, self.alpha_neg.imag, abs(self.alpha_neg), np.angle(self.alpha_neg), self.beta_neg.real, self.beta_neg.imag, abs(self.beta_neg), np.angle(self.beta_neg), self.d.real, self.d.imag, abs(self.d), np.angle(self.d), self.q.real, self.q.imag, abs(self.q), np.angle(self.q), self.d_pos.real, self.d_pos.imag, abs(self.d_pos), np.angle(self.d_pos), self.q_pos.real, self.q_pos.imag, abs(self.q_pos), np.angle(self.q_pos), self.d_neg.real, self.d_neg.imag, abs(self.d_neg), np.angle(self.d_neg), self.q_neg.real, self.q_neg.imag, abs(self.q_neg), np.angle(self.q_neg), pll_omega, pll_phi, self.thetaPLL ] gsyIO.save_csv_gui(header, data_sets) self.save_setting() self.print_info('Data saved as CSV') return True
def convert(self): """ This function converts the SVG files found to EMF files. The filenames of the SVG files would be kept. Overwirte files with the same filenames without notice. Conversion is achieved via Inkscape. The command is in the form of: .. code:: inkscape foo.svg --export-emf=bar.emf Parameter ---------- self Return ------- bool Returns True if conversion successful. Returns False if conversion unsuccessful or on exception. Example -------- .. code:: python self.btn_go.clicked.connect(self.convert) """ print(gsyIO.date_time_now() + 'Converting...') # progress bar control int_count = 0 dbl_progress = 0 self.progressBar.setValue(dbl_progress) # check if all folders exist bool_dir_exist = self.check_dir_exist() try: # if not all folders exist, prompt error message and return False if bool_dir_exist == False: gsyIO.prompt_msg(str_title='Folder not found', str_msg='At least one folder not found', str_type='err') print(gsyIO.date_time_now() + 'At least one folder not found') print(gsyIO.date_time_now() + 'Conversion failed') return False else: # first part of the shell command str_inkscape = '"' + self.str_inkscape_dir + os.sep + 'inkscape' + '"' # search for SVG files list_svg_file_path = self.search_svg() # if the list is empty if not list_svg_file_path: gsyIO.prompt_msg(str_title='SVG not found', str_msg='No SVG file found', str_type='err') print(gsyIO.date_time_now() + 'No SVG file found') print(gsyIO.date_time_now() + 'Conversion failed') return False else: # save user settings self.save_setting() # get the total number of SVG files in the list int_svg_file_count = len(list_svg_file_path) # For-Loop through the SVG files and convert to EMF for item in list_svg_file_path: str_svg_file_path = item # reverse find first path separator index = str_svg_file_path.rfind(os.sep) # get the filename (only) of the SVG file str_svg_filename = str_svg_file_path[(index + 1):] # find the "." of the SVG extension index = str_svg_filename.rfind('.') # replace the "svg" for "emf" str_emf_filename = str_svg_filename[:(index + 1)] + 'emf' # form the full path for the EMF file str_emf_file_path = os.path.join(self.str_emf_dir, str_emf_filename) # form the shell command str_cmd = (str_inkscape + ' ' + '"' + str_svg_file_path + '"' + ' ' + '"' + CONST_EXPT_EMF + str_emf_file_path + '"') # run the shell command, timeout is 10 minutes obj = subprocess.run(str_cmd, shell=True, timeout=600) # progress bar control int_count += 1 dbl_progress = float(int_count) / float(int_svg_file_count) * 100.0 str_info = ('Converting ' + str(int_count) + ' of ' + str(int_svg_file_count) + ', ' + '{:.2f}'.format(dbl_progress) + r'%') print(str_info) self.progressBar.setValue(dbl_progress) # open EMF folder on end if self.checkBox.isChecked() == True: self.open_emf_folder() else: pass print(gsyIO.date_time_now() + 'Conversion complete') return True except: print(gsyIO.date_time_now() + 'Conversion failed') return False
def update_data(self): ''' Update the user inputs. ''' print(gsyIO.date_time_now() + 'Updating') self.print_info('Updating data...') list_temp = [] # convert user inputs to numerics self.phaseAMag = self.to_numeric(self.ledt_phaseAMag.text()) self.phaseAOmega = self.to_numeric(self.ledt_phaseAOmega.text()) self.phaseAPhi = self.to_numeric(self.ledt_phaseAPhi.text()) self.phaseADC = self.to_numeric(self.ledt_phaseADC.text()) list_temp.append(['Phase-A Mag = ', self.phaseAMag]) list_temp.append(['Phase-A Omega = ', self.phaseAOmega]) list_temp.append(['Phase-A Phi = ', self.phaseAPhi]) list_temp.append(['Phase-A DC = ', self.phaseADC]) self.phaseBMag = self.to_numeric(self.ledt_phaseBMag.text()) self.phaseBOmega = self.to_numeric(self.ledt_phaseBOmega.text()) self.phaseBPhi = self.to_numeric(self.ledt_phaseBPhi.text()) self.phaseBDC = self.to_numeric(self.ledt_phaseBDC.text()) list_temp.append(['Phase-B Mag = ', self.phaseBMag]) list_temp.append(['Phase-B Omega = ', self.phaseBOmega]) list_temp.append(['Phase-B Phi = ', self.phaseBPhi]) list_temp.append(['Phase-B DC = ', self.phaseBDC]) self.phaseCMag = self.to_numeric(self.ledt_phaseCMag.text()) self.phaseCOmega = self.to_numeric(self.ledt_phaseCOmega.text()) self.phaseCPhi = self.to_numeric(self.ledt_phaseCPhi.text()) self.phaseCDC = self.to_numeric(self.ledt_phaseCDC.text()) list_temp.append(['Phase-C Mag = ', self.phaseCMag]) list_temp.append(['Phase-C Omega = ', self.phaseCOmega]) list_temp.append(['Phase-C Phi = ', self.phaseCPhi]) list_temp.append(['Phase-C DC = ', self.phaseCDC]) self.pllOmega = self.to_numeric(self.ledt_pllOmega.text()) self.pllPhi = self.to_numeric(self.ledt_pllPhi.text()) list_temp.append(['PLL Omega = ', self.pllOmega]) list_temp.append(['PLL Phi = ', self.pllPhi]) self.timeEnd = self.to_numeric(self.ledt_time.text()) self.timeEnd = abs(self.timeEnd) list_temp.append(['Time = ', self.timeEnd]) # print to console for item in list_temp: print(gsyIO.date_time_now() + str(item[0]) + str(item[1])) if self.timeEnd == 0: root = tk.Tk() root.withdraw() msgbox.showerror( 'Error', 'Error when making phase data. Time cannot be zero.') root.destroy() return False # make three-phase data self.phaseAdata, self.time_samples = self.make_phase( self.phaseAMag, self.phaseAOmega, self.phaseAPhi, self.phaseADC) self.phaseBdata, _ = self.make_phase(self.phaseBMag, self.phaseBOmega, self.phaseBPhi, self.phaseBDC) # print(self.phaseBdata) self.phaseCdata, _ = self.make_phase(self.phaseCMag, self.phaseCOmega, self.phaseCPhi, self.phaseCDC) # calculations for Fortescue, Clarke and Park # Fortescue (self.phaseA_pos, self.phaseB_pos, self.phaseC_pos, self.phaseA_neg, self.phaseB_neg, self.phaseC_neg, self.phaseZero) = trf.cal_symm(self.phaseAdata, self.phaseBdata, self.phaseCdata) # Clarke self.alpha, self.beta, _ = trf.cal_clarke(self.phaseAdata, self.phaseBdata, self.phaseCdata) # Clarke symm (self.alpha_pos, self.beta_pos, self.alpha_neg, self.beta_neg, _) = trf.cal_clarke_dsogi(self.phaseAdata, self.phaseBdata, self.phaseCdata) # Park self.thetaPLL = self.pllOmega * self.time_samples + self.pllPhi self.d, self.q, _ = trf.cal_park(self.thetaPLL, self.alpha, self.beta) # Park symm self.d_pos, self.q_pos, _ = trf.cal_park(self.thetaPLL, self.alpha_pos, self.beta_pos) self.d_neg, self.q_neg, _ = trf.cal_park(self.thetaPLL, self.alpha_neg, self.beta_neg) # axes limits self.xlim_max = self.timeEnd self.xlim_min = 0 # print('before limits') self.ylim_max = max(max(abs(self.phaseAdata)), max(abs(self.phaseBdata)), max(abs(self.phaseCdata)), max(abs(self.alpha)), max(abs(self.beta)), max(abs(self.d)), max(abs(self.q)), max(abs(self.phaseZero))) self.ylim_max *= 1.08 self.ylim_min = -1 * self.ylim_max self.print_info('Data updated') return True
def read_setting(self): # print('I am reading settings') self.print_info('Reading user settings...') str_cwd = os.getcwd() str_ini_file_path = os.path.join(str_cwd, CONST_INI_FILENAME) bool_ini_exist, str_setting = gsyINI.read_ini(str_ini_file_path) if bool_ini_exist == False: print(gsyIO.date_time_now() + 'Read user setting failed.') return False else: pass try: str_setting = [item.strip('\n') for item in str_setting] str_setting = [item.strip('\r') for item in str_setting] # print(str_setting) widget_count = self.gridLayout.count() # list for QLineEdit widgets ledt_list = [] for item in range(widget_count): temp_widget = self.gridLayout.itemAt(item).widget() if temp_widget.objectName().startswith('ledt'): ledt_list.append(temp_widget) # keep the left of the '=' for item in str_setting: index = item.find('=') str_temp_setting = item[:index] for j in ledt_list: if str_temp_setting == j.objectName(): j.setText(item[(index + 1):]) # if found, remove from list ledt_list.pop(ledt_list.index(j)) break else: pass print(gsyIO.date_time_now() + 'Read user setting complete') self.print_info('Read user settings complete') return True except: print(gsyIO.date_time_now() + 'Read user setting failed.') self.print_info('Read user setting failed') return False
def read_ini_to_tb(locStr_ini_file_path, locList_textbox): """ .. _read_ini_to_tb : Read a INI file and assign the corresponding elements to the matplotlib textboxes. This function would assign the INI element value (right of the "=" sign in the INI file) to the textbox if the label string of the textbox is the same as the INI element name (left of the "=" sign in the INI file). The input list for textbox would be copied by value into a new list object first to prevent modification of the original list. .. code:: python locTemp_textbox = list(locList_textbox) If the INI element is found, the corresponding textbox is removed from locTemp_textbox to make the search faster. Parameters ------------ locStr_ini_file_path : string The path for the INI file. locList_textbox : list (containing all the matplotlib textboxes) The list of textboxes to be filled. Returns ------- bool Returns True if deemed successful (no exception). Returns False if deemed unsuccessful (on exception). locConfig : list or int Each element in the list is a line of content read from the given INI file if read successful. Returns 0 when read fail. Examples -------- >>> read_ini_to_tb(r'C:\some.ini', list_textbox) 2017-11-23, 10:33:29:Reading INI file... 2017-11-23, 10:33:29:Read INI file complete 2017-11-23, 10:33:29:Setting config : InputHarmonicOrder=2 2017-11-23, 10:33:29:Setting config : InputPLLOrder=1 2017-11-23, 10:33:29:Setting config : Samples=300 2017-11-23, 10:33:29:Setting config : FPS=30 2017-11-23, 10:33:29:Setting config : BaseFreq=50 2017-11-23, 10:33:29:Setting config : FFmpegpath= """ try: # call function to read INI file bool_ini, locConfig = read_ini(locStr_ini_file_path) # if read INI fale, exit this function if bool_ini == False: return (False, locConfig) # get of the line break for each line locConfig = [item.strip('\n') for item in locConfig] locConfig = [item.strip('\r') for item in locConfig] # copy the values of the list, otherwise the original list object would be modified locTemp_textbox = list(locList_textbox) # double for-loop start for i in locConfig: locIndex = i.find('=') # keep the left of the '=' locStr_temp_config = i[:locIndex] for j in locTemp_textbox: # strip chars from the labels locStr_temp_label = (j.label.get_text().replace( ' ', '').replace('\n', '').replace('\r', '').replace(':', '')) if locStr_temp_config == locStr_temp_label: # get the right part of the '=' and assgin it to the text boxes j.set_val(i[(locIndex + 1):]) print(date_time_now() + 'Setting config : ' + i) # if found, remove from list locTemp_textbox.pop(locTemp_textbox.index(j)) break else: pass # double for-loop end return (True, locConfig) except: print(date_time_now() + 'INI file read failed') locConfig = 0 return (False, locConfig)
def read_ini(locStr_ini_file_path): """ .. _read_ini : This funciton reads the given INI file by line and return the read line as a list object. This does NOT manipulate the read contents. Parameters ---------- locStr_ini_file_path : str The INI file full path. Returns ------- bool Returns True if read successful (no exception). Returns False on exception. locConfig : list or int Returns the INI read by line contents if read successful. Returns 0 when read fail. Examples -------- >>> read_ini(r'C:\some.ini') 2017-11-23, 11:13:38:Reading INI file... 2017-11-23, 11:13:38:Read INI file complete (True, ['[User configurations]\\n', 'InputHarmonicOrder=1.7\\n', 'InputPLLOrder=1\\n', 'Samples=200\\n', 'FPS=30\\n', 'BaseFreq=50\\n', 'FFmpegpath=\\n']) """ print(date_time_now() + 'Reading INI file...') try: # open ini file locIni_file = open(locStr_ini_file_path, 'r') # read by lines locConfig = locIni_file.readlines() print(date_time_now() + 'Read INI file complete') return (True, locConfig) except: print(date_time_now() + 'Fail to read INI file.') locConfig = 0 return (False, locConfig)
def write_ini(locStr_ini_file_path, locStr_ini): """ .. _write_ini : Write the given string into the given INI file path. Parameters ---------- locStr_ini_file_path : str The file full path of the INI file. If the extension ".ini" is not included, it would be added to the path. locStr_ini : str The string to be written into the INI file. Returns ------- bool Returns True if deemed successful (no exception). Returns False if deemed unsuccessful (on exception). Examples -------- >>> write_ini('C:\\Temp\\testini', '[User configurations]\\nsome string') 2017-11-21, 16:24:40:INI file save start 2017-11-21, 16:24:40:INI file save complete Out[51]: True Content of the INI file would be: | '[User configurations] | some string' """ print(date_time_now() + 'INI file save start') try: # check whether the INI file path ends with '.ini' (case insensitive) if locStr_ini_file_path[-4:].lower() == '.ini': # if yes, pass pass else: # if no, append locStr_ini_file_path = locStr_ini_file_path + '.ini' # open the INI for write locIni_file = open(locStr_ini_file_path, 'w') # write the string into the INI locIni_file.write(locStr_ini) # close the INI file locIni_file.close() print(date_time_now() + 'INI file save complete') return True except: print(date_time_now() + 'INI file save failed') return False # ============================================================================= # </Function: write ini file> # =============================================================================