909 lines
52 KiB
Python
909 lines
52 KiB
Python
from PyQt6.QtGui import *
|
|
from PyQt6.QtWidgets import *
|
|
from PyQt6.QtCore import *
|
|
|
|
import multiprocessing
|
|
import multiprocessing.managers
|
|
|
|
import time
|
|
import traceback,sys,os
|
|
import pickle
|
|
import numpy as np
|
|
import pyqtgraph as pg
|
|
|
|
# Get the current script's directory
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
# Get the parent directory by going one level up
|
|
parent_dir = os.path.dirname(current_dir)
|
|
# Add the parent directory to sys.path
|
|
sys.path.append(parent_dir)
|
|
from scripts import import_txt, analyse_cooldown_tools
|
|
from design_files.Analyse_cooldown_design import Ui_MainWindow
|
|
from Raw_data import RawdataWindow
|
|
|
|
|
|
class WorkerSignals(QObject):
|
|
'''
|
|
Defines the signals available from a running worker thread.
|
|
Supported signals are:
|
|
finished: No data
|
|
error: tuple (exctype, value, traceback.format_exc() )
|
|
result: object data returned from processing, anything
|
|
progress: int indicating % progress
|
|
'''
|
|
finished = pyqtSignal()
|
|
error = pyqtSignal(tuple)
|
|
result = pyqtSignal(object)
|
|
progress = pyqtSignal(list)
|
|
|
|
|
|
class Worker(QRunnable):
|
|
'''
|
|
Worker thread
|
|
Inherits from QRunnable to handler worker thread setup, signals and wrap-up.
|
|
:param callback: The function callback to run on this worker thread. Supplied args and
|
|
kwargs will be passed through to the runner.
|
|
:type callback: function
|
|
:param args: Arguments to pass to the callback function
|
|
:param kwargs: Keywords to pass to the callback function
|
|
'''
|
|
|
|
def __init__(self, fn, *args, **kwargs):
|
|
super(Worker, self).__init__()
|
|
|
|
# Store constructor arguments (re-used for processing)
|
|
self.fn = fn
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
self.signals = WorkerSignals()
|
|
|
|
# Add the callback to our kwargs
|
|
self.kwargs['progress_callback'] = self.signals.progress
|
|
|
|
@pyqtSlot()
|
|
def run(self):
|
|
'''
|
|
Initialise the runner function with passed args, kwargs.
|
|
'''
|
|
|
|
# Retrieve args/kwargs here; and fire processing using them
|
|
try:
|
|
result = self.fn(*self.args, **self.kwargs)
|
|
except:
|
|
traceback.print_exc()
|
|
exctype, value = sys.exc_info()[:2]
|
|
self.signals.error.emit((exctype, value, traceback.format_exc()))
|
|
else:
|
|
self.signals.result.emit(result) # Return the result of the processing
|
|
finally:
|
|
self.signals.finished.emit() # Done
|
|
|
|
class cooldown():
|
|
'''Contains the metadata of a cooldown'''
|
|
def __init__(self,times:list, gradient:float, av_gradient:list, loc_gradient:list,
|
|
trans_time:float, rate:list, rate_loc:list, indixes:list, B_start:list,
|
|
B_expelled:list, B_trapped:list, WM:list, good:bool):
|
|
self.times:list = times #list of times: strart_ramp, stop_ramp, save button_pressed
|
|
self.gradient_glob:float = gradient #global gradient obtained between sensor 1 and 8
|
|
self.gradient_average:list = av_gradient #average of all local gradients, second list element is error
|
|
self.gradient_local:list = loc_gradient #list of all local gradients
|
|
self.trans_time:float = trans_time #transition time
|
|
self.rate:list = rate #average cooldown rate of all local cooldown rates with error
|
|
self.rate_local:list = rate_loc #list of all local cooldown rates
|
|
self.indixes:list = indixes #list of indixes at which cernox sensors reach
|
|
self.B_start:list = B_start #start field from fluxgate. List contains four entries: [Bx, By, Bz, |B|]
|
|
self.B_expelled:list = B_expelled #expelled field from AMR senors. List containts 60 entries: [15xBx, 15xBy, 15xBz, 15x|B|]
|
|
self.B_trapped:list = B_trapped #trapped field from AMR senors. List contains 60 entries: [15xBx, 15xBy, 15xBz, 15x|B|]
|
|
self.WM:list = WM #wave magnitude. List contains three entries: [WM_x, WM_y, WM_z]
|
|
self.good:bool = good #whether the cooldown was good or not
|
|
|
|
|
|
def get_float(Qline,default = 0): #gets value from QLineEdit and converts it to float. If text is empty or cannot be converted, it returns "default" which is 0, if not specified
|
|
try:
|
|
out = float(Qline.text())
|
|
except:
|
|
out = default
|
|
return(out)
|
|
|
|
def find_index_of_first_equal_to(lst, value):
|
|
'''Finds the index of the first element in a list that is equal to a given value. Returns -1 if no such element is found.'''
|
|
return next((i for i, x in enumerate(lst) if x == value), np.nan)
|
|
|
|
class MainWindow(QMainWindow, Ui_MainWindow):
|
|
def __init__(self, *args, **kwargs):
|
|
# Get the current script's directory
|
|
self.current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
# Get the parent directory by going one level up
|
|
self.parent_dir = os.path.dirname(current_dir)
|
|
|
|
|
|
#import Gui from QT designer file
|
|
super(MainWindow, self).__init__(*args, **kwargs)
|
|
self.setupUi(self)
|
|
|
|
#setup plot
|
|
self.graphWidget_B.setBackground('w')
|
|
self.graphWidget_B.setTitle("Trapped flux vs. B-field")
|
|
self.graphWidget_B.setLabel('bottom', 'B_y (µT)')
|
|
self.graphWidget_B.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_B.showGrid(x = True, y = True)
|
|
|
|
|
|
self.graphWidget_Gradient.setBackground('w')
|
|
self.graphWidget_Gradient.setTitle("Trapped flux vs. temperature gradient")
|
|
self.graphWidget_Gradient.setLabel('bottom', 'Temperature gradient (K/cm)')
|
|
self.graphWidget_Gradient.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_Gradient.showGrid(x = True, y = True)
|
|
|
|
self.graphWidget_CooldownSpeed.setBackground('w')
|
|
self.graphWidget_CooldownSpeed.setTitle("Trapped flux vs. cooldown speed (K/s)")
|
|
self.graphWidget_CooldownSpeed.setLabel('bottom', 'Cooldown speed (K/s)')
|
|
self.graphWidget_CooldownSpeed.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_CooldownSpeed.showGrid(x = True, y = True)
|
|
|
|
self.graphWidget_transitiontime.setBackground('w')
|
|
self.graphWidget_transitiontime.setTitle("Trapped flux vs. transition time (s)")
|
|
self.graphWidget_transitiontime.setLabel('bottom', 'transition time (s)')
|
|
self.graphWidget_transitiontime.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_transitiontime.showGrid(x = True, y = True)
|
|
|
|
self.graphWidget_WM_x.setBackground('w')
|
|
self.graphWidget_WM_x.setTitle("Wave Amplitude X vs. transition time (K/s)")
|
|
self.graphWidget_WM_x.setLabel('bottom', 'transition time (K/s)')
|
|
self.graphWidget_WM_x.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_WM_x.showGrid(x = True, y = True)
|
|
|
|
self.graphWidget_WM_y.setBackground('w')
|
|
self.graphWidget_WM_y.setTitle("Wave Amplitude Y vs. transition time (K/s)")
|
|
self.graphWidget_WM_y.setLabel('bottom', 'transition time (K/s)')
|
|
self.graphWidget_WM_y.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_WM_y.showGrid(x = True, y = True)
|
|
|
|
self.graphWidget_WM_z.setBackground('w')
|
|
self.graphWidget_WM_z.setTitle("Wave Amplitude Z vs. transition time (K/s)")
|
|
self.graphWidget_WM_z.setLabel('bottom', 'transition time (K/s)')
|
|
self.graphWidget_WM_z.setLabel('left', 'Trapped flux (µT)')
|
|
self.graphWidget_WM_z.showGrid(x = True, y = True)
|
|
|
|
self.graphWidget_free.setBackground('w')
|
|
self.graphWidget_free.setTitle("")
|
|
self.graphWidget_free.setLabel('bottom', '')
|
|
self.graphWidget_free.setLabel('left', '')
|
|
|
|
|
|
pen1 = pg.mkPen(color=(255, 255, 255), width=2)
|
|
# create some dummy data
|
|
x = np.array([0, 1, 2, 3, 4])
|
|
y = np.array([2, 4, 6, 8, 10])
|
|
y_err = np.array([0.5, 1, 1.5, 2, 2.5])
|
|
|
|
# create an error bar item
|
|
self.err_B = pg.ErrorBarItem(x=x, y=y, top=y_err, bottom=y_err, pen=pg.mkPen('k', width=1))
|
|
self.err_Gradient = pg.ErrorBarItem(x=x, y=y, left=y_err, right=y_err, top = y_err, bottom=y_err, pen=pg.mkPen('k', width=1))
|
|
self.err_CooldownSpeed = pg.ErrorBarItem(x=x, y=y, left=y_err, right=y_err, top = y_err, bottom=y_err, pen=pg.mkPen('k', width=1))
|
|
self.err_transitionTime = pg.ErrorBarItem(x=x, y=y, top = y_err, bottom=y_err, pen=pg.mkPen('k', width=1))
|
|
|
|
# add the error bar item to the plot
|
|
self.graphWidget_B.addItem(self.err_B)
|
|
self.graphWidget_Gradient.addItem(self.err_Gradient)
|
|
self.graphWidget_CooldownSpeed.addItem(self.err_CooldownSpeed)
|
|
self.graphWidget_transitiontime.addItem(self.err_transitionTime)
|
|
|
|
# create a scatter plot with markers
|
|
self.scatter_B = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
self.scatter_Gradient = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
self.scatter_CooldownSpeed = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
self.scatter_transitionTime = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
self.scatter_WM_x = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
self.scatter_WM_y = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
self.scatter_WM_z = pg.ScatterPlotItem(x=x, y=y, pen=None, symbol ='x', size=10)
|
|
|
|
# add the scatter plot to the plot
|
|
self.graphWidget_B.addItem(self.scatter_B)
|
|
self.graphWidget_Gradient.addItem(self.scatter_Gradient)
|
|
self.graphWidget_CooldownSpeed.addItem(self.scatter_CooldownSpeed)
|
|
self.graphWidget_transitiontime.addItem(self.scatter_transitionTime)
|
|
self.graphWidget_WM_x.addItem(self.scatter_WM_x)
|
|
self.graphWidget_WM_y.addItem(self.scatter_WM_y)
|
|
self.graphWidget_WM_z.addItem(self.scatter_WM_z)
|
|
|
|
#set up pyQT threadpool
|
|
self.threadpool = QThreadPool()
|
|
|
|
#define signals and slots
|
|
|
|
self.actionSet_default.triggered.connect(self.set_default)
|
|
self.actionReset_default.triggered.connect(self.read_default)
|
|
self.button_refresh_summary.clicked.connect(self.refresh_points_list)
|
|
self.button_refresh_summary.clicked.connect(self.refresh_data_list)
|
|
self.button_refresh_raw.clicked.connect(self.refresh_data_list)
|
|
self.button_refresh_raw.clicked.connect(self.refresh_points_list)
|
|
self.listWidget_files_summary.itemSelectionChanged.connect(self.list_changed)
|
|
self.listWidget_files_raw.itemSelectionChanged.connect(self.list_changed)
|
|
self.button_select_all_summary.clicked.connect(self.select_all)
|
|
self.button_select_all_raw.clicked.connect(self.select_all_raw)
|
|
self.button_select_all_points.clicked.connect(self.select_all_points)
|
|
self.button_clear_points.clicked.connect(self.clear_points)
|
|
self.comboBox_plot_settings.currentIndexChanged.connect(self.set_plot_settings)
|
|
# self.comboBox_select_sensor.currentIndexChanged.connect(self.update_plots)
|
|
# self.line_Plot_B_Field.editingFinished.connect(self.update_plots)
|
|
# self.line_Plot_T_Gradients.editingFinished.connect(self.update_plots)
|
|
# self.line_Plot_B_Field.editingFinished.connect(self.update_plots)
|
|
self.listWidget_points.itemSelectionChanged.connect(self.update_plots)
|
|
self.button_import.clicked.connect(self.import_data)
|
|
self.button_start_analysis.clicked.connect(self.start_analysis)
|
|
self.button_select_good_points.clicked.connect(self.select_good_points)
|
|
self.button_save_cooldowns.clicked.connect(self.save_cooldowns)
|
|
self.button_import_cd.clicked.connect(self.load_cooldowns)
|
|
self.button_update_plots.clicked.connect(self.update_plots)
|
|
self.button_export_points.clicked.connect(self.export_acitve_points)
|
|
|
|
self.dSB_Plot_B_Field_Tolerance.valueChanged.connect(self.set_Tolerances)
|
|
self.dSB_Plot_Cooldown_Speed_Tolerance.valueChanged.connect(self.set_Tolerances)
|
|
self.dSB_Plot_T_Gradients_Tolerance.valueChanged.connect(self.set_Tolerances)
|
|
self.dSB_Plot_Transition_Time_Tolerance.valueChanged.connect(self.set_Tolerances)
|
|
|
|
self.scatter_Gradient.sigClicked.connect(self.find_point_name)
|
|
self.scatter_B.sigClicked.connect(self.find_point_name)
|
|
self.scatter_CooldownSpeed.sigClicked.connect(self.find_point_name)
|
|
self.scatter_transitionTime.sigClicked.connect(self.find_point_name)
|
|
|
|
# self.actionSet_default.triggered.connect(self.set_default)
|
|
# self.actionReset_default.triggered.connect(self.read_default)
|
|
|
|
|
|
|
|
#define constants
|
|
self.w = None #constant to keep track of raw data window
|
|
self.files_selected = [] #list to keep the selected indices of point files. Is needed to keep the same indices aactived after refreshing.
|
|
self.files_selected_raw = [] #list to keep the selected indices of raw files. Is needed to keep the same indices aactived after refreshing.
|
|
self.file_path = 0 #File path for loading calibration
|
|
self.running = True #true while app is running
|
|
self.disable_plot = False #constant to disable plot to improve performance. Is changed by checkbox checkBox_disableplots
|
|
self.select_mean_single = 0 #Select if mean value of all absolute AMR-B-fields or a single sensor should be selected. (0: Mean of abs., 1: Abs. of single sensor, 2: Single sensor direction)
|
|
self.B_Tolerance = 0 #Tolerance when searching for specific B-fields
|
|
self.Gradient_Tolerance = 0 #Tolerance when searching for specific T-Gradients
|
|
self.Cooldown_Speed_Tolerance = 0 #Tolerance when searching for specific Cooldown-Speeds
|
|
self.row_length = 96 #Standard row-length (#columns) of data_array. This value will be updated in import_data
|
|
self.points_list = [] #store all points
|
|
self.cooldowns = {} #store cooldowns
|
|
self.mcol = ["#0072BD","#D95319","#EDB120","#7E2F8E","#77AC30","#4DBEEE","#A2142F","#0072BD","#D95319","#EDB120","#7E2F8E","#77AC30","#4DBEEE","#A2142F"] #define matlab colors
|
|
self.marker = ['x','o','s','t','d','+','p','arrow_up','t1','h','crosshair','t3','star','arrow_down']
|
|
self.dSB_all = [self.dSB_Plot_B_Field_Tolerance, self.dSB_Plot_T_Gradients_Tolerance,
|
|
self.dSB_Plot_Cooldown_Speed_Tolerance, self.dSB_Tc, self.dSB_Tc_top,
|
|
self.dSB_Tc_bottom]#is used for config file
|
|
self.lines_config_strings = [self.line_path_points, self.line_path_data,
|
|
self.line_Plot_B_Field, self.line_Plot_T_Gradients,
|
|
self.line_Plot_Cooldown_Speed, self.line_Plot_Transition_Time]#is used for config file
|
|
self.checkboxes_config = [self.checkBox_C_1, self.checkBox_C__2, self.checkBox_C_3,
|
|
self.checkBox_C_4, self.checkBox_C_5, self.checkBox_C_6,
|
|
self.checkBox_C_7, self.checkBox_C_8, self.checkBox_CRAFT]#is used for config file
|
|
self.combobox_config = [self.comboBox_plot_settings]#is used for config file
|
|
self.decided = True #constant which is set to true after a decision is made whether a cooldown is good or bad. This is needed for self.analyze_cooldown() to know if next cooldown can be analysed
|
|
|
|
|
|
#read default values from config and set them in gui
|
|
self.read_default()
|
|
|
|
#open raw data window
|
|
if self.w is None:
|
|
self.w = RawdataWindow()
|
|
self.w.show()
|
|
|
|
def refresh_points_list(self):
|
|
#imports data from folder and fills list. After it is finished it calls update_plots
|
|
path = self.line_path_points.text()
|
|
try: #if path does not exists nothing is plotted
|
|
files = os.listdir(path)
|
|
except:
|
|
print('Error: Please enter valid path')
|
|
return
|
|
self.data = {}
|
|
selected = self.files_selected #store old selected items so it not overwritten when new data is set in list
|
|
self.listWidget_files_summary.clear()
|
|
|
|
#store data from all files in data
|
|
for p in files:
|
|
# [header,data_arr,times] = import_txt.read_w2dates(path+'\\'+p, '%Y-%m-%d_%H-%M-%S',delim = '\t')
|
|
# self.data[f"{p}"] = [header[0],data_arr,time] #header is list in list, therefore, header[0]
|
|
self.listWidget_files_summary.addItem(f"{p}") #put files in list
|
|
|
|
#fill file list and check the one previously checked
|
|
for i in selected:
|
|
self.listWidget_files_summary.setCurrentIndex(i)
|
|
|
|
if files != []:
|
|
try:
|
|
self.row_length = len(self.data[f"{files[0]}"][1][0,:]) #Update row length (# columns) of data array. Until now its value is 96
|
|
except:
|
|
print("File "+str(files[0])+" is empty.")
|
|
|
|
# if selected != []: #Update plots automatically when refreshing / reloading updated measurements
|
|
# self.update_plots()
|
|
|
|
def refresh_data_list(self):
|
|
#imports data from folder and fills list. After it is finished it calls update_plots
|
|
path = self.line_path_data.text()
|
|
try: #if path does not exists nothing is plotted
|
|
files = os.listdir(path)
|
|
except:
|
|
print('Error: Please enter valid path')
|
|
return
|
|
selected = self.files_selected_raw #store old selected items so it not overwritten when new data is set in list
|
|
self.listWidget_files_raw.clear()
|
|
|
|
#store data from all files in data
|
|
for p in files:
|
|
# [header,data_arr,times] = import_txt.read_w2dates(path+'\\'+p, '%Y-%m-%d_%H-%M-%S',delim = '\t')
|
|
# self.data[f"{p}"] = [header[0],data_arr,time] #header is list in list, therefore, header[0]
|
|
self.listWidget_files_raw.addItem(f"{p}") #put files in list
|
|
|
|
#fill file list and check the one previously checked
|
|
for i in selected:
|
|
self.listWidget_files_raw.setCurrentIndex(i)
|
|
|
|
if files != []:
|
|
try:
|
|
self.row_length = len(self.data[f"{files[0]}"][1][0,:]) #Update row length (# columns) of data array. Until now its value is 96
|
|
except:
|
|
print("File "+str(files[0])+" is empty.")
|
|
|
|
# if selected != []: #Update plots automatically when refreshing / reloading updated measurements
|
|
self.update_plots()
|
|
|
|
def import_data(self):#imports data from selected files
|
|
|
|
#import points from files
|
|
self.points_list = [] #clear list
|
|
for s in self.files_selected:
|
|
path = self.line_path_points.text() + '\\' + s.data()
|
|
[header,data_arr,times] = import_txt.read_w3dates(path, '%Y-%m-%d_%H-%M-%S',delim = '\t')
|
|
self.points_list.extend(times)
|
|
|
|
#import "raw" data from files
|
|
self.data_list = [] #List to store the data of all raw files
|
|
for s in self.files_selected_raw:
|
|
path = self.line_path_data.text() + '\\' + s.data()
|
|
[header,data,times] = import_txt.read_wdate(path,'timestamp',delim=' ')
|
|
boundary_times = [times[0], times[-1]]
|
|
self.data_list.append([times,data,boundary_times])
|
|
|
|
#put start times in point List
|
|
self.listWidget_points.clear()
|
|
for p in self.points_list:
|
|
self.listWidget_points.addItem(f"{p[0]}")
|
|
|
|
def start_analysis(self):
|
|
'''starts self.analyse in a new thread. Is called when "start" button is clicked. '''
|
|
worker_ana = Worker(self.analyse)
|
|
worker_ana.signals.progress.connect(self.update_raw_plots) #The values from analyse must be transmitted via a signal, so that the gui is set in the main thread. If the plots are not updated in the main thread, they freeze.
|
|
self.threadpool.start(worker_ana)
|
|
|
|
def analyse(self,progress_callback):
|
|
'''performes analysis of selected cooldowns and emits signal to start update_raw_plots in main thread. Is started in start_analysis.'''
|
|
points_selected = self.listWidget_points.selectedIndexes()
|
|
#iterate though points
|
|
for p in points_selected:
|
|
ind = p.row() #get point index
|
|
name = p.data()
|
|
name.replace(' ','_')
|
|
times = self.points_list[ind] #get start and stop times from current point
|
|
#select correct data file for the point
|
|
for i,l in enumerate(self.data_list):
|
|
if times[0] >= l[2][0] and times[0] <= l[2][1]: #check if start time of point lies within the boundary times of the data file
|
|
data_ind = i
|
|
break
|
|
#find start and stop indixes in data file and prepare data
|
|
i_start = find_index_of_first_equal_to(self.data_list[data_ind][0], times[0])
|
|
i_stop = find_index_of_first_equal_to(self.data_list[data_ind][0], times[2])+1 #make shure point is included. This is necessary for analyse_B_field.
|
|
|
|
time_slice = self.data_list[data_ind][0][i_start:i_stop]
|
|
data_slice = self.data_list[data_ind][1][i_start:i_stop,:]
|
|
temp_slice = self.data_list[data_ind][1][i_start:i_stop,0:8]
|
|
|
|
#preapre list of active cernox sensors for analysis
|
|
act_sens = [] #list of active sensors
|
|
for i,c in enumerate([self.checkBox_C_1, self.checkBox_C__2, self.checkBox_C_3,
|
|
self.checkBox_C_4, self.checkBox_C_5, self.checkBox_C_6,
|
|
self.checkBox_C_7, self.checkBox_C_8]):
|
|
if c.isChecked() == True:
|
|
act_sens.append(i+1)
|
|
#perform analysis and discern wether CRAFT was used or mVTS. If CRAFT was used, fits need to be performed with the data
|
|
if self.checkBox_CRAFT.isChecked() == False:
|
|
[grad_glob, av_grad_glob, e_av_grad_glob, trans_time, av_rate_glob, e_av_rate_glob,
|
|
grad_loc, rate_loc, indices] = analyse_cooldown_tools.calc_gradient(
|
|
temp_slice,time_slice,act_sens,Tc = self.dSB_Tc.value(),return_indices=True)
|
|
[B_start, B_expelled, B_trapped, WM, indices_B] = analyse_cooldown_tools.analyse_B_field(data_slice, time_slice,times)
|
|
indices.extend(indices_B) #extend indices with indices from analyse_B_field to plot the times at which the fields are measured
|
|
#add cooldown to cooldown dictionary as good cooldown. Whether it is good or bad is updated later in self.accept_points
|
|
self.cooldowns[name] = cooldown(times, grad_glob, [av_grad_glob,e_av_grad_glob], grad_loc,
|
|
trans_time, [av_rate_glob,e_av_rate_glob], rate_loc,
|
|
indices, B_start, B_expelled, B_trapped, WM, True)
|
|
progress_callback.emit([time_slice, data_slice, grad_loc, indices, WM, 0, 0, name])
|
|
else:
|
|
[grad_glob, av_grad_glob, e_av_grad_glob, trans_time, av_rate_glob, e_av_rate_glob,
|
|
grad_loc, rate_loc, indices, popt_T1, popt_T2] = analyse_cooldown_tools.calc_gradient_CRAFT(
|
|
temp_slice,time_slice,act_sens,Tc_top = self.dSB_Tc_top.value(),
|
|
Tc_bottom = self.dSB_Tc_bottom.value(),return_indices=True)
|
|
[B_start, B_expelled, B_trapped, WM, indices_B] = analyse_cooldown_tools.analyse_B_field(data_slice, time_slice,times)
|
|
indices.extend(indices_B) #extend indices with indices from analyse_B_field to plot the times at which the fields are measured
|
|
#add cooldown to cooldown dictionary as good cooldown. Whether it is good or bad is updated later in self.accept_points
|
|
self.cooldowns[name] = cooldown(times, grad_glob, [av_grad_glob,e_av_grad_glob], grad_loc,
|
|
trans_time, [av_rate_glob,e_av_rate_glob], rate_loc,
|
|
indices, B_start, B_expelled, B_trapped, WM, True)
|
|
progress_callback.emit([time_slice, data_slice, grad_loc, indices, WM, popt_T1, popt_T2, act_sens, name])
|
|
|
|
self.decided = False
|
|
#wait until decision is made
|
|
while self.decided == False:
|
|
time.sleep(0.1)
|
|
|
|
def update_raw_plots(self,plot_data):
|
|
'''updates plots in raw plots window. Is called from self.analyse() by
|
|
the emitted signal'''
|
|
#make shure raw window is open
|
|
self.w.show()
|
|
#get T_c, depending on wether CRAFT was used or mVTS
|
|
if self.checkBox_CRAFT.isChecked() == False:
|
|
T_c = self.dSB_Tc.value()
|
|
else:
|
|
T_c = [self.dSB_Tc_top.value(), self.dSB_Tc_bottom.value()]
|
|
#pass data to rawdataWindow and plot it
|
|
self.w.update_plots(plot_data[0],plot_data[1],plot_data[2],plot_data[3],plot_data[4],
|
|
plot_data[5], plot_data[6], plot_data[7], T_c)
|
|
self.accept_points(plot_data[-1])
|
|
|
|
def accept_points(self,name):
|
|
'''Asks the user if a cooldown is good or bad. If Yes, then the cooldown is marked as good. If No, then the cooldown is marked as bad. The method is called after the raw data is plotted'''
|
|
button = QMessageBox.question(self, 'Accept points','Accept depicted point?')
|
|
if button == QMessageBox.StandardButton.Yes:
|
|
self.cooldowns[name].good = True
|
|
else:
|
|
self.cooldowns[name].good = False
|
|
self.decided = True
|
|
|
|
def select_good_points(self):
|
|
'''Selects all cooldowns that have been marked as good'''
|
|
for cd in self.cooldowns:
|
|
item = self.listWidget_points.findItems(cd,Qt.MatchFlag.MatchExactly)[0]
|
|
item.setSelected(self.cooldowns[cd].good)
|
|
|
|
def save_cooldowns(self):
|
|
'''Saves cooldowns to pickle file'''
|
|
fname = QFileDialog.getSaveFileName(self, 'Open file', r'D:',"*.pickle")[0]
|
|
with open(fname, 'wb') as handle:
|
|
pickle.dump(self.cooldowns, handle)
|
|
|
|
def load_cooldowns(self):
|
|
'''Loads cooldowns from pickle file'''
|
|
fname = QFileDialog.getOpenFileName(self, 'Open file', r'D:',"*.pickle")[0]
|
|
with open(fname, 'rb') as handle:
|
|
self.cooldowns.update(pickle.load(handle)) #add cooldowns to existing cooldown dictionary
|
|
|
|
#fill in points list from cooldowns
|
|
self.listWidget_points.clear()
|
|
for cd in self.cooldowns:
|
|
self.listWidget_points.addItem(cd)
|
|
|
|
def list_changed(self):
|
|
#Updates self.files_selected. It is executed when an item in list is selected.
|
|
self.files_selected = self.listWidget_files_summary.selectedIndexes()
|
|
self.files_selected_raw = self.listWidget_files_raw.selectedIndexes()
|
|
|
|
def select_all(self):
|
|
#activates all files refreshes.
|
|
self.listWidget_files_summary.selectAll()
|
|
self.files_selected = self.listWidget_files_summary.selectedIndexes()
|
|
self.refresh_points_list()
|
|
|
|
def select_all_raw(self):
|
|
#activates all files refreshes.
|
|
self.listWidget_files_raw.selectAll()
|
|
self.files_selected_raw = self.listWidget_files_raw.selectedIndexes()
|
|
self.refresh_points_list()
|
|
|
|
def select_all_points(self):
|
|
'''activates all points. If all are already activates, deactivates all'''
|
|
if len(self.listWidget_points.selectedIndexes()) == self.listWidget_points.count():
|
|
self.listWidget_points.clearSelection()
|
|
else:
|
|
self.listWidget_points.selectAll()
|
|
|
|
def clear_points(self):
|
|
'''clears list of points and deletes all cooldowns'''
|
|
self.listWidget_points.clear()
|
|
self.cooldowns = {}
|
|
|
|
def update_plots(self):
|
|
#create list of names of selected points
|
|
names = []
|
|
for i in self.listWidget_points.selectedItems():
|
|
names.append(i.data(0))
|
|
|
|
#create np.arrays of, B_start, gradient, cooldown rate, transition time, B_TF
|
|
B_start = np.empty((len(names),4))
|
|
gradient = np.empty((len(names),2))
|
|
rate = np.empty((len(names),2))
|
|
trans_time = np.empty((len(names),1))
|
|
B_TF = np.empty((len(names),60))
|
|
WM_x = np.empty((len(names)))
|
|
WM_y = np.empty((len(names)))
|
|
WM_z = np.empty((len(names)))
|
|
|
|
for i,n in enumerate(names):
|
|
if self.checkBox_local_gradient.isChecked() == True: #use local or average gradient
|
|
gradient[i,:] = np.array([
|
|
self.cooldowns[n].gradient_local[self.SB_sensor_gradient.value()-1],
|
|
self.cooldowns[n].gradient_average[1]])
|
|
else:
|
|
gradient[i,:] = self.cooldowns[n].gradient_average
|
|
B_start[i,:] = self.cooldowns[n].B_start
|
|
rate[i,:] = self.cooldowns[n].rate
|
|
trans_time[i] = self.cooldowns[n].trans_time
|
|
B_TF[i,:] = self.cooldowns[n].B_trapped
|
|
e_B_TF = np.zeros((len(B_TF))) + 2
|
|
WM_x[i] = self.cooldowns[n].WM[0]
|
|
WM_y[i] = self.cooldowns[n].WM[1]
|
|
WM_z[i] = self.cooldowns[n].WM[2]
|
|
|
|
|
|
#Select trapped flux
|
|
if self.select_mean_single == 0: #Mean of all absolute values (all sensors)
|
|
B_TF = np.mean(B_TF[:,45:], axis = 1)
|
|
elif self.select_mean_single == 1: ##Absolute value of one sensor
|
|
B_TF = B_TF[:,45+self.comboBox_select_sensor.currentIndex()]
|
|
elif self.select_mean_single == 2: #Value of single sensor in one direction
|
|
B_TF = B_TF[:,self.comboBox_select_sensor.currentIndex()]
|
|
|
|
|
|
#find good "beam size" for error bars. Make this 1 percent of the x or y axis
|
|
beam_size_B = (max(B_start[:,1]) - min(B_start[:,1]))/100
|
|
beam_size_gradient = (max(gradient[:,1]) - min(gradient[:,1]))/5
|
|
beam_size_rate = (max(rate[:,1]) - min(rate[:,1]))/5
|
|
beam_size_time = (max(trans_time) - min(trans_time))/100
|
|
|
|
#sort the data according to the three lines and tolerances
|
|
#get lists of sorting values
|
|
B_sort = self.line_Plot_B_Field.text().split(sep=',')
|
|
T_sort = self.line_Plot_T_Gradients.text().split(sep=',')
|
|
S_sort = self.line_Plot_Cooldown_Speed.text().split(sep=',')
|
|
TT_sort = self.line_Plot_Transition_Time.text().split(sep=',')
|
|
if B_sort != ['']:
|
|
B_sort = [float(x) for x in B_sort]
|
|
if T_sort != ['']:
|
|
T_sort = [float(x) for x in T_sort]
|
|
if S_sort != ['']:
|
|
S_sort = [float(x) for x in S_sort]
|
|
if TT_sort != ['']:
|
|
TT_sort = [float(x) for x in TT_sort]
|
|
|
|
sort = [B_sort,T_sort,S_sort,TT_sort]
|
|
tolerances = [self.dSB_Plot_B_Field_Tolerance.value(),self.dSB_Plot_T_Gradients_Tolerance.value(),
|
|
self.dSB_Plot_Cooldown_Speed_Tolerance.value(),self.dSB_Plot_Transition_Time_Tolerance.value()]
|
|
|
|
#sort out data depending on how the lines are filled. If no line has more than one entry, sort out points that do not fall in the tolerances. If one line has more than one entry, create multiple plots. If more than one line has entries, return error.
|
|
ind = []
|
|
lens = I = [len(x) for x in [B_sort,T_sort,S_sort,TT_sort] if len(x) > 1]
|
|
if len(lens) == 0: #no line has more than one entry => only sort out points that do not fall in the tolerances
|
|
for i,n in enumerate(names):
|
|
skip = False #if skip is True, the index will not be appended to ind. Default is False
|
|
point_data = [self.cooldowns[n].B_start[1], self.cooldowns[n].gradient_average[0],
|
|
self.cooldowns[n].rate[0], self.cooldowns[n].trans_time] #get data of the point which will be compared to the sort values.
|
|
for d,s,t in zip(point_data,sort,tolerances): #go through all sorting values, if any condition is not fullfilled the index is not appended to ind
|
|
if s != ['']: #check is the sorting value is not empty. If it is empty, the loop iteration is not skipped
|
|
if abs(d - s[0]) >= t: #check if the point is within the tolerances
|
|
skip = True #only if the point does not fall within the tolerances, skip is set to True and index will not be appended to ind
|
|
|
|
if skip == False:
|
|
ind.append(i) #append index of points that fall in the tolerances
|
|
self.active_points = ind #save indeces of activated points in so it can be used in "find_opint_name" and "export points"
|
|
|
|
#plot data
|
|
#adjust length of e_B_TF
|
|
e_B_TF = e_B_TF[ind]
|
|
|
|
#clear graph widgets and add new plots
|
|
for i,w in enumerate([self.graphWidget_B, self.graphWidget_Gradient,
|
|
self.graphWidget_CooldownSpeed, self.graphWidget_transitiontime,
|
|
self.graphWidget_WM_x, self.graphWidget_WM_y, self.graphWidget_WM_z]):
|
|
w.clear()
|
|
if i == 0: #graph B
|
|
self.scatter_B = pg.ScatterPlotItem(x = B_start[ind,1], y = B_TF[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
err = pg.ErrorBarItem(x = B_start[ind,1], y = B_TF[ind], top = e_B_TF, bottom = e_B_TF, pen=pg.mkPen(color = self.mcol[0], width = 2))
|
|
w.addItem(self.scatter_B)
|
|
self.scatter_B.sigClicked.connect(self.find_point_name)
|
|
elif i == 1: #graph gradient
|
|
self.scatter_Gradient = pg.ScatterPlotItem(x = gradient[ind,0],y = B_TF[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
err = pg.ErrorBarItem(x = gradient[ind,0], y = B_TF[ind], left = gradient[ind,1], right = gradient[ind,1], top = e_B_TF, bottom = e_B_TF, pen=pg.mkPen(color = self.mcol[0], width = 2))
|
|
w.addItem(self.scatter_Gradient)
|
|
self.scatter_Gradient.sigClicked.connect(self.find_point_name)
|
|
elif i == 2: #graph cooldown speed
|
|
self.scatter_CooldownSpeed = pg.ScatterPlotItem(x = rate[ind,0], y = B_TF[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
err = pg.ErrorBarItem(x = rate[ind,0], y = B_TF[ind], left = rate[ind,1], right = rate[ind,1], top = e_B_TF, bottom = e_B_TF, pen=pg.mkPen(color = self.mcol[0], width = 2))
|
|
w.addItem(self.scatter_CooldownSpeed)
|
|
self.scatter_CooldownSpeed.sigClicked.connect(self.find_point_name)
|
|
elif i == 3: #graph transition time
|
|
self.scatter_transitionTime = pg.ScatterPlotItem(x = trans_time[ind,0], y = B_TF[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
err = pg.ErrorBarItem(x = trans_time[ind,0], y = B_TF[ind], top = e_B_TF, bottom = e_B_TF, pen=pg.mkPen(color = self.mcol[0], width = 2))
|
|
w.addItem(self.scatter_transitionTime)
|
|
self.scatter_transitionTime.sigClicked.connect(self.find_point_name)
|
|
elif i == 4: #graph wavemagnitude x
|
|
self.scatter_WM_x = pg.ScatterPlotItem(x = trans_time[ind,0], y = WM_x[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
w.addItem(self.scatter_WM_x)
|
|
self.scatter_WM_x.sigClicked.connect(self.find_point_name)
|
|
continue #do not add errorbaritem to plot
|
|
elif i == 5: #graph wavemagnitude x
|
|
self.scatter_WM_y = pg.ScatterPlotItem(x = trans_time[ind,0], y = WM_y[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
w.addItem(self.scatter_WM_y)
|
|
self.scatter_WM_y.sigClicked.connect(self.find_point_name)
|
|
continue #do not add errorbaritem to plot
|
|
elif i == 6: #graph wavemagnitude x
|
|
self.scatter_WM_z = pg.ScatterPlotItem(x = trans_time[ind,0], y = WM_z[ind], pen=pg.mkPen(color = self.mcol[0]), brush = pg.mkBrush(color = self.mcol[0]), symbol ='x', hoverable = True, size = 10)
|
|
w.addItem(self.scatter_WM_z)
|
|
self.scatter_WM_z.sigClicked.connect(self.find_point_name)
|
|
continue #do not add errorbaritem to plot
|
|
w.addItem(err)
|
|
|
|
|
|
elif len(lens) == 1: #one line has more than one entry. So a set of plots should be generated from this line
|
|
ind_dict = {} #dictionary in which the sorted data will be saved
|
|
labels = [] #list in which labels of plots will be saved
|
|
#find sorting list with more than one entry
|
|
I = [i for i,x in enumerate(sort) if len(x) > 1]
|
|
I = I[0]
|
|
if len(B_sort) > 1:
|
|
for B in B_sort: #Find indices of data points where B = value in B_sort
|
|
ind = [i for i,x in enumerate(B_start[:,1]) if abs(x-B)<tolerances[0]]
|
|
ind_dict[str(B)] = ind
|
|
labels.append(f"B = {B} µT")
|
|
elif len(T_sort) > 1:
|
|
for T in T_sort: #Find indices of data points where Gradient = value in T_sort
|
|
ind = [i for i,x in enumerate(gradient[:,0]) if abs(x-T)<tolerances[1]]
|
|
ind_dict[str(T)] = ind
|
|
labels.append(f"nabla T = {T} K/cm")
|
|
elif len(S_sort) > 1:
|
|
for S in S_sort: #Find indices of data points where cooldownrate = value in S_sort
|
|
ind = [i for i,x in enumerate(rate[:,0]) if abs(x-S)<tolerances[2]]
|
|
ind_dict[str(S)] = ind
|
|
labels.append(f"rate = {S} K/s")
|
|
elif len(TT_sort) > 1:
|
|
for TT in TT_sort: #Find indices of data points where TransitionTime = value in TT_sort
|
|
ind = [i for i,x in enumerate(trans_time[:,0]) if abs(x-TT)<tolerances[3]]
|
|
ind_dict[str(TT)] = ind
|
|
labels.append(f"Transition time = {TT} s")
|
|
|
|
#kick out any points that do not fall in the tolerances of the other lines
|
|
sort.pop(I) #pop out the sorting list with more than one entry wich is already used for sorting
|
|
tolerances.pop(I)
|
|
for key in ind_dict.keys(): #go through all points in ind_dict
|
|
pop=[] #list of indices to be popped out because to do not fit the tolerances
|
|
for i,ind in enumerate(ind_dict[key]):
|
|
point_data = [B_start[ind,1], gradient[ind,0], rate[ind,0], trans_time[ind]]
|
|
point_data.pop(I) #pop out data of sorting list which is already used
|
|
|
|
for d,s,t in zip(point_data,sort,tolerances): #go through all sorting values, if any condition is not fullfilled index is removed from the dictionary
|
|
if s != ['']: #check is the sorting value is not empty. If it is empty, the loop iteration is not skipped
|
|
if abs(d - s[0]) >= t: #check if the point outside the tolerance
|
|
pop.append(i)
|
|
break #get out of loop so no more indices are deleted
|
|
#delete indices that are in pop
|
|
ind_dict[key] = [x for i,x in enumerate(ind_dict[key]) if i not in pop]
|
|
|
|
#clear all graph widgets, add a legend and add new scatter plots
|
|
for i,w in enumerate([self.graphWidget_B, self.graphWidget_Gradient, self.graphWidget_CooldownSpeed, self.graphWidget_transitiontime]):
|
|
w.clear()
|
|
w.addLegend()
|
|
#add new scatter and errorbars to plots
|
|
for n,key in enumerate(ind_dict.keys()):
|
|
if i == 0: #graph B
|
|
scatter = pg.ScatterPlotItem(x = B_start[ind_dict[key],1], y = B_TF[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
err = pg.ErrorBarItem(x = B_start[ind_dict[key],1], y = B_TF[ind_dict[key]], top = e_B_TF[:len(ind_dict[key])], bottom = e_B_TF[:len(ind_dict[key])], pen=pg.mkPen(color = self.mcol[n], width = 2))
|
|
self.graphWidget_B.addItem(scatter)
|
|
self.graphWidget_B.addItem(err)
|
|
if i == 1: #graph gradient
|
|
scatter = pg.ScatterPlotItem(x = gradient[ind_dict[key],0], y = B_TF[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
err = pg.ErrorBarItem(x = gradient[ind_dict[key],0], y = B_TF[ind_dict[key]], top = e_B_TF[:len(ind_dict[key])], bottom = e_B_TF[:len(ind_dict[key])], left = gradient[ind_dict[key],1], right = gradient[ind_dict[key],1], pen=pg.mkPen(color = self.mcol[n], width = 2))
|
|
self.graphWidget_Gradient.addItem(scatter)
|
|
self.graphWidget_Gradient.addItem(err)
|
|
if i == 2: #graph cooldown rate
|
|
scatter = pg.ScatterPlotItem(x = rate[ind_dict[key],0], y = B_TF[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
err = pg.ErrorBarItem(x = rate[ind_dict[key],0], y = B_TF[ind_dict[key]], top = e_B_TF[:len(ind_dict[key])], bottom = e_B_TF[:len(ind_dict[key])], left = rate[ind_dict[key],1], right = rate[ind_dict[key],1], pen=pg.mkPen(color = self.mcol[n], width = 2))
|
|
self.graphWidget_CooldownSpeed.addItem(scatter)
|
|
self.graphWidget_CooldownSpeed.addItem(err)
|
|
if i == 3: #graph transition time
|
|
scatter = pg.ScatterPlotItem(x = trans_time[ind_dict[key],0], y = B_TF[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
err = pg.ErrorBarItem(x = trans_time[ind_dict[key],0], y = B_TF[ind_dict[key]], top = e_B_TF[:len(ind_dict[key])], bottom = e_B_TF[:len(ind_dict[key])], pen=pg.mkPen(color = self.mcol[n], width = 2))
|
|
self.graphWidget_transitiontime.addItem(scatter)
|
|
self.graphWidget_transitiontime.addItem(err)
|
|
if i == 4: #graph transition time
|
|
scatter = pg.ScatterPlotItem(x = trans_time[ind_dict[key],0], y = WM_x[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
self.graphWidget_WM_x.addItem(scatter)
|
|
if i == 5: #graph transition time
|
|
scatter = pg.ScatterPlotItem(x = trans_time[ind_dict[key],0], y = WM_y[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
self.graphWidget_WM_y.addItem(scatter)
|
|
if i == 6: #graph transition time
|
|
scatter = pg.ScatterPlotItem(x = trans_time[ind_dict[key],0], y = WM_z[ind_dict[key]], pen=pg.mkPen(color = self.mcol[n]), brush = pg.mkBrush(color = self.mcol[n]), symbol =self.marker[n], hoverable = True, size = 10, name = labels[n])
|
|
self.graphWidget_WM_z.addItem(scatter)
|
|
|
|
|
|
elif len(lens) > 1:
|
|
print('ERROR: more than one sorting line has more than one entry. Please select only one line with more than one entry. Aborting...')
|
|
return
|
|
|
|
def find_point_name(self, graph, points, ev):
|
|
if len(points) == 1:
|
|
ind = points[0].index()
|
|
selected_points = self.listWidget_points.selectedIndexes()
|
|
I = self.active_points[ind]
|
|
name = selected_points[I].data()
|
|
print(name)
|
|
|
|
def select_data(self, raw_data, B_Array, TF_Array): #selects data for plotting depending on line_Plot_B_Field, line_Plot_T_Gradients, line_Plot_Cooldown_Speed. B_Array needed since one can select specific B_values to be plotted
|
|
|
|
Array_length = len(raw_data) #Array length of raw_data / B_Array / TF_Array
|
|
Array_width = len(raw_data[0,:])
|
|
|
|
#Convert string (of line) into list of floats
|
|
if self.line_Plot_B_Field.text() != '':
|
|
B_select_string = self.line_Plot_B_Field.text().split(",")
|
|
B_select = [float(x) for x in B_select_string]
|
|
else:
|
|
B_select = []
|
|
|
|
if self.line_Plot_T_Gradients.text() != '':
|
|
Gradient_select_string = self.line_Plot_T_Gradients.text().split(",")
|
|
Gradient_select = [float(x) for x in Gradient_select_string]
|
|
else:
|
|
Gradient_select = []
|
|
|
|
if self.line_Plot_Cooldown_Speed.text() != '':
|
|
Cooldown_speed_select_string = self.line_Plot_Cooldown_Speed.text().split(",")
|
|
Cooldown_speed_select = [float(x) for x in Cooldown_speed_select_string]
|
|
else:
|
|
Cooldown_speed_select = []
|
|
|
|
#Create emtpy array / empty list for filtered data as return value
|
|
raw_data_filtered = np.empty(shape=(0,Array_width))
|
|
B_Array_filtered = []
|
|
B_TF_Array_filtered = []
|
|
|
|
for i in range(0,Array_length):
|
|
B = B_Array[i]
|
|
Gradient = raw_data[i,0]
|
|
Cooldown_speed = raw_data[i,2]
|
|
|
|
#Booleans from which ALL have to be True in order to sign one measurement point (row) as filtered one
|
|
Bool1 = True
|
|
Bool2 = True
|
|
Bool3 = True
|
|
|
|
#if selection list isnt empty -> Start filtering
|
|
if B_select != []:
|
|
for B_s in B_select:
|
|
if np.absolute(B - B_s) > self.B_Tolerance:
|
|
Bool1 = False
|
|
|
|
if Gradient_select != []:
|
|
for G_s in Gradient_select:
|
|
if np.absolute(Gradient - G_s) > self.Gradient_Tolerance:
|
|
Bool2 = False
|
|
|
|
if Cooldown_speed_select != []:
|
|
for C_s in Cooldown_speed_select:
|
|
if np.absolute(Cooldown_speed - C_s) > self.Cooldown_Speed_Tolerance:
|
|
Bool3 = False
|
|
|
|
if Bool1 and Bool2 and Bool3: #If all Booleans are True: Measurement point (row) corresponds to filter settings -> Append it to filtered array / lists
|
|
raw_data_filtered = np.append(raw_data_filtered, [raw_data[i,:]], axis=0)
|
|
B_Array_filtered.append(B)
|
|
B_TF_Array_filtered.append(TF_Array[i])
|
|
|
|
return [raw_data_filtered, B_Array_filtered, B_TF_Array_filtered]
|
|
|
|
def set_Tolerances(self):
|
|
#Set tolerance values for filtering
|
|
self.B_Tolerance = self.dSB_Plot_B_Field_Tolerance.value()
|
|
self.Gradient_Tolerance = self.dSB_Plot_T_Gradients_Tolerance.value()
|
|
self.Cooldown_Speed_Tolerance = self.dSB_Plot_Cooldown_Speed_Tolerance.value()
|
|
self.Transition_Time_Tolerance = self.dSB_Plot_Transition_Time_Tolerance.value()
|
|
self.update_plots()
|
|
|
|
def set_plot_settings(self, value):
|
|
#Set plot settings (mean B-value of all AMR-sensors / absolute value of single sensor / single sensor direction)
|
|
self.select_mean_single = value
|
|
|
|
#set the right entries in qComboBox_select_sensor
|
|
if self.select_mean_single == 0: #Mean of all absolute values (all sensors)
|
|
self.comboBox_select_sensor.setEnabled(False)
|
|
self.comboBox_select_sensor.clear()
|
|
|
|
elif self.select_mean_single == 1: #Absolute value of one sensor
|
|
self.comboBox_select_sensor.setEnabled(True)
|
|
self.comboBox_select_sensor.clear()
|
|
|
|
for i in range(1,16): #Add 15 values
|
|
self.comboBox_select_sensor.addItem("Sensor "+str(i))
|
|
|
|
elif self.select_mean_single == 2: #Value of single sensor in one direction
|
|
self.comboBox_select_sensor.setEnabled(True)
|
|
self.comboBox_select_sensor.clear()
|
|
|
|
#Add 45 values
|
|
for direction in ["x", "y", "z"]:
|
|
for i in range(1,16):
|
|
self.comboBox_select_sensor.addItem("Sensor "+str(i) +" "+str(direction))
|
|
|
|
# self.update_plots()
|
|
|
|
def export_acitve_points(self):
|
|
'''creates list of names of points currently displayed and saves this list in a txt file.
|
|
Does not work if multiple plots are displayed'''
|
|
selected_points = self.listWidget_points.selectedIndexes()
|
|
names = [selected_points[i].data() for i in self.active_points]
|
|
fname = QFileDialog.getSaveFileName(self, 'Open file', r'D:',"*.txt")[0]
|
|
with open(fname, 'w') as file:
|
|
for name in names:
|
|
file.write(name + '\n')
|
|
|
|
def nearest_value_in_array(self, array, value): #Returns index of closest entry in array compared to value
|
|
index = (np.abs(array - value)).argmin()
|
|
return(index)
|
|
|
|
def set_default(self):
|
|
#saves current set values to txt file in subdirectory configs. All entries that are saved are defined in self.lines_config
|
|
#Overwrites old values in config file.
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
path = current_dir+'\\configs\\analyse_cooldowns_config.txt' #To make shure the config file is at the right place, independent from where the program is started the location of the file is retrieved
|
|
file = open(path,'w')
|
|
for l in self.dSB_all:
|
|
temp = f"{l.value()}"
|
|
file.write(temp+'\t')
|
|
for l in self.lines_config_strings:
|
|
file.write(l.text()+'\t')
|
|
for c in self.checkboxes_config:
|
|
file.write(str(c.isChecked())+'\t')
|
|
for c in self.combobox_config:
|
|
file.write(str(c.currentIndex())+'\t')
|
|
file.write('\n')
|
|
file.close
|
|
|
|
def read_default(self):
|
|
#reads default values from config file in subdirectory config and sets the values in gui. Then self.change is set to true so values are send
|
|
#to device. (If no config file exists, it does nothing.)
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
path = current_dir+'\\configs\\analyse_cooldowns_config.txt' #To make shure the config file is read from the right place, independent from where the program is started the location of the file is retrieved
|
|
try: #exit function if config file does not exist
|
|
vals = import_txt.read_raw(path)
|
|
except:
|
|
print('no config file found on')
|
|
print(path)
|
|
return
|
|
|
|
for SB,v in zip(self.dSB_all,vals[0]):
|
|
v = float(v) #convert string in txt to float, so number can be formatted according to "formats" when it's set
|
|
SB.setValue(v)
|
|
|
|
for l,v in zip(self.lines_config_strings,vals[0][len(self.dSB_all):]):
|
|
l.setText(v)
|
|
|
|
for c,v in zip(self.checkboxes_config,vals[0][len(self.dSB_all)+len(self.lines_config_strings):]):
|
|
c.setChecked(v == 'True')
|
|
|
|
for c,v in zip(self.combobox_config,vals[0][len(self.dSB_all)+len(self.lines_config_strings)+len(self.checkboxes_config):]):
|
|
c.setCurrentIndex(int(v))
|
|
|
|
self.change = True
|
|
|
|
def closeEvent(self,event): #when window is closed self.running is set to False, so all threads stop
|
|
self.running = False
|
|
self.w = None
|
|
time.sleep(1)
|
|
event.accept()
|
|
|
|
|
|
|
|
app = QApplication(sys.argv)
|
|
|
|
window = MainWindow()
|
|
window.show()
|
|
app.exec() |