# This file contains functions related to logging data from the program to a CSV file # They are mainly but not only called by the ConfigureLogging class in User_Interface.py import pandas as pd import globals as g from datetime import datetime import os from tkinter import filedialog from tkinter import messagebox import User_Interface as ui log_data = pd.DataFrame() # pandas data frame containing logged data unsaved_data = False # Bool to indicate if there is unsaved data, set to True each time a datapoint is logged zero_time = datetime.now() # create dictionary with all value handles that could be logged # Key: String that is displayed in UI and column headers. Also serves as handle to access dictionary elements. # Keys are the same as the rows in the status display ToDo (optional): use this for the status display # Content: name of the corresponding attribute in the Axis class (in cage_func.py). # Important: attribute handle must match definition in Axis class exactly, used with axis.getattr() to get values. axis_data_dict = { 'PSU Status': 'connected', 'Voltage Setpoint': 'voltage_setpoint', 'Actual Voltage': 'voltage', 'Current Setpoint': 'current_setpoint', 'Actual Current': 'current', 'Target Field': 'target_field_comp', 'Trgt. Field Raw': 'target_field_comp', 'Target Current': 'target_current', 'Inverted': 'polarity_switched' } def triple_list(key_list): # creates list with each entry of key_list tripled with axis names before it new_list = [] # initialize list for key in key_list: # go through the given list for axis_name in ['X', 'Y', 'Z']: # per given list entry create three, one for each axis new_list.append(' '.join((axis_name, key))) # put axis_name before the given entry and append to new list return new_list def log_datapoint(key_list): # ToDo: comments global log_data global unsaved_data date = datetime.now().date() time = datetime.now().strftime("%H:%M:%S,%f") t = (datetime.now() - zero_time).total_seconds() data = [[date, time, t]] for key in key_list: for axis in g.AXES: data[0].append(getattr(axis, axis_data_dict[key])) # get value column_names = ["Date", "Time", "t (s)", *triple_list(key_list)] new_row = pd.DataFrame(data, columns=column_names) log_data = log_data.append(new_row, ignore_index=True) unsaved_data = True def select_file(): # select a file to write logs to directory = os.path.abspath(os.getcwd()) # get project directory # open file selection dialogue and save path of selected file filepath = filedialog.asksaveasfilename(initialdir=directory, title="Set log file", filetypes=([("Comma Separated Values", "*.csv*")]), defaultextension=[("Comma Separated Values", "*.csv*")]) if filepath == '': # this happens when file selection window is closed without selecting a file ui.ui_print("No file selected, can not save logged data.") return None else: # a valid file name was entered return filepath def write_to_file(dataframe, filepath): # get global variables for use in this function: global unsaved_data if filepath is not None: # user has selected a file and no errors occurred ui.ui_print("Writing logged data to file", filepath) try: # write data collected in log_data DataFrame to csv file in german excel format: dataframe.to_csv(filepath, index=False, sep=';', decimal=',') except PermissionError: message = "No permission to write to: \n%s. \nFile may be open in another program." % filepath messagebox.showerror("Permission Error", message) except BaseException as e: message = "Error while trying to write to file \n%s.\n%s" % (filepath, e) messagebox.showerror("Error!", message) else: # no exceptions occurred unsaved_data = False # tell everything that there is no unsaved data remaining ui.ui_print("Log data saved to", filepath) def clear_logged_data(): # clears all logged data from data frame global log_data # get global variable log_data = pd.DataFrame() # reset to an empty data frame, i.e. clear all logged data