def graph_from_function(ax, function, xmin, xmax, discr, xlabel="", ylabel="", marker=".", linestyle="solid", linewidth=1.5): """ Plot mathematic function Parameters ---------- ax : Axis the matplotlib axis object function : str the mathematic function xmin : int the x min xmax : int the x max discr : int the discretization of the interval between xmin and xmax xlabel : str the name of the x label ylabel : str the name of the y label marker : string the style of the marker to plot linestyle : string the style of the line to plot linewidth : float the width of the line to plot """ logger.log(logging.INFO, "[Graph] Graph from function") plots = [PlotCreator.get_instance().plot_from_function(function, xmin, xmax, discr, xlabel, ylabel)] plot(ax, plots, marker, linestyle, linewidth)
def graph_compare_plot_values(ax, plot1, plot2, threshold, on_graph, round_value=2): """ Plot the diff values between two plots Parameters ---------- ax : Axis the matplotlib axis object plot1 : Plot the first plot to compare plot2 : Plot the second plot to compare threshold : float the threshold to print the difference value on_graph : boolean plot on graph or on the x axis round_value : int the number of decimal to use """ logger.log(logging.INFO, "[Graph] Display compare values") for ii in range(len(plot1.get_x())): value = abs(plot1.get_y()[ii] - plot2.get_y()[ii]) if value > threshold: y_pos = 0 if on_graph: y_pos = value else: if ii % 2 == 1: y_pos -= 0.40 ax.text(plot1.get_x()[ii] - 0.1, y_pos, round(value, round_value), size=8)
def graph_compare_plot_diff(ax, plot1, plot2, marker=".", linestyle="solid", linewidth=1.5): """ Plot the diff between two plots Parameters ---------- ax : Axis the matplotlib axis object plot1 : Plot the first plot to compare plot2 : Plot the second plot to compare marker : string the style of the marker to plot linestyle : string the style of the line to plot linewidth : float the width of the line to plot """ logger.log(logging.INFO, "[Graph] Display compare graph") diff = [] compar_dif = [] for ii in range(len(plot1.get_x())): diff.append(abs(plot1.get_y()[ii] - plot2.get_y()[ii])) compar_dif.append(0) label = "Difference between plots" ax.plot(plot1.get_x(), diff, label=label, alpha=0.50, marker=marker, linestyle=linestyle, linewidth=linewidth) ax.plot(plot1.get_x(), compar_dif, alpha=0.50, marker=marker, linestyle=linestyle, linewidth=linewidth) ax.fill_between(plot1.get_x(), diff, compar_dif, color='red', alpha=0.3)
def graph_compare_plot_diff_from_fieldnames(ax, manager, x_fieldname, y_fieldnames, marker=".", linestyle="solid", linewidth=1.5): """ Plot the diff between two plots Parameters ---------- ax : Axis the matplotlib axis object manager : DataManager the data manager used to read data from csv file x_fieldname : str the fieldname of the x-axis variable to plot y_fieldnames : list(str) the list of fieldname of the y-axis variable to plot marker : string the style of the marker to plot linestyle : string the style of the line to plot linewidth : float the width of the line to plot """ plots = PlotCreator.get_instance().plot_from_fieldnames(manager, x_fieldname, y_fieldnames) if len(plots) == 2: graph_compare_plot_diff(ax, plots[0], plots[1], marker, linestyle, linewidth) else: logger.log(logging.ERROR, "[Graph] You can only compare two graphs (" + str(len(plots)) + " given)")
def open_logger_command(self): """ Display or hide the LoggerFrame """ logger.log(logging.INFO, "[MainFrame] Opening Logger frame") if self.__logger_frame is not None: self.__logger_frame.quit() self.__logger_frame = None self.__logger_frame = LoggerFrame(self)
def show_diff_from_fieldnames(self, x_fieldname, y_fieldnames, values=False): """ Plot difference between two graph from fieldnames in a plt matplotlib object Parameters ---------- x_fieldname : str the fieldname of the x-axis variable to plot y_fieldnames : list(str) the list of fieldname of the y-axis variable for the two plot to compare values : boolean display the diff values on the graph """ if self.__data_manager is not None: logger.log( logging.INFO, "[CliHandler] Show from field names " + x_fieldname + " " + str(y_fieldnames)) fig, ax = plt.subplots() graph_clear(ax) graph_compare_plot_from_fieldnames(ax, self.__data_manager, x_fieldname, y_fieldnames) if values: graph_compare_plot_values_from_fieldnames( ax, self.__data_manager, x_fieldname, y_fieldnames, 0.1, True) plt.show() else: logger.log(logging.INFO, "[CliHandler] No data to show")
def graph_from_multiple_data(ax, x_data, y_datas, x_label, y_multiple_label, marker=".", linestyle="solid", linewidth=1.5): """ Plot data in a matplotlib object Parameters ---------- ax : Axis the matplotlib axis object x_data : list(int, float, ...) list of data (x-axis) y_datas : list(list(int, float, ...)) multiple list of data (y-axis) x_label : str the label of the x-axis y_multiple_label : str the list of label of the y-axis marker : string the style of the marker to plot linestyle : string the style of the line to plot linewidth : float the width of the line to plot """ logger.log(logging.INFO, "[Graph] Graph from multiple data") plots_to_display = PlotCreator.get_instance().plot_from_multiple_data(x_data, y_datas, x_label, y_multiple_label) plot(ax, plots_to_display, marker, linestyle, linewidth)
def string_to_function(self, string_function): """ Evaluates the string and returns a function of x Parameters ---------- string_function : str the string to eval Returns ------ func the math function from string """ # find all words and check if all are allowed: for word in re.findall('[a-zA-Z_]+', string_function): if word not in self.__allowed_words: logger.log( logging.INFO, "[PlotCreator] " + word + " is forbidden to use in math expression") raise ValueError( '"{}" is forbidden to use in math expression'.format(word)) for old, new in self.__replacements.items(): string_function = string_function.replace(old, new) def func(x): return eval(string_function) return func
def __create_plot(self, x_data, y_data, x_axis, y_axis, x_unit="", y_unit=""): """ Create a plot Parameters ---------- x_data : list (int, float, ...) list of data (x-axis) y_data : list (int, float, ...) list of data (y-axis) x_axis : str the label of the x-axis y_axis : str the label of the y-axis x_unit : str the unit of the x-axis ("") y_unit : str the unit of the x-axis ("") Returns ------ plot the plot """ plot = Plot(self.__counter, x_data, y_data, x_axis, y_axis, x_unit, y_unit) self.__plots_dict[self.__counter] = plot self.__counter += 1 logger.log(logging.INFO, "[PlotCreator] Create plot " + str(plot)) return plot
def plot_from_data(self, x_data, y_data, x_axis="", y_axis="", x_unit="", y_unit=""): """ Create a plot from data Parameters ---------- x_data : list (int, float, ...) list of data (x-axis) y_data : list (int, float, ...) list of data (y-axis) x_axis : str the label of the x-axis y_axis : str the label of the y-axis x_unit : str the unit of the x-axis ("") y_unit : str the unit of the x-axis ("") Returns ------ plot the plot """ logger.log(logging.INFO, "[PlotCreator] Plot from data") plot = self.__create_plot(x_data, y_data, x_axis, y_axis, x_unit, y_unit) return plot
def show_from_function(self, function, xmin, xmax, discr, xlabel="", ylabel=""): """ Plot mathematic function Parameters ---------- function : str the mathematic function xmin : int the x min xmax : int the x max discr : int the discretization of the interval between xmin and xmax xlabel : str the name of the x label ylabel : str the name of the y label """ logger.log(logging.INFO, "[CliHandler] Plot function " + function) fig, ax = plt.subplots() graph_clear(ax) graph_from_function(ax, function, xmin, xmax, discr, xlabel, ylabel) plt.show()
def clear_data(self): """ Clear data """ logger.log(logging.INFO, "[DataManager] Clear data") self.__fieldnames = [] self.__data_unit = [] self.__data = {} self.__data_values_as_list_tuple = []
def plot_from_fieldnames(self, data_manager, x_data_name, y_data_names): """ Create a list of plots from variable fieldnames Parameters ---------- data_manager : DataManager the data_manager used to read csv file x_data_name : str the name of the x variable y_data_names : list[str] the names of the y variables Returns ------ list(plot) the list of plots """ logger.log(logging.INFO, "[PlotCreator] Plot from multiple fieldnames") plots_list = [] for y_data_name in y_data_names: plot = self.__create_plot( data_manager.get_data_from_field_name(x_data_name), data_manager.get_data_from_field_name(y_data_name), x_data_name, y_data_name, data_manager.get_unit_from_field_name(x_data_name), data_manager.get_unit_from_field_name(y_data_name)) plots_list.append(plot) return plots_list
def refresh_data(self): """ Refresh data from the same data file """ if self.__filename != "": logger.log(logging.INFO, "[DataManager] Refresh data") self.clear_data() self.read_csv_file(self.__filename, self.__reading_options) else: logger.log(logging.INFO, "[DataManager] Cannot refresh data because no data file is defined")
def reset_manager(self): """ Reset the data manager """ logger.log(logging.INFO, "[DataManager] Reset data manager") self.__filename = "" self.__reading_options = {} self.__fieldnames = [] self.__data = {} self.__data_values_as_list_tuple = []
def refresh_file(self): """ Refresh data from the same csv file """ if self.__data_manager.manager_have_data(): logger.log(logging.INFO, "[MainFrame] Refreshing file") self.__data_manager.refresh_data() if self.__csv_frame is not None: self.__csv_frame.fill_data() else: logger.log(logging.ERROR, "[MainFrame] No data to refresh")
def remove_plot(self): """ Remove selected plot from the list """ if self.__plot_list.size() > 0: logger.log(logging.INFO, "[PlotFrame] Remove plot") idxs = self.__plot_list.curselection() for idx in idxs: self.__plot_list.delete(idx) else: logger.log(logging.ERROR, "[PlotFrame] No plot to remove")
def clear_data(self): """ Clear data """ if self.__data_manager is not None: logger.log(logging.INFO, "[MainFrame] Clearing data") self.__data_manager.reset_manager() else: logger.log(logging.ERROR, "[MainFrame] No data to clear") self.__variable1_combo.set('') self.__variable2_combo.set('')
def add_data(self, header, unit, list_values): """ Add new data in data dictionary""" logger.log(logging.INFO, "[DataManager] Add data " + header) self.__fieldnames.append(header) if self.__reading_options['unit'] == 1: self.__data_unit.insert(self.__fieldnames.index(header), unit) self.__data[header] = list_values self.dict_to_list_tuple()
def save_data(self): """ Save data in a CSV file """ file_type = [('csv files', '.csv'), ('out files', '.out'), ('all files', '.*')] file = asksaveasfile(filetypes=file_type, defaultextension=file_type) if file is None: logger.log(logging.ERROR, "[PlotFrame] No save file selected") else: logger.log(logging.INFO, "[MainFrame] Saving data") self.__data_manager.save_csv_file(file.name)
def display_data(self): """ Display csv data in a CsvFrame """ if self.__data_manager.manager_have_data(): logger.log(logging.INFO, "[MainFrame] Displaying data") self.__csv_frame = CsvFrame(self, self.__data_manager) else: logger.log( logging.ERROR, "[MainFrame] Could not display data, data manager does not have data" )
def add_plot_frame(self): """ Creating new plot frame """ plot_frame_id = "Plot frame " + str(self.__counter) plot_frame = PlotFrame(self, plot_frame_id) self.__plot_frame[plot_frame_id] = plot_frame self.__plot_frame_list.append(plot_frame_id) self.__counter += 1 logger.log(logging.INFO, "[MainFrame] Opening Plot frame: " + plot_frame_id)
def read_csv_file(self, filename, options): """ Read a csv file from its file name and options and fill data in dictionary Parameters ---------- filename : str the file name of the csv file options : dict the reading options of the csv file """ self.__filename = filename self.__reading_options = options logger.log(logging.INFO, "[DataManager] " + self.__filename + " " + str(self.__reading_options)) if self.__reading_options['clear']: self.clear_data() counter = 0 with open(self.__filename, 'rU') as infile: # read the file as a dictionary for each row ({header : value}) reader = csv.DictReader(infile, delimiter=self.__reading_options['delimiter'], skipinitialspace=True) if self.__reading_options['header'] == 1: for item in reader.fieldnames: self.__fieldnames.append(item) else: logger.log(logging.ERROR, "[DataManager] CSV error, it is not possible to parse data without header in CSV") return for row in reader: for header, value in row.items(): if counter == 0 and self.__reading_options['unit'] == 1: self.__data_unit.insert(self.__fieldnames.index(header), value) else: try: value_temp = float(value.replace(',', '.')) try: self.__data[header].append(value_temp) except KeyError: logger.log(logging.INFO, "[DataManager] Key error, create new Key: " + header) self.__data[header] = [value_temp] except ValueError: logger.log(logging.ERROR, "[DataManager] Value error: " + value) except AttributeError: logger.log(logging.ERROR, "[DataManager] CSV is badly formatted ") self.clear_data() return counter += 1 self.dict_to_list_tuple()
def graph_add_title(ax, title): """ Add title to the graph Parameters ---------- ax : Axis the matplotlib axis object title : str the title of the graph """ logger.log(logging.INFO, "[Graph] Clear") ax.set_title(title)
def edit_header(self): """ Edit the header a data column """ if self.combo_data.get() != "": answer = simpledialog.askstring("Input", "What is the new header?", parent=self.top) if answer is not None: self.__manager.edit_header(answer, self.combo_data.get()) self.fill_data() self.combo_data.set('') else: logger.log(logging.INFO, "[CsvFrame] No new header entered") else: logger.log(logging.ERROR, "[CsvFrame] No data field selected")
def fill_data(self): """ Fill data in Treeview """ logger.log(logging.INFO, "[CsvFrame] Fill data in TreeView") self.clear_data() self.tree.config(columns=self.__manager.get_field_names()) for field_name in self.__manager.get_field_names(): self.tree.heading(field_name, text=field_name, anchor=tkinter.W) self.tree.column(field_name, stretch=tkinter.YES) for entry in self.__manager.get_data_tuple(): self.tree.insert("", 'end', values=entry)
def create_plot_from_function(self): """ create plot from math functions """ logger.log( logging.INFO, "[FunctionDialog] Creating plot from math function " + self.__entry_function.get()) self.__plot = PlotCreator.get_instance().plot_from_function( self.__entry_function.get(), self.__entry_xmin.get(), self.__entry_xmax.get(), self.__entry_discr.get(), self.__entry_xlabel.get(), self.__entry_ylabel.get()) self.__plot.set_function(str(self.__entry_function.get())) self.quit()
def refresh_plots(self, data_manager): """ Refresh the plots with new data Parameters ---------- data_manager : DataManager the data manager associated to the data """ logger.log(logging.INFO, "[PlotCreator] Refresh plots data") for plot in self.__plots_dict.values(): if plot.get_x_axis() in data_manager.get_field_names() \ and plot.get_y_axis() in data_manager.get_field_names(): plot.set_x( data_manager.get_data_from_field_name(plot.get_x_axis())) plot.set_y( data_manager.get_data_from_field_name(plot.get_y_axis()))
def read_data(self, file_path, options=None): """ Read data from file_path with csv options Parameters ---------- file_path : str the file path to the csv file options : dict the options to read the csv file """ logger.log(logging.INFO, "[CliHandler] Read data from " + file_path) if options is None: options = {'delimiter': ';', 'unit': 1} if self.__file_path: self.__data_manager = DataManager() self.__data_manager.read_csv_file(file_path, options)
def get_data_from_field_name(self, field_name): """ Get data from data field name Parameters ---------- field_name : str the data field name Returns ------ list(float, int, ...) the data of data field name """ if field_name in self.__data: return copy_and_adapt_data(self.__data[field_name]) else: logger.log(logging.ERROR, "[DataManager] Error field name does not exist (get data)") return list()