Files
Helmholtz_Test_Bench/csv_logging.py
Martin Zietz 640d99c9e2 minor UI tweaks
- fixed bug where log data could not be cleared after saving to file
- added description for coil constant in settings page
- minor message tweaks
2021-03-08 18:36:23 +01:00

102 lines
5.1 KiB
Python

# 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 packages
import pandas as pd
from datetime import datetime
import os
from tkinter import filedialog
from tkinter import messagebox
# import other project files
import globals as g
import User_Interface as ui
log_data = pd.DataFrame() # pandas data frame containing the logged data, in-program representation of csv/excel 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() # set reference for timestamps in log file, reset when log_data is cleared and restarted
# 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 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): # logs a single row of data into the log_data DataFrame
# key_list determines what data is logged
global log_data # get global dataframe with logged data
global unsaved_data # get global variable that indicates if there is unsaved data
date = datetime.now().date() # get current date
time = datetime.now().strftime("%H:%M:%S,%f") # get string with current time in correct format
t = (datetime.now() - zero_time).total_seconds() # calculate timestamp relative to the start of the logging
data = [[date, time, t]] # initialize new data row with timestamps
for key in key_list: # go through the list telling us what data to log
for axis in g.AXES: # log this data for each axis
# get relevant value from the correct AXIS object and append to new data row:
data[0].append(getattr(axis, axis_data_dict[key]))
column_names = ["Date", "Time", "t (s)", *triple_list(key_list)] # create list with the correct column headers
new_row = pd.DataFrame(data, columns=column_names) # create data frame containing the new row
log_data = log_data.append(new_row, ignore_index=True) # append the new data frame to the logged data
unsaved_data = True # tell other program parts that there is now unsaved data
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't 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. clearing all logged data